atomics: more correct usage of gcc/clang __atomic builtins

This should be more correct. The builtins were made to directly map to
C11, and the way we use them is now relatively close to how gcc
implements atomics in 4.9. In particular, we make use of the load and
store builtins.

I'm not entirely sure why gcc didn't support stdatomic.h in 4.8 already.
Maybe support for the builtins was incomplete or broken - so there's a
lot of room for doubt about the correctness of this.
This commit is contained in:
wm4 2014-05-21 01:27:54 +02:00
parent 8e7cf4bc99
commit 885b744767
1 changed files with 16 additions and 12 deletions

View File

@ -38,21 +38,25 @@ typedef struct { volatile unsigned long long v; } atomic_ullong;
#define ATOMIC_VAR_INIT(x) \
{.v = (x)}
#define atomic_load(p) \
(mp_memory_barrier(), (p)->v)
#define atomic_store(p, val) \
((p)->v = (val), mp_memory_barrier())
#if HAVE_ATOMIC_BUILTINS
# define mp_memory_barrier() \
__atomic_thread_fence(__ATOMIC_SEQ_CST)
# define atomic_fetch_add(a, b) \
__atomic_add_fetch(&(a)->v, b, __ATOMIC_SEQ_CST)
#define atomic_load(p) \
__atomic_load_n(&(p)->v, __ATOMIC_SEQ_CST)
#define atomic_store(p, val) \
__atomic_store_n(&(p)->v, val, __ATOMIC_SEQ_CST)
#define atomic_fetch_add(a, b) \
__atomic_fetch_add(&(a)->v, b, __ATOMIC_SEQ_CST)
#elif HAVE_SYNC_BUILTINS
# define mp_memory_barrier() \
__sync_synchronize()
# define atomic_fetch_add(a, b) \
(__sync_add_and_fetch(&(a)->v, b), mp_memory_barrier())
#define atomic_load(p) \
(__sync_synchronize(), (p)->v)
#define atomic_store(p, val) \
((p)->v = (val), __sync_synchronize())
#define atomic_fetch_add(a, b) \
(__sync_add_and_fetch(&(a)->v, b), __sync_synchronize())
#else
# error "this should have been a configuration error, report a bug please"
#endif