From 0025f0042f68b664ab9e62ebd0279e0485f3eaa8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 9 Nov 2014 15:12:54 +0100 Subject: [PATCH] atomics: add atomic_compare_exchange_strong() As usual, we use C11 semantics, and emulate it if is not available. It's a bit messy with __sync_val_compare_and_swap(). We assume it has "strong" semantics (it can't fail sporadically), but I'm not sure if this is really the case. On the other hand, weak semantics don't seem to be possible, since the builtin can't distinguish between the two failure cases that could occur. Also, to match the C11 interface, use of gcc builtins is unavoidable. Add a check to the build system to make sure the compiler supports them (although I don't think there's any compiler which supports __sync_*, but not these extensions). Needed for the following commit. --- osdep/atomics.h | 11 +++++++++++ wscript | 1 + 2 files changed, 12 insertions(+) diff --git a/osdep/atomics.h b/osdep/atomics.h index e5fb717a78..39c741acd7 100644 --- a/osdep/atomics.h +++ b/osdep/atomics.h @@ -49,6 +49,9 @@ typedef struct { volatile unsigned long long v; } atomic_ullong; __atomic_store_n(&(p)->v, val, __ATOMIC_SEQ_CST) #define atomic_fetch_add(a, b) \ __atomic_fetch_add(&(a)->v, b, __ATOMIC_SEQ_CST) +#define atomic_compare_exchange_strong(a, b, c) \ + __atomic_compare_exchange_n(&(a)->v, b, c, 0, __ATOMIC_SEQ_CST, \ + __ATOMIC_SEQ_CST) #elif HAVE_SYNC_BUILTINS @@ -58,6 +61,12 @@ typedef struct { volatile unsigned long long v; } atomic_ullong; (__sync_synchronize(), (p)->v = (val), __sync_synchronize()) #define atomic_fetch_add(a, b) \ __sync_fetch_and_add(&(a)->v, b) +// Assumes __sync_val_compare_and_swap is "strong" (using the C11 meaning). +#define atomic_compare_exchange_strong(p, old, new) \ + ({ __typeof__((p)->v) val_ = __sync_val_compare_and_swap(&(p)->v, *(old), new); \ + bool ok_ = val_ == *(old); \ + if (!ok_) *(old) = val_; \ + ok_; }) #else @@ -66,6 +75,8 @@ typedef struct { volatile unsigned long long v; } atomic_ullong; #define atomic_load(p) ((p)->v) #define atomic_store(p, val) ((p)->v = (val)) #define atomic_fetch_add(a, b) (((a)->v += (b)) - (b)) +#define atomic_compare_exchange_strong(p, old, new) \ + ((p)->v == *(old) ? ((p)->v = (new), 1) : (*(old) = (p)->v, 0)) #undef HAVE_ATOMICS #define HAVE_ATOMICS 0 diff --git a/wscript b/wscript index affd261b16..a73c1f1a76 100644 --- a/wscript +++ b/wscript @@ -134,6 +134,7 @@ main_dependencies = [ 'desc': 'compiler support for __sync built-ins', 'func': check_statement('stdint.h', 'int64_t test = 0;' + '__typeof__(test) x = ({int a = 1; a;});' 'test = __sync_add_and_fetch(&test, 1)'), 'deps_neg': [ 'stdatomic', 'atomic-builtins' ], }, {