
All uses of READ_BARRIER or WRITE_BARRIER seem wrong, though. READ_WRITE_BARRIER is needed in all places where these are used.
Why? The intention was to prevent outer reads and writes being reordered with the atomic op. Did I miss something?
The acquire/release semantics are not specific to reads or writes. An acquire load should prevent subsequent writes from being reordered so as to precede it, and a read barrier doesn't do that, I think.
I suppose you're right. I was under impression that _ReadBarrier and _WriteBarrier intrinsics were equivalent to the acquire and release compiler fences but reading their docs now this doesn't seem to be correct. Only _ReadWriteBarrier has the comment that the compiler doesn't reorder operations across it. Thank you, I will correct the code.
It's been quite a while since I had my hands on VC' codegen, but I'm fairly certain the sole purpose of these intrins is to prevent reordering in the compiler. They don't result in any code being emitted directly. I guess, in real-world cases it's rather unlikely to make a difference as there's usually some expression with side-effects in between memory operations or there are volatile accesses. However, these intrinsics are needed to avoided things like redundant-load-after-load optimizations. E.g.: // address-taken globals extern int x; extern int y; void foo() { int lx = x; int ly = y; use(x); sync_operation(); lx = x; use(x); } If use and sync_operation have no side effects, the second load of x would usually be optimized out. The initial load might be ordered after the sync_operation. This is where the _*Barrier intrinsics come in. -hg