/* ISO C Runtime Library Copyright (c) 2019-2020 Green Hills Software, Inc. This program is the property of Green Hills Software, Inc, its contents are proprietary information and no part of it is to be disclosed to anyone except employees of Green Hills Software, Inc., or as agreed in writing signed by the President of Green Hills Software, Inc. */ #ifndef _STDATOMIC_H #ifdef __ghs__ #pragma ghs startnomisra #endif #define _STDATOMIC_H #if __STDC_VERSION__ < 201112L #error stdatomic.h is only implemented for C11 and later #endif /* __STDC_VERSION__ < 201112L */ #define __GHS_WANT_NULL #include #include #include void __ghsLock(void); void __ghsUnlock(void); /* from stddef.h */ #if (__PTR_BIT <= __INT_BIT) || (__INT_BIT == __LONG_BIT) typedef int __ptrdiff_t; #elif (__PTR_BIT <= __LONG_BIT) || (__LONG_BIT == __LLONG_BIT) typedef long __ptrdiff_t; #else typedef long long __ptrdiff_t; #endif #if defined(__LLONG_BIT) && __PTR_BIT > __LONG_BIT typedef unsigned long long __size_t; #elif __PTR_BIT > __INT_BIT typedef unsigned long __size_t; #else typedef unsigned int __size_t; #endif #if defined(__WCHAR_TYPE__) typedef __WCHAR_TYPE__ __wchar_t; #elif defined(__WChar_Is_Int__) && defined(__WChar_Is_Unsigned__) typedef unsigned int __wchar_t; #elif defined(__WChar_Is_Int__) typedef int __wchar_t; #elif (__WCHAR_BIT == __LONG_BIT) && defined(__WChar_Is_Unsigned__) typedef unsigned long __wchar_t; #elif (__WCHAR_BIT == __LONG_BIT) typedef long __wchar_t; #elif (__WCHAR_BIT == __INT_BIT) && defined(__WChar_Is_Unsigned__) typedef unsigned int __wchar_t; #elif (__WCHAR_BIT == __INT_BIT) typedef int __wchar_t; #elif (__WCHAR_BIT == __SHRT_BIT) && defined(__WChar_Is_Unsigned__) typedef unsigned short __wchar_t; #elif (__WCHAR_BIT == __SHRT_BIT) typedef short __wchar_t; #else error Unknown size of __wchar_t #endif #if defined(__REG_BIT) && (__REG_BIT == __INT_BIT) #define ___FAST32 int #elif defined(__REG_BIT) && (__REG_BIT == __LONG_BIT) #define ___FAST32 long #elif defined(__REG_BIT) && defined(__LLONG_BIT) && (__REG_BIT == __LLONG_BIT) #define ___FAST32 long long #else #define ___FAST32 int #endif #if __LONG_BIT >= 64 #define ___FAST64 long #else #define ___FAST64 long long #endif typedef unsigned char __Uint8_T; typedef unsigned short __Uint16_T; typedef unsigned int __Uint32_T; typedef unsigned ___FAST64 __Uint64_T; /* LOCK_FREE macros */ #define ATOMIC_BOOL_LOCK_FREE \ (1 <= _ATOMIC_MAXBYTES_LOCK_FREE ? 2 : 0) #define ATOMIC_CHAR_LOCK_FREE \ (1 <= _ATOMIC_MAXBYTES_LOCK_FREE ? 2 : 0) #define ATOMIC_CHAR16_T_LOCK_FREE \ (2 <= _ATOMIC_MAXBYTES_LOCK_FREE ? 2 : 0) #define ATOMIC_CHAR32_T_LOCK_FREE \ (2 <= _ATOMIC_MAXBYTES_LOCK_FREE ? 2 : 0) #define ATOMIC_WCHAR_T_LOCK_FREE \ ((__WCHAR_BIT/8) <= _ATOMIC_MAXBYTES_LOCK_FREE ? 2 : 0) #define ATOMIC_SHORT_LOCK_FREE \ (2 <= _ATOMIC_MAXBYTES_LOCK_FREE ? 2 : 0) #define ATOMIC_INT_LOCK_FREE \ (4 <= _ATOMIC_MAXBYTES_LOCK_FREE ? 2 : 0) #define ATOMIC_LONG_LOCK_FREE \ ((__LONG_BIT/8) <= _ATOMIC_MAXBYTES_LOCK_FREE ? 2 : 0) #define ATOMIC_LLONG_LOCK_FREE \ (8 <= _ATOMIC_MAXBYTES_LOCK_FREE ? 2 : 0) #define ATOMIC_POINTER_LOCK_FREE \ ((__PTR_BIT/8) <= _ATOMIC_MAXBYTES_LOCK_FREE ? 2 : 0) /* Utility macros */ #define ATOMIC_FLAG_INIT { 0 } #define ATOMIC_VAR_INIT(__val) (__val) #define kill_dependency(__val) (__val) /* Memory order types */ typedef enum memory_order { memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_seq_cst } memory_order; /* Atomic Types */ typedef _Atomic unsigned char atomic_flag; 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 unsigned short atomic_char16_t; typedef _Atomic unsigned int atomic_char32_t; typedef _Atomic __wchar_t atomic_wchar_t; typedef _Atomic signed char atomic_int_least8_t; typedef _Atomic unsigned char atomic_uint_least8_t; typedef _Atomic signed short atomic_int_least16_t; typedef _Atomic unsigned short atomic_uint_least16_t; typedef _Atomic signed int atomic_int_least32_t; typedef _Atomic unsigned int atomic_uint_least32_t; typedef _Atomic signed ___FAST64 atomic_int_least64_t; typedef _Atomic unsigned ___FAST64 atomic_uint_least64_t; typedef _Atomic signed ___FAST32 atomic_int_fast8_t; typedef _Atomic unsigned ___FAST32 atomic_uint_fast8_t; typedef _Atomic signed ___FAST32 atomic_int_fast16_t; typedef _Atomic unsigned ___FAST32 atomic_uint_fast16_t; typedef _Atomic signed ___FAST32 atomic_int_fast32_t; typedef _Atomic unsigned ___FAST32 atomic_uint_fast32_t; typedef _Atomic signed ___FAST64 atomic_int_fast64_t; typedef _Atomic unsigned ___FAST64 atomic_uint_fast64_t; #undef ___FAST32 #undef ___FAST64 typedef _Atomic __ptrdiff_t atomic_intptr_t; typedef _Atomic __size_t atomic_uintptr_t; typedef _Atomic __size_t atomic_size_t; typedef _Atomic __ptrdiff_t atomic_ptrdiff_t; #if defined(__EINT1_BIT) && defined(__LLONG_BIT) && __EINT1_BIT > __LLONG_BIT typedef _Atomic signed __extended_int1 atomic_intmax_t; typedef _Atomic unsigned __extended_int1 atomic_uintmax_t; #else typedef _Atomic signed long long atomic_intmax_t; typedef _Atomic unsigned long long atomic_uintmax_t; #endif // Intrinsic declarations extern void __ghs_atomic_store_8(__Uint8_T *__ptr, __Uint8_T __val, int __mo); extern __Uint8_T __ghs_atomic_fetch_add_8(__Uint8_T *__ptr, __Uint8_T __val, int __mo); extern __Uint8_T __ghs_atomic_fetch_sub_8(__Uint8_T *__ptr, __Uint8_T __val, int __mo); extern __Uint8_T __ghs_atomic_fetch_and_8(__Uint8_T *__ptr, __Uint8_T __val, int __mo); extern __Uint8_T __ghs_atomic_fetch_xor_8(__Uint8_T *__ptr, __Uint8_T __val, int __mo); extern __Uint8_T __ghs_atomic_fetch_or_8(__Uint8_T *__ptr, __Uint8_T __val, int __mo); #if (_ATOMIC_MINBYTES_LOCK_FREE == 4) extern _Bool __ghs_atomic_compare_exchange_32_8(__Uint32_T *__ptr, __Uint8_T *__exp, __Uint32_T __val, _Bool __weak, int __mo1, int __mo2); extern __Uint32_T __ghs_atomic_fetch_add_32_8(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_sub_32_8(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_and_32_8(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_or_32_8(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_xor_32_8(__Uint32_T *__ptr, __Uint32_T __val, int __mo); #endif extern void __ghs_atomic_store_16(__Uint16_T *__ptr, __Uint16_T __val, int __mo); extern __Uint16_T __ghs_atomic_fetch_add_16(__Uint16_T *__ptr, __Uint16_T __val, int __mo); extern __Uint16_T __ghs_atomic_fetch_sub_16(__Uint16_T *__ptr, __Uint16_T __val, int __mo); extern __Uint16_T __ghs_atomic_fetch_and_16(__Uint16_T *__ptr, __Uint16_T __val, int __mo); extern __Uint16_T __ghs_atomic_fetch_xor_16(__Uint16_T *__ptr, __Uint16_T __val, int __mo); extern __Uint16_T __ghs_atomic_fetch_or_16(__Uint16_T *__ptr, __Uint16_T __val, int __mo); #if (_ATOMIC_MINBYTES_LOCK_FREE == 4) extern _Bool __ghs_atomic_compare_exchange_32_16(__Uint32_T *__ptr, __Uint16_T *__exp, __Uint32_T __val, _Bool __weak, int __mo1, int __mo2); extern __Uint32_T __ghs_atomic_fetch_add_32_16(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_sub_32_16(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_and_32_16(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_or_32_16(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_xor_32_16(__Uint32_T *__ptr, __Uint32_T __val, int __mo); #endif extern void __ghs_atomic_store_32(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_add_32(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_sub_32(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_and_32(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_xor_32(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern __Uint32_T __ghs_atomic_fetch_or_32(__Uint32_T *__ptr, __Uint32_T __val, int __mo); extern void __ghs_atomic_store_64(__Uint64_T *__ptr, __Uint64_T __val, int __mo); extern __Uint64_T __ghs_atomic_fetch_add_64(__Uint64_T *__ptr, __Uint64_T __val, int __mo); extern __Uint64_T __ghs_atomic_fetch_sub_64(__Uint64_T *__ptr, __Uint64_T __val, int __mo); extern __Uint64_T __ghs_atomic_fetch_and_64(__Uint64_T *__ptr, __Uint64_T __val, int __mo); extern __Uint64_T __ghs_atomic_fetch_xor_64(__Uint64_T *__ptr, __Uint64_T __val, int __mo); extern __Uint64_T __ghs_atomic_fetch_or_64(__Uint64_T *__ptr, __Uint64_T __val, int __mo); extern void __ghs_atomic_thread_fence(int __mo); // Function declarations void _Atomic_store_1_locking(volatile atomic_flag * __flag, volatile __Uint8_T *_Tgt, __Uint8_T _Value, memory_order _Order); __Uint8_T _Atomic_fetch_add_1_locking(volatile atomic_flag * __flag, volatile __Uint8_T *_Tgt, __Uint8_T _Value, memory_order _Order); __Uint8_T _Atomic_fetch_sub_1_locking(volatile atomic_flag * __flag, volatile __Uint8_T *_Tgt, __Uint8_T _Value, memory_order _Order); __Uint8_T _Atomic_fetch_and_1_locking(volatile atomic_flag * __flag, volatile __Uint8_T *_Tgt, __Uint8_T _Value, memory_order _Order); __Uint8_T _Atomic_fetch_or_1_locking(volatile atomic_flag * __flag, volatile __Uint8_T *_Tgt, __Uint8_T _Value, memory_order _Order); __Uint8_T _Atomic_fetch_xor_1_locking(volatile atomic_flag * __flag, volatile __Uint8_T *_Tgt, __Uint8_T _Value, memory_order _Order); void _Atomic_store_2_locking(volatile atomic_flag * __flag, volatile __Uint16_T *_Tgt, __Uint16_T _Value, memory_order _Order); __Uint16_T _Atomic_fetch_add_2_locking(volatile atomic_flag * __flag, volatile __Uint16_T *_Tgt, __Uint16_T _Value, memory_order _Order); __Uint16_T _Atomic_fetch_sub_2_locking(volatile atomic_flag * __flag, volatile __Uint16_T *_Tgt, __Uint16_T _Value, memory_order _Order); __Uint16_T _Atomic_fetch_and_2_locking(volatile atomic_flag * __flag, volatile __Uint16_T *_Tgt, __Uint16_T _Value, memory_order _Order); __Uint16_T _Atomic_fetch_or_2_locking(volatile atomic_flag * __flag, volatile __Uint16_T *_Tgt, __Uint16_T _Value, memory_order _Order); __Uint16_T _Atomic_fetch_xor_2_locking(volatile atomic_flag * __flag, volatile __Uint16_T *_Tgt, __Uint16_T _Value, memory_order _Order); void _Atomic_store_4_locking(volatile atomic_flag * __flag, volatile __Uint32_T *_Tgt, __Uint32_T _Value, memory_order _Order); __Uint32_T _Atomic_fetch_add_4_locking(volatile atomic_flag * __flag, volatile __Uint32_T *_Tgt, __Uint32_T _Value, memory_order _Order); __Uint32_T _Atomic_fetch_sub_4_locking(volatile atomic_flag * __flag, volatile __Uint32_T *_Tgt, __Uint32_T _Value, memory_order _Order); __Uint32_T _Atomic_fetch_and_4_locking(volatile atomic_flag * __flag, volatile __Uint32_T *_Tgt, __Uint32_T _Value, memory_order _Order); __Uint32_T _Atomic_fetch_or_4_locking(volatile atomic_flag * __flag, volatile __Uint32_T *_Tgt, __Uint32_T _Value, memory_order _Order); __Uint32_T _Atomic_fetch_xor_4_locking(volatile atomic_flag * __flag, volatile __Uint32_T *_Tgt, __Uint32_T _Value, memory_order _Order); void _Atomic_store_8_locking(volatile atomic_flag * __flag, volatile __Uint64_T *_Tgt, __Uint64_T _Value, memory_order _Order); __Uint64_T _Atomic_fetch_add_8_locking(volatile atomic_flag * __flag, volatile __Uint64_T *_Tgt, __Uint64_T _Value, memory_order _Order); __Uint64_T _Atomic_fetch_sub_8_locking(volatile atomic_flag * __flag, volatile __Uint64_T *_Tgt, __Uint64_T _Value, memory_order _Order); __Uint64_T _Atomic_fetch_and_8_locking(volatile atomic_flag * __flag, volatile __Uint64_T *_Tgt, __Uint64_T _Value, memory_order _Order); __Uint64_T _Atomic_fetch_or_8_locking(volatile atomic_flag * __flag, volatile __Uint64_T *_Tgt, __Uint64_T _Value, memory_order _Order); __Uint64_T _Atomic_fetch_xor_8_locking(volatile atomic_flag * __flag, volatile __Uint64_T *_Tgt, __Uint64_T _Value, memory_order _Order); #if _ATOMIC_FENCE_USES_LOCK void _Atomic_thread_fence_locking(memory_order _Order); void _Atomic_signal_fence_locking(memory_order _Order); #else void _Atomic_thread_fence(memory_order _Order); void _Atomic_signal_fence(memory_order _Order); #endif // Atomic operations #if _ATOMIC_MINBYTES_LOCK_FREE <= 1 && 1 <= _ATOMIC_MAXBYTES_LOCK_FREE #define _Atomic_Op_1(_OpName, _Obj, ...) __ghs_atomic_ ## _OpName ## _8 ((__Uint8_T *)(_Obj), __VA_ARGS__) #else #define _Atomic_Op_1(_OpName, _Obj, ...) _Atomic_## _OpName ## _1_locking(NULL, (__Uint8_T *)(_Obj), __VA_ARGS__) #endif #if _ATOMIC_MINBYTES_LOCK_FREE <= 2 && 2 <= _ATOMIC_MAXBYTES_LOCK_FREE #define _Atomic_Op_2(_OpName, _Obj, ...) __ghs_atomic_ ## _OpName ## _16((__Uint16_T *)(_Obj), __VA_ARGS__) #else #define _Atomic_Op_2(_OpName, _Obj, ...) _Atomic_## _OpName ## _2_locking(NULL, (__Uint16_T *)(_Obj), __VA_ARGS__) #endif #if _ATOMIC_MINBYTES_LOCK_FREE <= 4 && 4 <= _ATOMIC_MAXBYTES_LOCK_FREE #define _Atomic_Op_4(_OpName, _Obj, ...) __ghs_atomic_ ## _OpName ## _32((__Uint32_T *)(_Obj), __VA_ARGS__) #else #define _Atomic_Op_4(_OpName, _Obj, ...) _Atomic_## _OpName ## _4_locking(NULL, (__Uint32_T *)(_Obj), __VA_ARGS__) #endif #if _ATOMIC_MINBYTES_LOCK_FREE <= 8 && 8 <= _ATOMIC_MAXBYTES_LOCK_FREE #define _Atomic_Op_8(_OpName, _Obj, ...) __ghs_atomic_ ## _OpName ## _64((__Uint64_T *)(_Obj), __VA_ARGS__) #else #define _Atomic_Op_8(_OpName, _Obj, ...) _Atomic_## _OpName ## _8_locking(NULL, (__Uint64_T *)(_Obj), __VA_ARGS__) #endif #if __LONG_BIT == 64 #if _ATOMIC_MINBYTES_LOCK_FREE <= 8 && 8 <= _ATOMIC_MAXBYTES_LOCK_FREE #define _Atomic_Op_L(_OpName, _Obj, ...) __ghs_atomic_ ## _OpName ## _64((__Uint64_T *)(_Obj), __VA_ARGS__) #else #define _Atomic_Op_L(_OpName, _Obj, ...) _Atomic_## _OpName ## _8_locking(NULL, (__Uint64_T *)(_Obj), __VA_ARGS__) #endif #else #if _ATOMIC_MINBYTES_LOCK_FREE <= 4 && 4 <= _ATOMIC_MAXBYTES_LOCK_FREE #define _Atomic_Op_L(_OpName, _Obj, ...) __ghs_atomic_ ## _OpName ## _32((__Uint32_T *)(_Obj), __VA_ARGS__) #else #define _Atomic_Op_L(_OpName, _Obj, ...) _Atomic_## _OpName ## _4_locking(NULL, (__Uint32_T *)(_Obj), __VA_ARGS__) #endif #endif #if __PTR_BIT == 64 #if _ATOMIC_MINBYTES_LOCK_FREE <= 8 && 8 <= _ATOMIC_MAXBYTES_LOCK_FREE #define _Atomic_Op_A(_OpName, _Obj, ...) __ghs_atomic_ ## _OpName ## _64((__Uint64_T *)(_Obj), __VA_ARGS__) #else #define _Atomic_Op_A(_OpName, _Obj, ...) _Atomic_## _OpName ## _8_locking(NULL, (__Uint64_T *)(_Obj), __VA_ARGS__) #endif #else #if _ATOMIC_MINBYTES_LOCK_FREE <= 4 && 4 <= _ATOMIC_MAXBYTES_LOCK_FREE #define _Atomic_Op_A(_OpName, _Obj, ...) __ghs_atomic_ ## _OpName ## _32((__Uint32_T *)(_Obj), __VA_ARGS__) #else #define _Atomic_Op_A(_OpName, _Obj, ...) _Atomic_## _OpName ## _4_locking(NULL, (__Uint32_T *)(_Obj), __VA_ARGS__) #endif #endif #if defined(__GHS_NO_EXTERN_INLINE__) # define __GHS_EXTERN_INLINE /* Don't inline */ #elif defined(__cplusplus) # define __GHS_EXTERN_INLINE extern "C" inline /* ANSI/ISO C++ */ #elif defined(__GNUC__) && !defined(__GNUC_STDC_INLINE__) # define __GHS_EXTERN_INLINE extern __inline__ /* GNU C */ #elif defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L) # define __GHS_EXTERN_INLINE inline /* ANSI/ISO C99 */ #else # define __GHS_EXTERN_INLINE __inline /* GHS C */ #endif /* _Atomic qualifier cast away when doing locked operations. * volatile qualifier cast away to pass to intrinsics declared with * non-volatile type. */ #pragma ghs nowarning 1836 __GHS_EXTERN_INLINE int atomic_flag_test_and_set(volatile atomic_flag *_Flag) { #if _ATOMIC_MINBYTES_LOCK_FREE <= 1 && 1 <= _ATOMIC_MAXBYTES_LOCK_FREE return _Atomic_Op_1(exchange, (__Uint8_T *)_Flag, 1, memory_order_seq_cst); #else __ghsLock(); __Uint8_T __ret = *(volatile __Uint8_T *)_Flag; *(volatile __Uint8_T *)_Flag = 1; __ghsUnlock(); return __ret; #endif } __GHS_EXTERN_INLINE int atomic_flag_test_and_set_explicit(volatile atomic_flag *_Flag, memory_order _Order) { #if _ATOMIC_MINBYTES_LOCK_FREE <= 1 && 1 <= _ATOMIC_MAXBYTES_LOCK_FREE return _Atomic_Op_1(exchange, (__Uint8_T *)_Flag, 1, _Order); #else (void)_Order; __ghsLock(); __Uint8_T __ret = *(volatile __Uint8_T *)_Flag; *(volatile __Uint8_T *)_Flag = 1; __ghsUnlock(); return __ret; #endif } __GHS_EXTERN_INLINE void atomic_flag_clear(volatile atomic_flag *_Flag) { #if _ATOMIC_MINBYTES_LOCK_FREE <= 1 && 1 <= _ATOMIC_MAXBYTES_LOCK_FREE _Atomic_Op_1(store, (__Uint8_T *)_Flag, 0, memory_order_seq_cst); #else __ghsLock(); *(volatile __Uint8_T *)_Flag = 0; __ghsUnlock(); #endif } __GHS_EXTERN_INLINE void atomic_flag_clear_explicit(volatile atomic_flag *_Flag, memory_order _Order) { #if _ATOMIC_MINBYTES_LOCK_FREE <= 1 && 1 <= _ATOMIC_MAXBYTES_LOCK_FREE _Atomic_Op_1(store, (__Uint8_T *)_Flag, 0, _Order); #else (void)_Order; __ghsLock(); *(volatile __Uint8_T *)_Flag = 0; __ghsUnlock(); #endif } #pragma ghs endnowarning 1836 __GHS_EXTERN_INLINE void atomic_thread_fence(memory_order _Order) { if (_Order != memory_order_relaxed) { #if _ATOMIC_FENCE_USES_LOCK __ghsLock(); __ghsUnlock(); #elif defined(_ATOMIC_FENCE_USES_EXCHANGE) __ghs_atomic_thread_fence(_Order); #else _GHS_ATOMIC_BARRIER(); #endif } } __GHS_EXTERN_INLINE void atomic_signal_fence(memory_order _Order) { (void)_Order; __schedule_barrier(); } // Sanitize the written argument _A based on the type of the _Atomic // operand _Obj. Arithmatic types are broadly compatible enough that you can // cast them around, but you can't cast an aggregate type to an arithmatic // type, so we have the default clause corresponding to aggregates give a 0. #define _Atomic_Op_Sanitize_For_Integers(_Obj,_A) \ _Generic((_Obj), \ atomic_bool * : (_A), \ atomic_char * : (_A), \ atomic_schar * : (_A), \ atomic_flag * : (_A), \ atomic_short * : (_A), \ atomic_ushort * : (_A), \ atomic_int * : (_A), \ atomic_uint * : (_A), \ atomic_long * : (_A), \ atomic_ulong * : (_A), \ atomic_llong * : (_A), \ atomic_ullong * : (_A), \ void ** __attribute__((ghs_any_ptrptr)) \ : (_A), \ default : 0) // Sanitize the written argument _A based on the type of the _Atomic // operand _Obj. We need to be able to double-dereference the type returned // by this. #define _Atomic_Op_Sanitize_For_Pointers(_Obj) \ _Generic((_Obj), \ void ** __attribute__((ghs_any_ptrptr)) : (_Obj), \ default : ((int **)0)) #define _Atomic_op_store(_Obj, _OpName, _Arg, ...) \ _Pragma("ghs nowarning 167") \ _Pragma("ghs nowarning 767") \ _Pragma("ghs nowarning 1053") \ _Pragma("ghs nowarning 1518") \ _Pragma("ghs nowarning 1834") \ _Pragma("ghs nowarning 1836") \ _Pragma("ghs nowarning 2003") \ _Pragma("ghs nowarning 2123") \ _Pragma("ghs startnomisra") \ _Generic((_Obj), \ atomic_bool * : _Atomic_Op_1(_OpName, (_Obj), (__Uint8_T) _Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_char * : _Atomic_Op_1(_OpName, (_Obj), (__Uint8_T) _Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_schar * : _Atomic_Op_1(_OpName, (_Obj), (__Uint8_T) _Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_flag * : _Atomic_Op_1(_OpName, (_Obj), (__Uint8_T) _Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_short * : _Atomic_Op_2(_OpName, (_Obj), (__Uint16_T)_Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_ushort * : _Atomic_Op_2(_OpName, (_Obj), (__Uint16_T)_Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_int * : _Atomic_Op_4(_OpName, (_Obj), (__Uint32_T)_Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_uint * : _Atomic_Op_4(_OpName, (_Obj), (__Uint32_T)_Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_long * : _Atomic_Op_L(_OpName, (_Obj), (unsigned long)_Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_ulong * : _Atomic_Op_L(_OpName, (_Obj), (unsigned long)_Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_llong * : _Atomic_Op_8(_OpName, (_Obj), (__Uint64_T)_Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ atomic_ullong * : _Atomic_Op_8(_OpName, (_Obj), (__Uint64_T)_Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ void ** __attribute__((ghs_any_ptrptr)) \ : _Atomic_Op_A(_OpName, (_Obj), (__size_t) _Atomic_Op_Sanitize_For_Integers((_Obj),(_Arg)),__VA_ARGS__), \ default : (void)(*(_Obj)=(_Arg))) \ _Pragma("ghs endnomisra") \ _Pragma("ghs endnowarning 2123") \ _Pragma("ghs endnowarning 2003") \ _Pragma("ghs endnowarning 1836") \ _Pragma("ghs endnowarning 1834") \ _Pragma("ghs endnowarning 1518") \ _Pragma("ghs endnowarning 1053") \ _Pragma("ghs endnowarning 767") \ _Pragma("ghs endnowarning 167") // _Atomic_op_store depends on these assumptions about the sizes of types. _Static_assert(sizeof(char) == 1, ""); _Static_assert(sizeof(short) == 2, ""); _Static_assert(sizeof(int) == 4, ""); _Static_assert(sizeof(long long) == 8, ""); // Atomic generic selector // Note: Atomic fetch_op operations are applicable to only non-bool integer // types. We also accept bool although it is in poor taste and may result in // undefined behavior if the stored value is other than 0 or 1. #define _Atomic_op(_Obj, _OpName, _Val, ...) \ _Pragma("ghs nowarning 167") \ _Pragma("ghs nowarning 1053") \ _Pragma("ghs nowarning 1518") \ _Pragma("ghs nowarning 1834") \ _Pragma("ghs nowarning 1836") \ _Pragma("ghs nowarning 1910") \ _Pragma("ghs nowarning 2003") \ _Pragma("ghs nowarning 2123") \ _Pragma("ghs startnomisra") \ _Generic((_Obj), \ atomic_bool * : (_Bool) _Atomic_Op_1(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_bool * : (_Bool) _Atomic_Op_1(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_char * : (char) _Atomic_Op_1(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_char * : (char) _Atomic_Op_1(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_schar * : (signed char) _Atomic_Op_1(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_schar * : (signed char) _Atomic_Op_1(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_flag * : (unsigned char) _Atomic_Op_1(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_flag * : (unsigned char) _Atomic_Op_1(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_short * : (short) _Atomic_Op_2(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_short * : (short) _Atomic_Op_2(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_ushort * : (unsigned short) _Atomic_Op_2(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_ushort* : (unsigned short) _Atomic_Op_2(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_int * : (int) _Atomic_Op_4(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_int * : (int) _Atomic_Op_4(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_uint * : (unsigned int) _Atomic_Op_4(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_uint * : (unsigned int) _Atomic_Op_4(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_long * : (long) _Atomic_Op_L(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_long * : (long) _Atomic_Op_L(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_ulong * : (unsigned long) _Atomic_Op_L(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_ulong * : (unsigned long) _Atomic_Op_L(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_llong * : (long long) _Atomic_Op_8(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_llong * : (long long) _Atomic_Op_8(_OpName, (_Obj), (_Val), __VA_ARGS__), \ atomic_ullong * : (unsigned long long)_Atomic_Op_8(_OpName, (_Obj), (_Val), __VA_ARGS__), \ volatile atomic_ullong* : (unsigned long long)_Atomic_Op_8(_OpName, (_Obj), (_Val), __VA_ARGS__), \ void ** __attribute__((ghs_any_ptrptr)) \ : (__typeof__(*(_Obj))) \ _Atomic_Op_A(_OpName, (_Obj), \ ((_Val) * sizeof(** _Atomic_Op_Sanitize_For_Pointers(_Obj))), \ __VA_ARGS__)) \ _Pragma("ghs endnomisra") \ _Pragma("ghs endnowarning 2123") \ _Pragma("ghs endnowarning 2003") \ _Pragma("ghs endnowarning 1910") \ _Pragma("ghs endnowarning 1836") \ _Pragma("ghs endnowarning 1834") \ _Pragma("ghs endnowarning 1518") \ _Pragma("ghs endnowarning 1053") \ _Pragma("ghs endnowarning 167") // Atomic functions #define atomic_init(_Obj, _Arg) (*(_Obj) = (_Arg)) #define atomic_store_explicit(_Obj, _Arg, _Order) _Atomic_op_store((_Obj), store, (_Arg), (_Order)) #define atomic_store(_Obj, _Arg) atomic_store_explicit((_Obj), (_Arg), memory_order_seq_cst) #define atomic_load_explicit(_Obj, _Order) _Pragma("ghs nowarning 1725,1931,2123") _Pragma("ghs startnomisra") (__ghs_c11_atomic_load(NULL, (_Obj), sizeof(*(_Obj)), NULL, (_Order))) _Pragma("ghs endnomisra") _Pragma("ghs endnowarning 1725,1931,2123") #define atomic_load(_Obj) _Pragma("ghs nowarning 1725,1931,2123") _Pragma("ghs startnomisra") (__ghs_c11_atomic_load(NULL, (_Obj), sizeof(*(_Obj)), NULL, memory_order_seq_cst)) _Pragma("ghs endnomisra") _Pragma("ghs endnowarning 1725,1931,2123") #define atomic_exchange_explicit(_Obj, _Arg, _Order) _Pragma("ghs nowarning 1725,1931,2123") _Pragma("ghs startnomisra") (__ghs_c11_atomic_exchange(NULL, (_Obj), sizeof(*(_Obj)), (_Arg), NULL, (_Order))) _Pragma("ghs endnomisra") _Pragma("ghs endnowarning 1725,1931,2123") #define atomic_exchange(_Obj, _Arg) _Pragma("ghs nowarning 1725,1931,2123") _Pragma("ghs startnomisra") (__ghs_c11_atomic_exchange(NULL, (_Obj), sizeof(*(_Obj)), (_Arg), NULL, memory_order_seq_cst)) _Pragma("ghs endnomisra") _Pragma("ghs endnowarning 1725,1931,2123") #define atomic_compare_exchange_weak_explicit(_Obj, _Old, _Arg, _Succ, _Fail) _Pragma("ghs nowarning 1725,1931") _Pragma("ghs startnomisra") (__ghs_c11_atomic_compare_exchange(NULL, (_Obj), sizeof(*(_Obj)), (_Old), (_Arg), 1, (_Succ), (_Fail))) _Pragma("ghs endnomisra") _Pragma("ghs endnowarning 1725,1931") #define atomic_compare_exchange_weak(_Obj, _Old, _Arg) _Pragma("ghs nowarning 1725,1931") _Pragma("ghs startnomisra") (__ghs_c11_atomic_compare_exchange(NULL, (_Obj), sizeof(*(_Obj)), (_Old), (_Arg), 1, memory_order_seq_cst, memory_order_seq_cst)) _Pragma("ghs endnomisra") _Pragma("ghs endnowarning 1725,1931") #define atomic_compare_exchange_strong_explicit(_Obj, _Old, _Arg, _Succ, _Fail) _Pragma("ghs nowarning 1725,1931") _Pragma("ghs startnomisra") (__ghs_c11_atomic_compare_exchange(NULL, (_Obj), sizeof(*(_Obj)), (_Old), (_Arg), 0, (_Succ), (_Fail))) _Pragma("ghs endnomisra") _Pragma("ghs endnowarning 1725,1931") #define atomic_compare_exchange_strong(_Obj, _Old, _Arg) _Pragma("ghs nowarning 1725,1931") _Pragma("ghs startnomisra") (__ghs_c11_atomic_compare_exchange(NULL, (_Obj), sizeof(*(_Obj)), (_Old), (_Arg), 0, memory_order_seq_cst, memory_order_seq_cst)) _Pragma("ghs endnomisra") _Pragma("ghs endnowarning 1725,1931") #define atomic_fetch_add_explicit(_Obj, _Arg, _Order) _Atomic_op((_Obj), fetch_add, (_Arg), (_Order)) #define atomic_fetch_add(_Obj, _Arg) atomic_fetch_add_explicit((_Obj), (_Arg), memory_order_seq_cst) #define atomic_fetch_sub_explicit(_Obj, _Arg, _Order) _Atomic_op((_Obj), fetch_sub, (_Arg), (_Order)) #define atomic_fetch_sub(_Obj, _Arg) atomic_fetch_sub_explicit((_Obj), (_Arg), memory_order_seq_cst) #define atomic_fetch_or_explicit(_Obj, _Arg, _Order) _Atomic_op((_Obj), fetch_or, (_Arg), (_Order)) #define atomic_fetch_or(_Obj, _Arg) atomic_fetch_or_explicit((_Obj), (_Arg), memory_order_seq_cst) #define atomic_fetch_xor_explicit(_Obj, _Arg, _Order) _Atomic_op((_Obj), fetch_xor, (_Arg), (_Order)) #define atomic_fetch_xor(_Obj, _Arg) atomic_fetch_xor_explicit((_Obj), (_Arg), memory_order_seq_cst) #define atomic_fetch_and_explicit(_Obj, _Arg, _Order) _Atomic_op((_Obj), fetch_and, (_Arg), (_Order)) #define atomic_fetch_and(_Obj, _Arg) atomic_fetch_and_explicit((_Obj), (_Arg), memory_order_seq_cst) #define atomic_is_lock_free(_Obj) \ _Pragma("ghs nowarning 174") \ _Pragma("ghs startnomisra") \ ((_Obj), _Generic((_Obj), \ atomic_bool * : ((_Bool)ATOMIC_BOOL_LOCK_FREE), \ volatile atomic_bool * : ((_Bool)ATOMIC_BOOL_LOCK_FREE), \ const atomic_bool * : ((_Bool)ATOMIC_BOOL_LOCK_FREE), \ volatile const atomic_bool * : ((_Bool)ATOMIC_BOOL_LOCK_FREE), \ atomic_char * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ volatile atomic_char * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ const atomic_char * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ volatile const atomic_char * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ atomic_schar * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ volatile atomic_schar * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ const atomic_schar * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ volatile const atomic_schar * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ atomic_flag * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ volatile atomic_flag * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ const atomic_flag * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ volatile const atomic_flag * : ((_Bool)ATOMIC_CHAR_LOCK_FREE), \ atomic_short * : ((_Bool)ATOMIC_SHORT_LOCK_FREE), \ volatile atomic_short * : ((_Bool)ATOMIC_SHORT_LOCK_FREE), \ const atomic_short * : ((_Bool)ATOMIC_SHORT_LOCK_FREE), \ volatile const atomic_short * : ((_Bool)ATOMIC_SHORT_LOCK_FREE), \ atomic_ushort * : ((_Bool)ATOMIC_SHORT_LOCK_FREE), \ volatile atomic_ushort * : ((_Bool)ATOMIC_SHORT_LOCK_FREE), \ const atomic_ushort * : ((_Bool)ATOMIC_SHORT_LOCK_FREE), \ volatile const atomic_ushort * : ((_Bool)ATOMIC_SHORT_LOCK_FREE), \ atomic_int * : ((_Bool)ATOMIC_INT_LOCK_FREE), \ volatile atomic_int * : ((_Bool)ATOMIC_INT_LOCK_FREE), \ const atomic_int * : ((_Bool)ATOMIC_INT_LOCK_FREE), \ volatile const atomic_int * : ((_Bool)ATOMIC_INT_LOCK_FREE), \ atomic_uint * : ((_Bool)ATOMIC_INT_LOCK_FREE), \ volatile atomic_uint * : ((_Bool)ATOMIC_INT_LOCK_FREE), \ const atomic_uint * : ((_Bool)ATOMIC_INT_LOCK_FREE), \ volatile const atomic_uint * : ((_Bool)ATOMIC_INT_LOCK_FREE), \ atomic_long * : ((_Bool)ATOMIC_LONG_LOCK_FREE), \ volatile atomic_long * : ((_Bool)ATOMIC_LONG_LOCK_FREE), \ const atomic_long * : ((_Bool)ATOMIC_LONG_LOCK_FREE), \ volatile const atomic_long * : ((_Bool)ATOMIC_LONG_LOCK_FREE), \ atomic_ulong * : ((_Bool)ATOMIC_LONG_LOCK_FREE), \ volatile atomic_ulong * : ((_Bool)ATOMIC_LONG_LOCK_FREE), \ const atomic_ulong * : ((_Bool)ATOMIC_LONG_LOCK_FREE), \ volatile const atomic_ulong * : ((_Bool)ATOMIC_LONG_LOCK_FREE), \ atomic_llong * : ((_Bool)ATOMIC_LLONG_LOCK_FREE), \ volatile atomic_llong * : ((_Bool)ATOMIC_LLONG_LOCK_FREE), \ const atomic_llong * : ((_Bool)ATOMIC_LLONG_LOCK_FREE), \ volatile const atomic_llong * : ((_Bool)ATOMIC_LLONG_LOCK_FREE), \ atomic_ullong * : ((_Bool)ATOMIC_LLONG_LOCK_FREE), \ volatile atomic_ullong * : ((_Bool)ATOMIC_LLONG_LOCK_FREE), \ const atomic_ullong * : ((_Bool)ATOMIC_LLONG_LOCK_FREE), \ volatile const atomic_ullong * : ((_Bool)ATOMIC_LLONG_LOCK_FREE), \ void ** __attribute__((ghs_any_ptrptr)) \ : ((_Bool)ATOMIC_POINTER_LOCK_FREE), \ default : ((_Bool)0))) \ _Pragma("ghs endnomisra") \ _Pragma("ghs endnowarning 174") \ #ifdef __ghs__ #pragma ghs endnomisra #endif #endif /*_STDATOMIC */