Search code examples
c++gccx86-64atomicstdatomic

Is my understanding of __ATOMIC_SEQ_CST correct? (I'd like to write a mutex with it + atomics)


For fun I'm writing my own threading library used by me and a friend or two. First thing I'd like to write is a mutex

It appears I'm generating the assembly I want. __atomic_fetch_add seems to generate lock xadd and __atomic_exchange seems to generate xchg (not cmpxchg). I use both with __ATOMIC_SEQ_CST (for now I'll stick to that)

If I am using __ATOMIC_SEQ_CST will gcc or clang understand these are synchronizing function? If I write lock(); global++; unlock(); will any compilers move global++; before or after the lock/unlock function? Do I need to call __atomic_thread_fence(__ATOMIC_SEQ_CST); or __sync_synchronize(); for any reason? (they seem to do the same thing on x86-64). https://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync seems to suggest my understanding is correct but its easy to misread documentation and I sometimes wonder if scope plays a part in these rules.

I think using those intrinsic the behavior of code in between a lock/unlock will act the same way as a pthread mutex lock/unlock?


Solution

  • If I am using __ATOMIC_SEQ_CST will gcc or clang understand these are synchronizing function?

    Yes, that is the entire reason for these primitives to have memory ordering semantics.

    The memory ordering semantics accomplish two things: (1) ensure that the compiler emits instructions that include the appropriate barriers to prevent reordering by the CPU; (2) ensure that compiler optimizations do not move code past those instructions in ways that the barrier should forbid.

    If I write lock(); global++; unlock(); will any compilers move global++; before or after the lock/unlock function?

    They will not. Again, that is the whole point of being able to specify memory ordering.

    Do I need to call __atomic_thread_fence(__ATOMIC_SEQ_CST); or __sync_synchronize(); for any reason?

    Not in this setting, no.