x86 instructions: atomic vs non-atomic assignment in C
Andrey Tarasevich
atarasevich@comcast.net
Fri Sep 25 16:33:33 GMT 2026
I see. Thank you.
I presume your answer is intended to state the same thing as Martin's answer. However, I'm a bit perplexed by
the code snippet you supplied. Both variables are declared '_Atomic' in your code. Which means that the
compiler (GCC x86-64 at least) will generate an 'xchg' (with an implied 'lock') in response to a simple
assignment. This is what originally prompted my question. With locked 'xchg' the memory ordering issue you
describe cannot occur, can it? Only if we remove the '_Atomic' qualifiers from your declarations, the compiler
will resort to using 'mov' to implement simple assignment, which has weaker ordering semantics
('memory_order_seq_cst', i.e. just 'release' in this particular case), and which can lead to
different observers seeing different orders of 'x' and 'y' modifications.
Is my above interpretation of your answer correct? Or am I still missing something?
> On 09/25/2026 12:20 AM PDT LIU Hao <lh_mouse@126.com> wrote:
>
>
> 在 2026-9-25 12:12, Andrey Tarasevich via Gcc 写道:
> > My question is: is there a tangible rationale/reason for the difference? I do understand that "memory-immediate operand" version of `mov` instruction is not atomic as a whole. But if I'm not mistaken, the store operation performed by such a `mov` is still perfectly atomic by itself (provided the memory location is aligned correctly). Which means that for the above purposes a plain `mov` would still satisfy the requirements of atomic behavior. Nevertheless, the code generator opts for a separate load into `eax` followed by an atomic `xchg`. Why? Is there a reason to prefer that latter approach? Am I missing something about the `mov` version?
> It's because the builtin assignment operator writes an `_Atomic` object with `memory_order_seq_cst`. Given
>
> // aligned to avoid false sharing
> _Alignas(64) _Atomic int x = 0;
> _Alignas(64) _Atomic int y = 0;
>
> void
> thread_X(void)
> {
> // same as `atomic_store_explicit(&x, 1, memory_order_seq_cst)`
> x = 1;
> }
>
> void
> thread_Y(void)
> {
> // same as `atomic_store_explicit(&y, 1, memory_order_seq_cst)`
> y = 1;
> }
>
>
> The order of the two stores are indeterminate, but all the other threads must see the same; it is not
> allowed that thread foo sees `x == 1` and `y == 0` (not updated yet) but thread bar sees `x == 0` and `y
> == 1`.
>
> And that's why these stores are implemented with XCHG.
>
>
> --
> Best regards,
> LIU Hao
More information about the Gcc
mailing list