diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2021-12-08 13:31:20 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2021-12-08 13:31:20 +0200 |
| commit | 383e55e6bb725a01f652a9fb74f6103b2c789793 (patch) | |
| tree | d5ce2f92a5f5545a2203d4dbfbf9b8fd8caa7584 /include | |
| parent | 5c335752c4fb7e472d68b2b2731c3674a10cbd97 (diff) | |
| download | kmi-383e55e6bb725a01f652a9fb74f6103b2c789793.tar.gz kmi-383e55e6bb725a01f652a9fb74f6103b2c789793.zip | |
Added some C11 atomic operations
Mainly to be used in spinlocks etc.
Diffstat (limited to 'include')
| -rw-r--r-- | include/apos/atomic.h | 184 | ||||
| -rw-r--r-- | include/apos/lock.h | 23 |
2 files changed, 207 insertions, 0 deletions
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 <apos/utils.h> /* 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 */ diff --git a/include/apos/lock.h b/include/apos/lock.h new file mode 100644 index 0000000..b8983fa --- /dev/null +++ b/include/apos/lock.h @@ -0,0 +1,23 @@ +#ifndef LOCK_H +#define LOCK_H + +#include <apos/atomic.h> +typedef atomic_int spinlock_t; + +#include <lock.h> + +static inline void spin_lock(spinlock_t *lck) +{ + do { + while (atomic_load_explicit(lck, memory_order_acquire)) + optional_pause(); + + } while (atomic_exchange_explicit(lck, 1, memory_order_acq_rel)); +} + +static inline void spin_unlock(spinlock_t *lck) +{ + atomic_store_explicit(lck, 0, memory_order_release); +} + +#endif /* LOCK_H */ |
