blob: 590eb60444a7fb6de948f43d924659187d842a3f [file] [log] [blame]
#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;