Can a store-release be reordered with a subsequent sequential-consistent load in C++11?

153 views Asked by At

A store with std::memory_order_release to some location can be reordered with a subsequent load from another location with std::memory_order_acquire.

But can a store with std::memory_order_release to some location be reordered with a subsequent load from another location with std::memory_order_seq_cst?

Analogously, can a store with std::memory_order_seq_cst to a variable be reordered with a subsequent load from another location with std::memory_order_acquire?

Consider this example:

std::atomic<int> x{0};
std::atomic<int> y{0};

void thread1() {
    x.store(std::memory_order_release, 1);
    int r1 = y.load(std::memory_order_seq_cst);
    std::cout << r1 << std::endl;
}

void thread2() {
    y.store(std::memory_order_seq_cst, 1);
    int r2 = x.load(std::memory_order_acquire);
    std::cout << r2 << std::endl;
}

It is well known (http://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/) that if both std::memory_order_seq_cst were replaced by their release/acquire counterpart the output could be two times "0".

Does the sequential-consistency buy anything in this example or can the output still be two times "0"?

1

There are 1 answers

0
levzettelin On BEST ANSWER

No, the sequential-consistency does not buy anything in this example and the output can still be two times "0".

The only difference between std::memory_order_seq_cst and std::memory_order_acquire/release is that std::memory_order_seq_cst-stores may not be reordered with subsequent std::memory_order_seq_cst-loads to different variables/locations, see Herb Sutter's "atomic<> Weapons" talk. (Of course, it may never happen that stores are reordered with subsequent loads to the same variable.)

But, as soon as only one (let alone both) of the memory-orders gets weakened (as is the case in both threads in the example) the StoreLoad reordering may happen. That means, in the example both loads may be reordered before their respective store.

This means that a program that only contains a single std::memory_order_seq_cst and otherwise only std::memory_order_release/acquire remains the same program if one were to replace the lonely std::memory_order_seq_cst by std::memory_order_release (if it is with a store) or a std::memory_order_acquire (if it is with a load).