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' ], }, {