diff options
author | wm4 <wm4@nowhere> | 2014-11-09 15:12:54 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-11-09 15:12:54 +0100 |
commit | 0025f0042f68b664ab9e62ebd0279e0485f3eaa8 (patch) | |
tree | bfa8a6f7fa32b02cbb344025727c9d252db3498f /osdep/atomics.h | |
parent | 5db0fbd95ec8790cd1a133bb57f701c5c9f970c0 (diff) | |
download | mpv-0025f0042f68b664ab9e62ebd0279e0485f3eaa8.tar.bz2 mpv-0025f0042f68b664ab9e62ebd0279e0485f3eaa8.tar.xz |
atomics: add atomic_compare_exchange_strong()
As usual, we use C11 semantics, and emulate it if <stdatomic.h> 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.
Diffstat (limited to 'osdep/atomics.h')
-rw-r--r-- | osdep/atomics.h | 11 |
1 files changed, 11 insertions, 0 deletions
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 |