diff options
author | Nicolai Hähnle <[email protected]> | 2017-11-03 15:19:57 +0100 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2017-11-09 11:37:30 +0100 |
commit | 0a7f17cf5b591330a257ed0485f759d4e600972c (patch) | |
tree | 70fb2f459b7a55ad711e303463d2218a6ba75cdd /src/util/u_atomic.h | |
parent | b4b2a951c8b4c1315c06cb4d58dbc787949daa4c (diff) |
util/u_atomic: add p_atomic_xchg
The closest to it in the old-style gcc builtins is __sync_lock_test_and_set,
however, that is only guaranteed to work with values 0 and 1 and only
provides an acquire barrier. I also don't know about other OSes, so we
provide a simple & stupid emulation via p_atomic_cmpxchg.
Reviewed-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src/util/u_atomic.h')
-rw-r--r-- | src/util/u_atomic.h | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/src/util/u_atomic.h b/src/util/u_atomic.h index 2a5bbae295b..c6d4bde3439 100644 --- a/src/util/u_atomic.h +++ b/src/util/u_atomic.h @@ -12,6 +12,7 @@ #define U_ATOMIC_H #include <stdbool.h> +#include <stdint.h> /* Favor OS-provided implementations. * @@ -47,6 +48,8 @@ #define p_atomic_add(v, i) (void) __atomic_add_fetch((v), (i), __ATOMIC_ACQ_REL) #define p_atomic_inc_return(v) __atomic_add_fetch((v), 1, __ATOMIC_ACQ_REL) #define p_atomic_dec_return(v) __atomic_sub_fetch((v), 1, __ATOMIC_ACQ_REL) +#define p_atomic_xchg(v, i) __atomic_exchange_n((v), (i), __ATOMIC_ACQ_REL) +#define PIPE_NATIVE_ATOMIC_XCHG #else @@ -220,6 +223,33 @@ #error "No pipe_atomic implementation selected" #endif - +#ifndef PIPE_NATIVE_ATOMIC_XCHG +static inline uint32_t p_atomic_xchg_32(uint32_t *v, uint32_t i) +{ + uint32_t actual = p_atomic_read(v); + uint32_t expected; + do { + expected = actual; + actual = p_atomic_cmpxchg(v, expected, i); + } while (expected != actual); + return actual; +} + +static inline uint64_t p_atomic_xchg_64(uint64_t *v, uint64_t i) +{ + uint64_t actual = p_atomic_read(v); + uint64_t expected; + do { + expected = actual; + actual = p_atomic_cmpxchg(v, expected, i); + } while (expected != actual); + return actual; +} + +#define p_atomic_xchg(v, i) ((__typeof(*(v))) \ + sizeof(*(v)) == sizeof(uint32_t) ? p_atomic_xchg_32((uint32_t *)(v), (uint32_t)(i)) : \ + sizeof(*(v)) == sizeof(uint64_t) ? p_atomic_xchg_64((uint64_t *)(v), (uint64_t)(i)) : \ + (assert(!"should not get here"), 0)) +#endif #endif /* U_ATOMIC_H */ |