Additions to atomic<T>

155 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

"I asked in the team,"
Thanks. At this point my concern is largely based on aesthetics, because good solutions are often symmetrical and something doesn't feel quite right when comparing with smart pointers (it could also have been just something I ate the night before), but it probably doesn't hurt to at least have a look. With "const T* operator->() const { return *this; }" and "const T& operator*() const { return **this; }", only 6 changes are required (outside of test_atomic.cpp) in the patched version of 2009-04-02 (listed below), so the impact to the already vetted code in TBB is minimal (of course I should probably also investigate why the changes are required, but...). On the other hand, it just occurred to me that to also prevent, e.g., "*apT++=fT();" instead of "*apT=fT(); ++apT;", more radical changes would be required, and I'd much prefer to delegate that (anyone?). Anyway, it's not clear-cut (even if never intended to be a panacea), and it would probably also involve a study of how many mistakes in "real" code would be caught vs. what overhead it would cause elsewhere, etc. So until a more across-the-board protection has been field-tested (lots of hyphens today...) I will just be wondering.

"and we agreed that you probably should not worry, because the case described is covered by atomic*, or atomic*> (atomic pointer to atomic variable) if access to both the pointer itself and the referent should be synchronized."
Well, with the use of atomics you're already concerned about performance, so the first instinct isn't to have double synchronisation. BTW, I don't think you can ever stop worrying: adding some const qualifiers might just help minimally, but even if everything is decreed to have to be sequentially consistent, and verified by automated data flow analysis and other tools (I should probably have a closer look at Dmitriy Vyukov's Relacy Race Detector sometime), the possibilities for failure seem so much less constrained than with single-threaded code. :-)

"As for the atomic itself, its purpose I feel is to provide consistent view of the pointer value across the threads, but not of the referent value. E.g. in the implementation of queuing_mutex, the tail of the queue is an atomic pointer to the scoped_lock node object, and the actual data in that object do not matter much when the node at the tail changes."
queuing_mutex is not concerned: the only changes I had to make were in task.cpp ("my_node.my_next.load()->my_prev = my_node.my_prev;", "my_exception.load()->destroy();" (twice), "s->context_list_head.my_next.load()->my_prev = &my_node;") and concurrent_queue(_v2).cpp ("page& p = *(head_page.load());"); perhaps some of these could use load() instead.

#147 "Also tested successfully on x86-64 (dual core)/Red Hat 5.1/g++ 4.1.2 (both original and patched tbb21_20080925oss seem to have pop_if_present problems in release-build test_concurrent_queue_v2.exe, though)."

Added: in both original and patched tbb21_20080925oss, test_malloc_compliance.exe occasionally fails with "valid pointer returned, error: errno not kept" (caveat: both occasionally failed, but only in the patched version did I identify the cause); I did not compare with tbb21_20090313oss yet because that wouldn't build out of the box ("../../src/tbb/itt_notify_proxy.c:1: sorry, unimplemented: 64-bit mode not compiled in").

Quoting - robert.jay.gould

well the standard does say reinterpret_cast functionality is compiler dependent, so I guess its not a bug in g++, besides g++ has become the aliasing police as of lately, I've encoutered this issue way to many times since I upgraded my g++ compiler.

Kind of out of context( as it's not related with floating points, but with int32 and int64) I'll quote the g++ known bugs/non-bugs docs:

This is often caused by a violation of aliasing rules, which are part of the ISO C standard. These rules say that a program is invalid if you try to access a variable through a pointer of an incompatible type.

The aliasing rules were designed to allow compilers more aggressive optimization. Basically, a compiler can assume that all changes to variables happen through pointers or references to variables of a type compatible to the accessed variable. Dereferencing a pointer that violates the aliasing rules results in undefined behavior.

Now thesolutionto these problems in g++ is described here:

To fix the code above, you can use a union instead of a cast (note that this is a GCC extension which might not work with other compilers):

Which means that it's not easy to have a single code path that will work correctly on all compilers. One option is to compile with-fno-strict-aliasing that will make g++ not cause the aliasing problems.

Guys,

I have been trying to compile ac3 decoder and due to the strict alisaing rules, the ac3 decoder output invalid bitstream when compiler is asked to optimize the code. One of the solutions could be to use char pointers to access memory location (ofcourse then it will have to be accessed byte by byte) because strict aliasing excludes char pointer and any memory location can be accessed by char pointers.

I wanted to ask if there's any new release of IPP that takes care of these strict aliasing rules.

Quoting - rahulmittal321

Guys,

I have been trying to compile ac3 decoder and due to the strict alisaing rules, the ac3 decoder output invalid bitstream when compiler is asked to optimize the code. One of the solutions could be to use char pointers to access memory location (ofcourse then it will have to be accessed byte by byte) because strict aliasing excludes char pointer and any memory location can be accessed by char pointers.

I wanted to ask if there's any new release of IPP that takes care of these strict aliasing rules.

Pages

Leave a Comment

Please sign in to add a comment. Not a member? Join today