Skip to content

Instantly share code, notes, and snippets.

@mu578
Last active June 22, 2023 13:52
Show Gist options
  • Save mu578/b7bd9ebd2131c02d73d25f1a6f927751 to your computer and use it in GitHub Desktop.
Save mu578/b7bd9ebd2131c02d73d25f1a6f927751 to your computer and use it in GitHub Desktop.
// C11 Clang Atomic support
# if defined(__clang__)
# if __has_feature(c_atomic)
# define HAVE_CLANG_ATOMICS 1
# endif
# endif
# if defined(__GNUC__) && !defined(HAVE_CLANG_ATOMICS)
# if __GNUC_PREREQ__(4, 7)
# define HAVE_GNUC_ATOMICS 1
# endif
# endif
// Possible _Atomic keyword
// # define _Atomic(T) struct { volatile T value; }
# if defined(HAVE_GNUC_ATOMICS)
# define _Atomic(T) struct { volatile T value; }
# define __c11_atomic_store(obj, desired, order) __atomic_store_n(&(obj)->value, desired, order)
# define __c11_atomic_load(obj, order) __atomic_load_n(&(obj)->value, order)
# define __c11_atomic_exchange(obj, desired, order) __atomic_exchange_n(&(obj)->value, desired, order)
# define __c11_atomic_compare_exchange_strong(obj, expected, desired, success, fail) __atomic_compare_exchange_n(&(obj)->value, expected, desired, 0, success, fail)
# define __c11_atomic_compare_exchange_weak(obj, expected, desired, success, fail) __atomic_compare_exchange_n(&(obj)->value, expected, desired, 1, success, fail)
# define __c11_atomic_fetch_add(obj, value, order) __atomic_fetch_add(&(obj)->value, value, order)
# define __c11_atomic_fetch_sub(obj, value, order) __atomic_fetch_sub(&(obj)->value, value, order)
# define __c11_atomic_fetch_or(obj, value, order) __atomic_fetch_or(&(obj)->value, value, order)
# define __c11_atomic_fetch_xor(obj, value, order) __atomic_fetch_xor(&(obj)->value, value, order)
# define __c11_atomic_fetch_and(obj, value, order) __atomic_fetch_and(&(obj)->value, value, order)
# define __c11_atomic_init(obj, desired) do { (obj)->value = (desired); } while (0)
# define HAVE_CLANG_ATOMICS 1
# elif defined(__GNUC__) && !defined(HAVE_CLANG_ATOMICS)
# define _Atomic(T) struct { volatile T value; }
# define __c11_atomic_store(obj, desired, order) do { __sync_synchronize(); (obj)->value = (desired); __sync_synchronize(); } while (0)
# define __c11_atomic_load(obj, order) __sync_fetch_and_add(&(obj)->value, 0)
# if defined(__clang__)
# if __has_builtin(__sync_swap)
# define __c11_atomic_exchange(obj, desired, order) __sync_swap(&(obj)->value, desired)
# endif
# endif
# if !defined(__c11_atomic_exchange)
# define __c11_atomic_exchange(obj, desired, order) __extension__ ({ __typeof__((obj)->value) v; v = __sync_lock_test_and_set(&(obj)->value, desired); __sync_synchronize(); v; })
# endif
# define __c11_atomic_compare_exchange_strong(obj, expected, desired, success, fail) __extension__ ({ _Bool r; v = __sync_val_compare_and_swap(&(obj)->value, *(expected), desired); r = *(expected) == v; *(expected) = v; r; })
# define __c11_atomic_compare_exchange_weak(obj, expected, desired, success, fail) __extension__ ({ _Bool r; v = __sync_val_compare_and_swap(&(obj)->value, *(expected), desired); r = *(expected) == v; *(expected) = v; r; })
# define __c11_atomic_fetch_add(obj, value, order) __sync_fetch_and_add(&(obj)->value, value)
# define __c11_atomic_fetch_sub(obj, value, order) __sync_fetch_and_sub(&(obj)->value, value)
# define __c11_atomic_fetch_or(obj, value, order) __sync_fetch_and_or(&(obj)->value, value)
# define __c11_atomic_fetch_xor(obj, value, order) __sync_fetch_and_xor(&(obj)->value, value)
# define __c11_atomic_init(obj, desired) do { (obj)->value = (desired); } while (0)
# define HAVE_CLANG_ATOMICS 1
# endif
# if defined(HAVE_CLANG_ATOMICS)
// void atomic_store (volatile A * obj, C desired);
// void atomic_store_explicit (volatile A * obj, C desired, memory_order order);
# define atomic_store(obj, desired) __c11_atomic_store(obj, desired, __ATOMIC_SEQ_CST)
# define atomic_store_explicit(obj, desired, order) __c11_atomic_store(obj, desired, order)
// C atomic_load (const volatile A * obj);
// C atomic_load_explicit (const volatile A * obj, memory_order order);
# define atomic_load(obj) __c11_atomic_load(obj, __ATOMIC_SEQ_CST)
# define atomic_load_explicit(obj, order) __c11_atomic_load(obj, order)
// C atomic_exchange (volatile A * obj, C desired);
// C atomic_exchange_explicit (volatile A * obj, C desired, memory_order order);
# define atomic_exchange(obj, desired) __c11_atomic_exchange(obj, desired, __ATOMIC_SEQ_CST)
# define atomic_exchange_explicit(obj, desired, order) __c11_atomic_exchange(obj, desired, order)
// _Bool atomic_compare_exchange_strong (volatile A * obj, C * expected, C desired);
// _Bool atomic_compare_exchange_strong_explicit (volatile A * obj, C * expected, C desired, memory_order success, memory_order fail);
# define atomic_compare_exchange_strong(obj, expected, desired) __c11_atomic_compare_exchange_strong(obj, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
# define atomic_compare_exchange_strong_explicit(obj, expected, desired, success, fail) __c11_atomic_compare_exchange_strong(obj, expected, desired, success, fail)
// _Bool atomic_compare_exchange_weak (volatile A * obj, C * expected, C desired);
// _Bool atomic_compare_exchange_weak_explicit (volatile A * obj, C * expected, C desired, memory_order success, memory_order fail);
# define atomic_compare_exchange_weak(obj, expected, desired) __c11_atomic_compare_exchange_weak(obj, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
# define atomic_compare_exchange_weak_explicit(obj, expected, desired, success, fail) __c11_atomic_compare_exchange_weak(obj, expected, desired, success, fail)
// C atomic_fetch_add (volatile A * obj, M value);
// C atomic_fetch_add_explicit (volatile A * obj, M value, memory_order order);
# define atomic_fetch_add(obj, value) __c11_atomic_fetch_add(obj, value, __ATOMIC_SEQ_CST)
# define atomic_fetch_add_explicit(obj, value, order) __c11_atomic_fetch_add(obj, value, order)
// C atomic_fetch_sub (volatile A * obj, M value);
// C atomic_fetch_sub_explicit (volatile A * obj, M value, memory_order order);
# define atomic_fetch_sub(obj, value) __c11_atomic_fetch_sub(obj, value, __ATOMIC_SEQ_CST)
# define atomic_fetch_sub_explicit(obj, value, order) __c11_atomic_fetch_sub(obj, value, order)
// C atomic_fetch_or (volatile A * obj, M value);
// C atomic_fetch_or_explicit (volatile A * obj, M value, memory_order order);
# define atomic_fetch_or(obj, value) __c11_atomic_fetch_or(obj, value, __ATOMIC_SEQ_CST)
# define atomic_fetch_or_explicit(obj, value, order) __c11_atomic_fetch_or(obj, value, order)
// C atomic_fetch_xor (volatile A * obj, M value);
// C atomic_fetch_xor_explicit (volatile A * obj, M value, memory_order order);
# define atomic_fetch_xor(obj, value) __c11_atomic_fetch_xor(obj, value, __ATOMIC_SEQ_CST)
# define atomic_fetch_xor_explicit(obj, value, order) __c11_atomic_fetch_xor(obj, value, order)
// C atomic_fetch_and (volatile A * obj, M value);
// C atomic_fetch_and_explicit (volatile A * obj, M value, memory_order order);
# define atomic_fetch_and(obj, value) __c11_atomic_fetch_and(obj, value, __ATOMIC_SEQ_CST)
# define atomic_fetch_and_explicit(obj, value, order) __c11_atomic_fetch_and(obj, value, order)
// Possible atomic_flag type.
// typedef struct atomic_flag { atomic_bool value; } atomic_flag;
// _Bool atomic_flag_test_and_set (volatile atomic_flag * flag);
// _Bool atomic_flag_test_and_set_explicit (volatile atomic_flag * flag, memory_order order);
# define atomic_flag_test_and_set(flag) __c11_atomic_exchange(&(flag)->value, 1, __ATOMIC_SEQ_CST)
# define atomic_flag_test_and_set_explicit(flag, order) __c11_atomic_exchange(&(flag)->value, 1, order)
// void atomic_flag_clear (volatile atomic_flag * flag);
// void atomic_flag_clear_explicit (volatile atomic_flag * flag, memory_order order);
# define atomic_flag_clear(flag) __c11_atomic_store(&(flag)->value, 0, __ATOMIC_SEQ_CST)
# define atomic_flag_clear_explicit(flag, order) __c11_atomic_store(&(flag)->value, 0, order)
// void atomic_init (volatile A * obj, C desired)
# define atomic_init(obj, desired) __c11_atomic_init(obj, desired)
# endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment