/* * Provides atomic load and store functions using either native C11 atomic * types and operations if available, or otherwise using fallback * implementations (e.g. with GCC where stdatomic.h is not useable from * Objective-C). * * Adopted from FreeBSD's stdatomic.h. */ #ifndef _GSAtomic_h_ #define _GSAtomic_h_ #ifndef __has_extension #define __has_extension(x) 0 #endif #if __has_extension(c_atomic) || __has_extension(cxx_atomic) /* * Use native C11 atomic operations. _Atomic() should be defined by the * compiler. */ #define atomic_load_explicit(object, order) \ __c11_atomic_load(object, order) #define atomic_store_explicit(object, desired, order) \ __c11_atomic_store(object, desired, order) #else /* * No native support for _Atomic(). Place object in structure to prevent * most forms of direct non-atomic access. */ #define _Atomic(T) struct { T volatile __val; } #if __has_builtin(__sync_swap) /* Clang provides a full-barrier atomic exchange - use it if available. */ #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 before * it. */ #define atomic_exchange_explicit(object, desired, order) \ __extension__ ({ \ __typeof__(object) __o = (object); \ __typeof__(desired) __d = (desired); \ (void)(order); \ __sync_synchronize(); \ __sync_lock_test_and_set(&(__o)->__val, __d); \ }) #endif #define atomic_load_explicit(object, order) \ ((void)(order), __sync_fetch_and_add(&(object)->__val, 0)) #define atomic_store_explicit(object, desired, order) \ ((void)atomic_exchange_explicit(object, desired, order)) #endif #ifndef __ATOMIC_SEQ_CST #define __ATOMIC_SEQ_CST 5 #endif /* * Convenience functions. */ #define atomic_load(object) \ atomic_load_explicit(object, __ATOMIC_SEQ_CST) #define atomic_store(object, desired) \ atomic_store_explicit(object, desired, __ATOMIC_SEQ_CST) #endif // _GSAtomic_h_