According to this https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html,
a released store is implemented as MOV
(into memory) on x86 (including x86-64).
According to his http://en.cppreference.com/w/cpp/atomic/memory_order
memory_order_release:
A store operation with this memory order performs the release operation: no memory accesses in the current thread can be reordered after this store. This ensures that all writes in the current thread are visible in other threads that acquire or the same atomic variable and writes that carry a dependency into the atomic variable become visible in other threads that consume the same atomic.
I understand that when memory_order_release is used, all memory stores done previously should finish before this one.
int a;
a = 10;
std::atomic<int> b;
b.store(50, std::memory_order_release); // i can be sure that 'a' is already 10, so processor can't reorder the stores to 'a' and 'b'
QUESTION: how is it possible that a bare MOV
instruction (without an explicit memory fence) is sufficient for this behaviour? How does MOV
tell the processor to finish all previous stores?
There's memory reordering at run-time (done by CPU) and there's memory reordering at compile-time. Please read Jeff Preshing's article on compile-time reordering (and also great many other good ones on that blog) for further information.
memory_order_release
prevents the compiler from reordering access to data, as well as emitting any necessary fencing or special instructions. In x86 asm, ordinary loads and stores already have acquire / release semantics, so blocking compile-time reordering is sufficient for acq_rel, but not seq_cst.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With