164 lines
6.7 KiB
C
164 lines
6.7 KiB
C
// SPDX-License-Identifier: ISC
|
|
#pragma once
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
typedef enum memory_order {
|
|
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;
|
|
|
|
#define atomic_thread_fence(order) __atomic_thread_fence(order)
|
|
#define atomic_signal_fence(order) __atomic_signal_fence(order)
|
|
|
|
#ifdef __clang__
|
|
|
|
#define atomic_init(obj, value) __c11_atomic_init(obj, value)
|
|
|
|
#define atomic_store_explicit(obj, val, order) __c11_atomic_store(obj, val, order)
|
|
#define atomic_load_explicit(obj, order) __c11_atomic_load(obj, order)
|
|
|
|
#define atomic_exchange_explicit(obj, val, order) __c11_atomic_exchange(obj, val, order)
|
|
|
|
#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail) \
|
|
__c11_atomic_compare_exchange_strong(obj, expected, desired, succ, fail)
|
|
#define atomic_compare_exchange_weak_explicit(obj, expected, desired, succ, fail) \
|
|
__c11_atomic_compare_exchange_weak(obj, expected, desired, succ, fail)
|
|
|
|
#define atomic_fetch_add_explicit(obj, arg, order) __c11_atomic_fetch_add(obj, arg, order)
|
|
#define atomic_fetch_sub_explicit(obj, arg, order) __c11_atomic_fetch_sub(obj, arg, order)
|
|
#define atomic_fetch_or_explicit(obj, arg, order) __c11_atomic_fetch_or(obj, arg, order)
|
|
#define atomic_fetch_xor_explicit(obj, arg, order) __c11_atomic_fetch_xor(obj, arg, order)
|
|
#define atomic_fetch_and_explicit(obj, arg, order) __c11_atomic_fetch_and(obj, arg, order)
|
|
|
|
#define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj)))
|
|
|
|
#else /* GCC */
|
|
|
|
#define atomic_init(obj, value) \
|
|
do { \
|
|
*(obj) = (value); \
|
|
} while (0)
|
|
|
|
#define atomic_store_explicit(obj, val, order) \
|
|
({ \
|
|
auto __ao = (obj); \
|
|
typeof(*__ao) __av = (val); \
|
|
__atomic_store(__ao, &__av, order); \
|
|
})
|
|
|
|
#define atomic_load_explicit(obj, order) \
|
|
({ \
|
|
auto __ao = (obj); \
|
|
typeof(*__ao) __ar; \
|
|
__atomic_load(__ao, &__ar, order); \
|
|
__ar; \
|
|
})
|
|
|
|
#define atomic_exchange_explicit(obj, val, order) \
|
|
({ \
|
|
auto __ao = (obj); \
|
|
typeof(*__ao) __av = (val); \
|
|
typeof(*__ao) __ar; \
|
|
__atomic_exchange(__ao, &__av, &__ar, order); \
|
|
__ar; \
|
|
})
|
|
|
|
#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, fail) \
|
|
({ \
|
|
auto __ao = (obj); \
|
|
auto __ae = (expected); \
|
|
typeof(*__ao) __ad = (desired); \
|
|
__atomic_compare_exchange(__ao, __ae, &__ad, 0, succ, fail); \
|
|
})
|
|
|
|
#define atomic_compare_exchange_weak_explicit(obj, expected, desired, succ, fail) \
|
|
({ \
|
|
auto __ao = (obj); \
|
|
auto __ae = (expected); \
|
|
typeof(*__ao) __ad = (desired); \
|
|
__atomic_compare_exchange(__ao, __ae, &__ad, 1, succ, fail); \
|
|
})
|
|
|
|
#define atomic_fetch_add_explicit(obj, arg, order) __atomic_fetch_add(obj, arg, order)
|
|
#define atomic_fetch_sub_explicit(obj, arg, order) __atomic_fetch_sub(obj, arg, order)
|
|
#define atomic_fetch_or_explicit(obj, arg, order) __atomic_fetch_or(obj, arg, order)
|
|
#define atomic_fetch_xor_explicit(obj, arg, order) __atomic_fetch_xor(obj, arg, order)
|
|
#define atomic_fetch_and_explicit(obj, arg, order) __atomic_fetch_and(obj, arg, order)
|
|
|
|
#define atomic_is_lock_free(obj) __atomic_is_lock_free(sizeof(*(obj)), (obj))
|
|
|
|
#endif
|
|
|
|
#define atomic_store(obj, val) atomic_store_explicit(obj, val, memory_order_seq_cst)
|
|
#define atomic_load(obj) atomic_load_explicit(obj, memory_order_seq_cst)
|
|
|
|
#define atomic_exchange(obj, val) atomic_exchange_explicit(obj, val, memory_order_seq_cst)
|
|
|
|
#define atomic_compare_exchange_strong(obj, expected, desired) \
|
|
atomic_compare_exchange_strong_explicit(obj, expected, desired, memory_order_seq_cst, memory_order_seq_cst)
|
|
#define atomic_compare_exchange_weak(obj, expected, desired) \
|
|
atomic_compare_exchange_weak_explicit(obj, expected, desired, memory_order_seq_cst, memory_order_seq_cst)
|
|
|
|
#define atomic_fetch_add(obj, arg) atomic_fetch_add_explicit(obj, arg, memory_order_seq_cst)
|
|
#define atomic_fetch_sub(obj, arg) atomic_fetch_sub_explicit(obj, arg, memory_order_seq_cst)
|
|
#define atomic_fetch_or(obj, arg) atomic_fetch_or_explicit(obj, arg, memory_order_seq_cst)
|
|
#define atomic_fetch_xor(obj, arg) atomic_fetch_xor_explicit(obj, arg, memory_order_seq_cst)
|
|
#define atomic_fetch_and(obj, arg) atomic_fetch_and_explicit(obj, arg, memory_order_seq_cst)
|
|
|
|
// atomic_flag
|
|
typedef struct atomic_flag {
|
|
_Atomic(bool) __val;
|
|
} atomic_flag;
|
|
|
|
#define ATOMIC_FLAG_INIT {0}
|
|
|
|
#define atomic_flag_test_and_set_explicit(obj, order) atomic_exchange_explicit(&(obj)->__val, 1, order)
|
|
#define atomic_flag_test_and_set(obj) atomic_flag_test_and_set_explicit(obj, memory_order_seq_cst)
|
|
#define atomic_flag_clear_explicit(obj, order) atomic_store_explicit(&(obj)->__val, 0, order)
|
|
#define atomic_flag_clear(obj) atomic_flag_clear_explicit(obj, memory_order_seq_cst)
|
|
|
|
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_t) atomic_int_least8_t;
|
|
typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
|
|
typedef _Atomic(int_least16_t) atomic_int_least16_t;
|
|
typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
|
|
typedef _Atomic(int_least32_t) atomic_int_least32_t;
|
|
typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
|
|
typedef _Atomic(int_least64_t) atomic_int_least64_t;
|
|
typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
|
|
typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
|
|
typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
|
|
typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
|
|
typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
|
|
typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
|
|
typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
|
|
typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
|
|
typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
|
|
typedef _Atomic(intptr_t) atomic_intptr_t;
|
|
typedef _Atomic(uintptr_t) atomic_uintptr_t;
|
|
typedef _Atomic(size_t) atomic_size_t;
|
|
typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
|
|
typedef _Atomic(intmax_t) atomic_intmax_t;
|
|
typedef _Atomic(uintmax_t) atomic_uintmax_t;
|