From 383e55e6bb725a01f652a9fb74f6103b2c789793 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 8 Dec 2021 13:31:20 +0200 Subject: Added some C11 atomic operations Mainly to be used in spinlocks etc. --- include/apos/atomic.h | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 include/apos/atomic.h (limited to 'include/apos/atomic.h') diff --git a/include/apos/atomic.h b/include/apos/atomic.h new file mode 100644 index 0000000..1b92100 --- /dev/null +++ b/include/apos/atomic.h @@ -0,0 +1,184 @@ +#ifndef ATOMIC_H +#define ATOMIC_H + +#include /* GLUE */ + +typedef enum +{ + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST +} memory_order; + +typedef _Atomic _Bool atomic_bool; +typedef _Atomic char atomic_char; +typedef _Atomic signed char atomic_schar; +typedef _Atomic unsigned char atomic_uchar; +typedef _Atomic short atomic_short; +typedef _Atomic unsigned short atomic_ushort; +typedef _Atomic int atomic_int; +typedef _Atomic unsigned int atomic_uint; +typedef _Atomic long atomic_long; +typedef _Atomic unsigned long atomic_ulong; +typedef _Atomic long long atomic_llong; +typedef _Atomic unsigned long long atomic_ullong; +typedef _Atomic __CHAR16_TYPE__ atomic_char16_t; +typedef _Atomic __CHAR32_TYPE__ atomic_char32_t; +typedef _Atomic __WCHAR_TYPE__ atomic_wchar_t; +typedef _Atomic __INT_LEAST8_TYPE__ atomic_int_least8_t; +typedef _Atomic __UINT_LEAST8_TYPE__ atomic_uint_least8_t; +typedef _Atomic __INT_LEAST16_TYPE__ atomic_int_least16_t; +typedef _Atomic __UINT_LEAST16_TYPE__ atomic_uint_least16_t; +typedef _Atomic __INT_LEAST32_TYPE__ atomic_int_least32_t; +typedef _Atomic __UINT_LEAST32_TYPE__ atomic_uint_least32_t; +typedef _Atomic __INT_LEAST64_TYPE__ atomic_int_least64_t; +typedef _Atomic __UINT_LEAST64_TYPE__ atomic_uint_least64_t; +typedef _Atomic __INT_FAST8_TYPE__ atomic_int_fast8_t; +typedef _Atomic __UINT_FAST8_TYPE__ atomic_uint_fast8_t; +typedef _Atomic __INT_FAST16_TYPE__ atomic_int_fast16_t; +typedef _Atomic __UINT_FAST16_TYPE__ atomic_uint_fast16_t; +typedef _Atomic __INT_FAST32_TYPE__ atomic_int_fast32_t; +typedef _Atomic __UINT_FAST32_TYPE__ atomic_uint_fast32_t; +typedef _Atomic __INT_FAST64_TYPE__ atomic_int_fast64_t; +typedef _Atomic __UINT_FAST64_TYPE__ atomic_uint_fast64_t; +typedef _Atomic __INTPTR_TYPE__ atomic_intptr_t; +typedef _Atomic __UINTPTR_TYPE__ atomic_uintptr_t; +typedef _Atomic __SIZE_TYPE__ atomic_size_t; +typedef _Atomic __PTRDIFF_TYPE__ atomic_ptrdiff_t; +typedef _Atomic __INTMAX_TYPE__ atomic_intmax_t; +typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t; + +#define ATOMIC_VAR_INIT(VALUE) (VALUE) +#define atomic_init(PTR, VAL)\ + atomic_store_explicit(PTR, VAL, __ATOMIC_RELAXED) + +#define kill_dependency(y) (y) + +#if defined(__GNUC__) +#define CMPLR_LOCK_FREE(x) GLUE(__GCC_ATOMIC_, x)##_LOCK_FREE +#elif defined(__clang__) +#define CMPLR_LOCK_FREE(x) GLUE(__CLANG_ATOMIC_, x)##_LOCK_FREE +#endif + +#define ATOMIC_BOOL_LOCK_FREE CMPLR_LOCK_FREE(BOOL) +#define ATOMIC_CHAR_LOCK_FREE CMPLR_LOCK_FREE(CHAR) +#define ATOMIC_CHAR16_T_LOCK_FREE CMPLR_LOCK_FREE(CHAR16_T) +#define ATOMIC_CHAR32_T_LOCK_FREE CMPLR_LOCK_FREE(CHAR32_T) +#define ATOMIC_WCHAR_T_LOCK_FREE CMPLR_LOCK_FREE(WCHAR32_T) +#define ATOMIC_SHORT_LOCK_FREE CMPLR_LOCK_FREE(SHORT) +#define ATOMIC_INT_LOCK_FREE CMPLR_LOCK_FREE(INT) +#define ATOMIC_LONG_LOCK_FREE CMPLR_LOCK_FREE(LONG) +#define ATOMIC_LLONG_LOCK_FREE CMPLR_LOCK_FREE(LLONG) +#define ATOMIC_POINTER_LOCK_FREE CMPLR_LOCK_FREE(POINTER) + +#if defined(__GNUC__) +#define C11_ATOMIC(x) GLUE(__atomic_, x) +#elif defined(__clang__) +#define C11_ATOMIC(x) GLUE(__c11_atomic_, x) +#endif + +/* no libc, so fences aren't used here (unless implemented, but I don't see that + * to be necessary) + * + * void atomic_thread_fence(memory_order); + * void atomic_signal_fence(memory_order); + */ + +#define atomic_thread_fence(order) C11_ATOMIC(thread_fence)(order) +#define atomic_signal_fence(order) C11_ATOMIC(signal_fence)(order) + +#if defined(__GNUC__) +#define atomic_is_lock_free(obj) C11_ATOMIC(is_lock_free)(sizeof(*(obj)), (obj)) +#elif defined(__clang__) +#define atomic_is_lock_free(obj) C11_ATOMIC(is_lock_free)(sizeof(*(obj))) +#endif + +#if defined(__GNUC__) +#define N_ATOMIC(x) GLUE(C11_ATOMIC(x), _n) +#elif defined(__clang__) +#define N_ATOMIC(x) C11_ATOMIC(x) +#endif + +#define atomic_store_explicit(obj, val, mode)\ + N_ATOMIC(store)(obj, val, mode) + +#define atomic_store(obj, val)\ + atomic_store_explicit(obj, val, __ATOMIC_SEQ_CST); + +#define atomic_load_explicit(obj, mode)\ + N_ATOMIC(load)(obj, mode) + +#define atomic_load(obj)\ + atomic_load_explicit(obj, ATOMIC_SEQ_CST) + +#define atomic_exchange_explicit(obj, val, mode)\ + N_ATOMIC(exchange)(obj, val, mode) + +#define atomic_exchange(obj, val)\ + atomic_exchange_explicit(obj, val, __ATOMIC_SEQ_CST) + +#if defined(__GNUC__) +#define atomic_compare_exchange_strong_explicit(obj, val, des, suc, fail)\ + N_ATOMIC(compare_exchange)(obj, val, des, 0, suc, fail) +#elif defined(__clang__) +#define atomic_compare_exchange_strong_explicit(obj, val, des, suc, fail)\ + N_ATOMIC(compare_exchange_strong)(obj, val, des, suc, fail) +#endif + +#define atomic_compare_exchange_strong(obj, val, des)\ + atomic_compare_exchange_strong_explicit\ + (obj, val, des, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) + +#if defined(__GNUC__) +#define atomic_compare_exchange_weak_explicit(obj, val, des, suc, fail)\ + N_ATOMIC(compare_exchange)(obj, val, des, 1, suc, fail) +#elif defined(__clang__) +#define atomic_compare_exchange_weak_explicit(obj, val, des, suc, fail)\ + N_ATOMIC(compare_exchange_weak)(obj, val, des, suc, fail) +#endif + +#define atomic_compare_exchange_weak(obj, val, des)\ + atomic_compare_exchange_weak_explicit\ + (obj, val, des, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) + +#define atomic_fetch_add_explicit(obj, val, mode)\ + C11_ATOMIC(fetch_add)(obj, val, mode) + +#define atomic_fetch_add(obj, val)\ + atomic_fetch_add_explicit(obj, val, __ATOMIC_SEQ_CST) + +#define atomic_fetch_sub_explicit(obj, val, mode)\ + C11_ATOMIC(fetch_sub)(obj, val, mode) + +#define atomic_fetch_sub(obj, val)\ + atomic_fetch_sub_explicit(obj, val, __ATOMIC_SEQ_CST) + +#define atomic_fetch_and_explicit(obj, val, mode)\ + C11_ATOMIC(fetch_and)(obj, val, mode) + +#define atomic_fetch_and(obj, val)\ + atomic_fetch_and_explicit(obj, val, __ATOMIC_SEQ_CST) + +#define atomic_fetch_xor_explicit(obj, val, mode)\ + C11_ATOMIC(fetch_xor)(obj, val, mode) + +#define atomic_fetch_xor(obj, val)\ + atomic_fetch_xor_explicit(obj, val, __ATOMIC_SEQ_CST) + +#define atomic_fetch_or_explicit(obj, val, mode)\ + C11_ATOMIC(fetch_or)(obj, val, mode) + +#define atomic_fetch_or(obj, val)\ + atomic_fetch_or_explicit(obj, val, __ATOMIC_SEQ_CST) + +#define atomic_fetch_nand_explicit(obj, val, mode)\ + C11_ATOMIC(fetch_nand)(obj, val, mode) + +#define atomic_fetch_nand(obj, val)\ + atomic_fetch_nand_explicit(obj, val, __ATOMIC_SEQ_CST) + +/* skip atomic flags, probably not needed */ +#endif /* ATOMIC_H */ -- cgit v1.3