A codebase has a COMPILER_BARRIER
macro defined as __asm__ volatile("" ::: "memory")
. The intent of the macro is to prevent the compiler from re-ordering reads and writes across the barrier. Note that this is explicitly a compiler barrier, and not a processor level memory barrier.
As is, this is fairly portable since there are no actual assembly instructions in the AssemblerTemplate, just the volatile
and the memory
clobber. So, as long as the compiler honors GCCs Extended Asm syntax, it should work fine. Still, I'm curious what the right way to express this would be in the C++11 atomics API, if possible.
The following seemed like it might be the right idea: atomic_signal_fence(memory_order_acq_rel);
.
My reasoning being that:
<atomic>
APIs, only atomic_signal_fence
and atomic_thread_fence
do not need a memory address against which to operate.atomic_thread_fence
affects memory ordering, which we don't need for a compiler barrier.memory
clobber in the Extended Asm version doesn't distinguish between reads and writes, so it would appear that we want both acquire and release semantics, so memory_order_acq_rel
seems to be required, at minimum.memory_order_seq_cst
seems unnecessary, as we don't require a total order across threads - we are only interested in the instruction sequencing within the current thread.Is it possible to express the equivalent to __asm__ volatile("" ::: "memory")
entirely portably with the C++11 atomics API? If so, is atomic_signal_fence
the correct API to use? If so, what memory order argument is appropriate/required here?
Or, am I off in the weeds here and there is a better way to approach this?
__asm__ volatile("" ::: "memory")
is not even a complete compiler barrier; it only forces ordering of loads/stores to objects whose addresses are potentially accessible to the asm block, which would not include local variables for which the compiler can track that the address does not leak. For example, memset(password, 0, len);
followed by __asm__ volatile("" ::: "memory");
may fail to actually zero the memory used by password[]
.
This can be remedied by passing the addresses of such objects as inputs to the asm block, but I don't see any perfect equivalent with atomic_signal_fence
. The closest you could probably do is storing the address of the object into an external-linkage volatile
pointer object (be careful to make the pointer, not the pointed-to-type, volatile
-qualified) and then atomic_signal_fence
would have to assume it might be accessed from a signal handler.
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