c++memory-barriersstdatomic

Understanding sequential consistency fence in C++


I was reading about memory orders in C++. I could understand relaxed and acquire-release models a well. But I'm struggling with sequential-consistency.

If I am not wrong, from cppreference, std::memory_order_seq_cst 'operation' is equivalent to:

But what is the case with std::memory_order_seq_cst 'fence'? Is it equivalent to which of these?

If it is equivalent to one of above, what about the other two?

As far as I know, if it is case 1 (acquire fence), compilers would be free to move any write operation from above the fence to below it. Similarly, if it is case 2 (release fence), compilers would be free to move any read operation from below the fence to above it. Finally, if it is case 3 (acq-rel fence), compilers would be disallowed to move any instructions across the fence. Is this correct?

I'm still in a lot of confusion. Above statements may be incorrect. Please correct me where I'm wrong.


Solution

  • In short, it's case 3.

    A seq_cst fence includes all the functionality of an acq_rel fence. See [atomics.fences p5.5]:

    is a sequentially consistent acquire and release fence, if order == memory_order::seq_cst.

    So in particular it is an acquire and release fence. And it is also a sequentially consistent fence, meaning that it is included in the total order S defined in [atomics.order p4], in a manner consistent with the rules stated there.

    The formal C++ memory model does not have a concept of "reordering". However, you are right that a typical implementation of a seq_cst fence would be one which prevents loads and stores from being reordered across it in either direction. Note that this is strictly stronger than an acq_rel fence, which would permit a store before the fence to be reordered with a load after the fence (StoreLoad reordering).