Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does memory_order_seq_cst synchronize with non-atomic operations?

If one uses a single atomic variable and std::memory_order_seq_cst, are non-atomic operations guaranteed not to be reordered?

For example, if I have

std::atomic<bool> quux = {false};

void foo() {
    bar();
    quux.store(true, std::memory_order_seq_cst);
    moo();
}

is bar() guaranteed not to get reordered after the call of store, and moo() not to get reordered before the call of store, as long as I use std::memory_order_seq_cst, at least from the perspective of another thread?

Or, to put it in code, are the following assumptions valid if run from another thread?

if(quux.load(std::memory_order_seq_cst) == true) {
   // bar guaranteed to be called; its side-effects are visible
   // moo might have been called, but is not guaranteed to
} else {
   // bar might have been called, but is not guaranteed to
   // moo might have been called, but is not guaranteed to
}

Note that I assume that neither bar nor moo use atomic operations, mutexes, locks, fences or other synchronization features.

like image 636
Zeta Avatar asked Oct 18 '22 20:10

Zeta


2 Answers

According to the link http://en.cppreference.com/w/cpp/atomic/memory_order linked by @Maxim there is an error with regards of the memory_order_seq_cst.The text above is exchanged with memory_order_acq_rel. The text for memory_order_seq_cst:

memory_order_seq_cst: A load operation with this memory order performs an acquire operation, a store performs a release operation, and read-modify-write performs both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order (see Sequentially-consistent ordering below)

So in your case the store operation is equivalent to a release which means that moo() can be reordered before the fence.

like image 98
Minee Avatar answered Oct 21 '22 07:10

Minee


If one uses a single atomic variable and std::memory_order_seq_cst, are non-atomic operations guaranteed not to be reordered?

The standard is pretty clear on this http://en.cppreference.com/w/cpp/atomic/memory_order:

memory_order_seq_cst A load operation with this memory order performs an acquire operation, a store performs a release operation, and read-modify-write performs both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order.

memory_order_acquire A load operation with this memory order performs the acquire operation on the affected memory location: no reads or writes in the current thread can be reordered before this load.

memory_order_release A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store.

In other words, no loads or stores (both non-atomic and atomic) can be reordered around memory_order_seq_cst operations.


is bar() guaranteed not to get reordered after the call of store, and moo() not to get reordered before the call of store, as long as I use std::memory_order_seq_cst, at least from the perspective of another thread?

If the definitions of bar and moo are not available in the current translation unit, the compiler assumes that these functions do memory loads and/or have side effects (do I/O or stores to memory), and hence cannot be reordered around memory_order_seq_cst operations.

If the definitions are available and the functions do not do I/O or memory loads/stores then they can be reordered. These would be pure functions or functions that do nothing and return void or a constant.

like image 25
Maxim Egorushkin Avatar answered Oct 21 '22 08:10

Maxim Egorushkin