On 2/10/22 18:18, Jinoh Kang wrote:
> GCC, clang, and other compilers do not actually provide acquire/release
> semantics on volatile memory accesses. This is also true on MSVC with
> the /volatile:iso (use strict ISO C semantics for volatile accesses)
> flag.
>
> Consider the following test program:
>
> void func(int *foo, volatile int *bar)
> {
> *foo = 1;
> *bar = 2; /* NOTE: *not* immune to reordering! */
> *foo = 3;
> }
>
> After store reordering and dead code removal, the function above
> compiles into the following x86-64 assembly on GCC 11.2 (gcc -O2):
>
> movl $2, (%rsi)
> movl $3, (%rdi)
> ret
>
> Note that the first write to "*foo" has been ellided; the compiler
> decided that it is safe to reorder writes to "*foo" around writes to the
> volatile variable "*bar", so it simply merged the first "*foo" write
> into the second one.
>
> Fix this by explicitly specifying a compiler memory barrier before the
> atomic store. As a workaround for GCC bug #81316, we do this even for
> other architectures where we explicitly use the atomic memory access
> builtin.
>
FWIW I believe that the only thing that matters for these helpers and
where they are used (to write to user shared data section) is that the
ordering is guaranteed between the volatile stores, not really with
other load or stores on non-volatile data around them. This should be
the case.
Then maybe they shouldn't be named atomic, because they aren't. Or, if
we really want to fix the semantics here, maybe we should just use the
__atomic intrinsics everywhere. The concern was the compatibility with
older GCC or non-GCC compilers, and I don't think they are much less
portable than inline assembly at this point.
We still support GCC 4.x (an in-support RHEL/CentOS release uses it), so I think we still need some wrappers around it. That and the GCC bug.