diff options
author | tijl <tijl@FreeBSD.org> | 2012-09-26 19:49:22 +0000 |
---|---|---|
committer | tijl <tijl@FreeBSD.org> | 2012-09-26 19:49:22 +0000 |
commit | 0d4a7769ee242da1cfca4c55dffedafd8a656c27 (patch) | |
tree | 873092856974775594664ff0b87e42bd187adc77 /include/stdatomic.h | |
parent | 95d0e5a41c0eb872db91f775722408ca5411b19d (diff) | |
download | FreeBSD-src-0d4a7769ee242da1cfca4c55dffedafd8a656c27.zip FreeBSD-src-0d4a7769ee242da1cfca4c55dffedafd8a656c27.tar.gz |
- Make C11 atomic macros usable in expressions:
- Replace do-while statements with void expressions.
- Wrap __asm statements in statement expressions.
- Make the macros function-like:
- Evaluate all arguments exactly once.
- Make sure there's a sequence point between evaluation of the arguments
and the function body. Arguments should be evaluated before any memory
barriers.
- Fix use of __atomic_is_lock_free built-in. It requires the address of
an atomic variable as second argument. Use this built-in on clang as
well because clang's __c11_atomic_is_lock_free only takes the size of the
variable into account.
- In atomic_exchange_explicit put the barrier before instead of after the
__sync_lock_test_and_set call.
Reviewed by: theraven
Diffstat (limited to 'include/stdatomic.h')
-rw-r--r-- | include/stdatomic.h | 58 |
1 files changed, 33 insertions, 25 deletions
diff --git a/include/stdatomic.h b/include/stdatomic.h index b9f5204..392ae67 100644 --- a/include/stdatomic.h +++ b/include/stdatomic.h @@ -54,9 +54,7 @@ #define atomic_init(obj, value) __c11_atomic_init(obj, value) #else #define ATOMIC_VAR_INIT(value) { .__val = (value) } -#define atomic_init(obj, value) do { \ - (obj)->__val = (value); \ -} while (0) +#define atomic_init(obj, value) ((void)((obj)->__val = (value))) #endif /* @@ -111,23 +109,24 @@ enum memory_order { #define atomic_thread_fence(order) __atomic_thread_fence(order) #define atomic_signal_fence(order) __atomic_signal_fence(order) #else -#define atomic_thread_fence(order) __sync_synchronize() -#define atomic_signal_fence(order) __asm volatile ("" : : : "memory") +#define atomic_thread_fence(order) ((void)(order), __sync_synchronize()) +#define atomic_signal_fence(order) __extension__ ({ \ + (void)(order); \ + __asm volatile ("" ::: "memory"); \ + (void)0; \ +}) #endif /* * 7.17.5 Lock-free property. */ -#if defined(__CLANG_ATOMICS) -#define atomic_is_lock_free(obj) \ - __c11_atomic_is_lock_free(sizeof(obj)) -#elif defined(__GNUC_ATOMICS) +#if defined(__CLANG_ATOMICS) || defined(__GNUC_ATOMICS) #define atomic_is_lock_free(obj) \ - __atomic_is_lock_free(sizeof((obj)->__val)) + __atomic_is_lock_free(sizeof((obj)->__val), &(obj)->val) #else #define atomic_is_lock_free(obj) \ - (sizeof((obj)->__val) <= sizeof(void *)) + ((void)(obj), sizeof((obj)->__val) <= sizeof(void *)) #endif /* @@ -234,13 +233,17 @@ typedef _Atomic(__uintmax_t) atomic_uintmax_t; __atomic_store_n(&(object)->__val, desired, order) #else #define atomic_compare_exchange_strong_explicit(object, expected, \ - desired, success, failure) ({ \ + desired, success, failure) __extension__ ({ \ __typeof__((object)->__val) __v; \ + __typeof__(expected) __e; \ _Bool __r; \ + __e = (expected); \ + (void)(success); \ + (void)(failure); \ __v = __sync_val_compare_and_swap(&(object)->__val, \ - *(expected), desired); \ - __r = *(expected) == __v; \ - *(expected) = __v; \ + *__e, (desired)); \ + __r = (*__e == __v); \ + *__e = __v; \ __r; \ }) @@ -250,19 +253,21 @@ typedef _Atomic(__uintmax_t) atomic_uintmax_t; desired, success, failure) #if __has_builtin(__sync_swap) /* Clang provides a full-barrier atomic exchange - use it if available. */ -#define atomic_exchange_explicit(object, desired, order) \ - __sync_swap(&(object)->__val, desired) +#define atomic_exchange_explicit(object, desired, order) \ + ((void)(order), __sync_swap(&(object)->__val, desired)) #else /* * __sync_lock_test_and_set() is only an acquire barrier in theory (although in - * practice it is usually a full barrier) so we need an explicit barrier after + * practice it is usually a full barrier) so we need an explicit barrier before * it. */ -#define atomic_exchange_explicit(object, desired, order) ({ \ - __typeof__((object)->__val) __v; \ - __v = __sync_lock_test_and_set(&(object)->__val, desired); \ +#define atomic_exchange_explicit(object, desired, order) \ +__extension__ ({ \ + __typeof__(object) __o = (object); \ + __typeof__(desired) __d = (desired); \ + (void)(order); \ __sync_synchronize(); \ - __v; \ + __sync_lock_test_and_set(&(__o)->__val, __d); \ }) #endif #define atomic_fetch_add_explicit(object, operand, order) \ @@ -277,11 +282,14 @@ typedef _Atomic(__uintmax_t) atomic_uintmax_t; __sync_fetch_and_xor(&(object)->__val, operand) #define atomic_load_explicit(object, order) \ __sync_fetch_and_add(&(object)->__val, 0) -#define atomic_store_explicit(object, desired, order) do { \ +#define atomic_store_explicit(object, desired, order) __extension__ ({ \ + __typeof__(object) __o = (object); \ + __typeof__(desired) __d = (desired); \ + (void)(order); \ __sync_synchronize(); \ - (object)->__val = (desired); \ + __o->__val = __d; \ __sync_synchronize(); \ -} while (0) +}) #endif /* |