vendredi 22 juillet 2022

Does C++ provide a complete set of membars?

Acquire-release memory ordering provides a way to create a partial ordering of surrounding operations between two points in the program. This memory ordering inhibits reordering of instructions or memory operations (maybe partially) across this barrier. This essentially guarantees some synchronization across various marked points. But this is just a pairwise relationship and there is no total ordering guarantee. There are four values: relaxed, acquire, release, acq-rel.

Sequential-consistency property guarantees a total ordering of memory at various points in the program. Just plain sequential consistency property does not inhibit any kind of instruction reordering or memory reordering. It just ensures that, marked instructions or memory operations happens in a global order. But this does not give any guarantees about surrounding instructions(?). There are two values: not-cst, seq-cst.

I'm not sure if there are any other types of membars or other ways to categorize them. Wherever I see, I only see these barriers. So I intuitively listed them like above.

Now, by combining acquire-release ordering with sequential consistency property, we can create many kinds of barriers (at least on paper):

LOAD:          (C++ std::atomic_load)
relaxed                          (C++ std::memory_order_relaxed)
relaxed with seq-consist         (C++ ?)
acquire                          (C++ std::memory_order_acquire)
acquire with seq-consist         (C++ std::memory_order_seq_cst)
STORE:         (C++ std::atomic_store)
relaxed                          (C++ std::memory_order_relaxed)
relaxed with seq-consist         (C++ ?)
release                          (C++ std::memory_order_release)
release with seq-consist         (C++ std::memory_order_seq_cst)
EXCHANGE:      (C++ std::atomic_exchange)
relaxed                          (C++ std::memory_order_relaxed)
relaxed with seq-consist         (C++ ?)
acquire                          (C++ std::memory_order_acquire)
acquire with seq-consist         (C++ ?)
release                          (C++ std::memory_order_release)
release with seq-consist         (C++ ?)
acq-rel                          (C++ std::memory_order_acq_rel)
acq-rel with seq-consist         (C++ std::memory_order_seq_cst)
FENCE:         (C++ std::atomic_thread_fence)
acquire                          (C++ std::memory_order_acquire)
acquire with seq-consist         (C++ ?)
release                          (C++ std::memory_order_release)
release with seq-consist         (C++ ?)
acq-rel                          (C++ std::memory_order_acq_rel)
acq-rel with seq-consist         (C++ std::memory_order_seq_cst)

In the table, there are some missing values (relaxed_seq_cst load, stores; acquire_seq_cst and release_seq_cst fences; etc). Are they redundant? Or are they harder to use correctly / debug? Or it is left out just to reduce complexity in the library?

Aucun commentaire:

Enregistrer un commentaire