| #pragma once | |
| /** | |
| * This file implements the C11 and C++23 C atomics interfaces. On targets | |
| * without hardware atomics, these will all lower to calls into the atomics | |
| * shared library. You must link either atomics or atomics_fixed (if you use | |
| * only fixed-width atomics) into your firmware image. | |
| * | |
| * *WARNING*: The C++ atomics interface is more efficient for non-primitive | |
| * types but is *not* guaranteed to be interoperable with the C version. | |
| * Interoperable code should use only primitive types in atomics. | |
| */ | |
| #ifdef __cplusplus | |
| # include <atomic> | |
| # define _Atomic(T) std::atomic<T> | |
| #else | |
| # include <stddef.h> | |
| # include <stdint.h> | |
| 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, | |
| }; | |
| typedef _Atomic(_Bool) atomic_flag; | |
| # define ATOMIC_FLAG_INIT false | |
| // Clang thinks that all atomics are too big, so ignore it. | |
| __clang_ignored_warning_push("-Watomic-alignment") | |
| __always_inline static inline _Bool | |
| atomic_flag_test_and_set_explicit(volatile atomic_flag *obj, | |
| enum memory_order order) | |
| { | |
| return __c11_atomic_exchange(obj, 1, order); | |
| } | |
| __always_inline static inline _Bool | |
| atomic_flag_test_and_set(volatile atomic_flag *obj) | |
| { | |
| return atomic_flag_test_and_set_explicit(obj, memory_order_seq_cst); | |
| } | |
| __always_inline static inline _Bool | |
| atomic_flag_test_and_clear_explicit(volatile atomic_flag *obj, | |
| enum memory_order order) | |
| { | |
| return __c11_atomic_exchange(obj, 0, order); | |
| } | |
| __always_inline static inline _Bool | |
| atomic_flag_test_and_clear(volatile atomic_flag *obj) | |
| { | |
| return atomic_flag_test_and_clear_explicit(obj, memory_order_seq_cst); | |
| } | |
| __clang_ignored_warning_pop() | |
| // The functions in the following block are mapped directly to builtins. | |
| # define atomic_init(obj, value) __c11_atomic_init(obj, value) | |
| # define atomic_compare_exchange_strong_explicit( \ | |
| object, expected, desired, success, failure) \ | |
| __c11_atomic_compare_exchange_strong( \ | |
| object, expected, desired, success, failure) | |
| # define atomic_compare_exchange_weak_explicit( \ | |
| object, expected, desired, success, failure) \ | |
| __c11_atomic_compare_exchange_weak( \ | |
| object, expected, desired, success, failure) | |
| # define atomic_exchange_explicit(object, desired, order) \ | |
| __c11_atomic_exchange(object, desired, order) | |
| # define atomic_fetch_add_explicit(object, operand, order) \ | |
| __c11_atomic_fetch_add(object, operand, order) | |
| # define atomic_fetch_and_explicit(object, operand, order) \ | |
| __c11_atomic_fetch_and(object, operand, order) | |
| # define atomic_fetch_or_explicit(object, operand, order) \ | |
| __c11_atomic_fetch_or(object, operand, order) | |
| # define atomic_fetch_sub_explicit(object, operand, order) \ | |
| __c11_atomic_fetch_sub(object, operand, order) | |
| # define atomic_fetch_xor_explicit(object, operand, order) \ | |
| __c11_atomic_fetch_xor(object, operand, order) | |
| # define atomic_load_explicit(object, order) __c11_atomic_load(object, order) | |
| # define atomic_store_explicit(object, desired, order) \ | |
| __c11_atomic_store(object, desired, order) | |
| // The functions in the following block are convenience wrappers around the | |
| // previous block | |
| # define atomic_compare_exchange_strong(object, expected, desired) \ | |
| atomic_compare_exchange_strong_explicit(object, \ | |
| expected, \ | |
| desired, \ | |
| memory_order_seq_cst, \ | |
| memory_order_seq_cst) | |
| # define atomic_compare_exchange_weak(object, expected, desired) \ | |
| atomic_compare_exchange_weak_explicit(object, \ | |
| expected, \ | |
| desired, \ | |
| memory_order_seq_cst, \ | |
| memory_order_seq_cst) | |
| # define atomic_exchange(object, desired) \ | |
| atomic_exchange_explicit(object, desired, memory_order_seq_cst) | |
| # define atomic_fetch_add(object, operand) \ | |
| atomic_fetch_add_explicit(object, operand, memory_order_seq_cst) | |
| # define atomic_fetch_and(object, operand) \ | |
| atomic_fetch_and_explicit(object, operand, memory_order_seq_cst) | |
| # define atomic_fetch_or(object, operand) \ | |
| atomic_fetch_or_explicit(object, operand, memory_order_seq_cst) | |
| # define atomic_fetch_sub(object, operand) \ | |
| atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst) | |
| # define atomic_fetch_xor(object, operand) \ | |
| atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst) | |
| # define atomic_load(object) \ | |
| atomic_load_explicit(object, memory_order_seq_cst) | |
| # define atomic_store(object, desired) \ | |
| atomic_store_explicit(object, desired, memory_order_seq_cst) | |
| #endif | |
| 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(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; |