1e5dd7070Spatrick /*===---- stdatomic.h - Standard header for atomic types and operations -----=== 2e5dd7070Spatrick * 3e5dd7070Spatrick * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick * See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick * 7e5dd7070Spatrick *===-----------------------------------------------------------------------=== 8e5dd7070Spatrick */ 9e5dd7070Spatrick 10e5dd7070Spatrick #ifndef __CLANG_STDATOMIC_H 11e5dd7070Spatrick #define __CLANG_STDATOMIC_H 12e5dd7070Spatrick 13e5dd7070Spatrick /* If we're hosted, fall back to the system's stdatomic.h. FreeBSD, for 14e5dd7070Spatrick * example, already has a Clang-compatible stdatomic.h header. 15*12c85518Srobert * 16*12c85518Srobert * Exclude the MSVC path as well as the MSVC header as of the 14.31.30818 17*12c85518Srobert * explicitly disallows `stdatomic.h` in the C mode via an `#error`. Fallback 18*12c85518Srobert * to the clang resource header until that is fully supported. The 19*12c85518Srobert * `stdatomic.h` header requires C++ 23 or newer. 20e5dd7070Spatrick */ 21*12c85518Srobert #if __STDC_HOSTED__ && \ 22*12c85518Srobert __has_include_next(<stdatomic.h>) && \ 23*12c85518Srobert (!defined(_MSC_VER) || (defined(__cplusplus) && __cplusplus >= 202002L)) 24e5dd7070Spatrick # include_next <stdatomic.h> 25e5dd7070Spatrick #else 26e5dd7070Spatrick 27e5dd7070Spatrick #include <stddef.h> 28e5dd7070Spatrick #include <stdint.h> 29e5dd7070Spatrick 30e5dd7070Spatrick #ifdef __cplusplus 31e5dd7070Spatrick extern "C" { 32e5dd7070Spatrick #endif 33e5dd7070Spatrick 34e5dd7070Spatrick /* 7.17.1 Introduction */ 35e5dd7070Spatrick 36e5dd7070Spatrick #define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE 37e5dd7070Spatrick #define ATOMIC_CHAR_LOCK_FREE __CLANG_ATOMIC_CHAR_LOCK_FREE 38e5dd7070Spatrick #define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 39e5dd7070Spatrick #define ATOMIC_CHAR32_T_LOCK_FREE __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 40e5dd7070Spatrick #define ATOMIC_WCHAR_T_LOCK_FREE __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 41e5dd7070Spatrick #define ATOMIC_SHORT_LOCK_FREE __CLANG_ATOMIC_SHORT_LOCK_FREE 42e5dd7070Spatrick #define ATOMIC_INT_LOCK_FREE __CLANG_ATOMIC_INT_LOCK_FREE 43e5dd7070Spatrick #define ATOMIC_LONG_LOCK_FREE __CLANG_ATOMIC_LONG_LOCK_FREE 44e5dd7070Spatrick #define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE 45e5dd7070Spatrick #define ATOMIC_POINTER_LOCK_FREE __CLANG_ATOMIC_POINTER_LOCK_FREE 46e5dd7070Spatrick 47e5dd7070Spatrick /* 7.17.2 Initialization */ 48e5dd7070Spatrick 49e5dd7070Spatrick #define ATOMIC_VAR_INIT(value) (value) 50*12c85518Srobert #if ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201710L) || \ 51*12c85518Srobert (defined(__cplusplus) && __cplusplus >= 202002L)) && \ 52*12c85518Srobert !defined(_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS) 53*12c85518Srobert /* ATOMIC_VAR_INIT was deprecated in C17 and C++20. */ 54*12c85518Srobert #pragma clang deprecated(ATOMIC_VAR_INIT) 55*12c85518Srobert #endif 56e5dd7070Spatrick #define atomic_init __c11_atomic_init 57e5dd7070Spatrick 58e5dd7070Spatrick /* 7.17.3 Order and consistency */ 59e5dd7070Spatrick 60e5dd7070Spatrick typedef enum memory_order { 61e5dd7070Spatrick memory_order_relaxed = __ATOMIC_RELAXED, 62e5dd7070Spatrick memory_order_consume = __ATOMIC_CONSUME, 63e5dd7070Spatrick memory_order_acquire = __ATOMIC_ACQUIRE, 64e5dd7070Spatrick memory_order_release = __ATOMIC_RELEASE, 65e5dd7070Spatrick memory_order_acq_rel = __ATOMIC_ACQ_REL, 66e5dd7070Spatrick memory_order_seq_cst = __ATOMIC_SEQ_CST 67e5dd7070Spatrick } memory_order; 68e5dd7070Spatrick 69e5dd7070Spatrick #define kill_dependency(y) (y) 70e5dd7070Spatrick 71e5dd7070Spatrick /* 7.17.4 Fences */ 72e5dd7070Spatrick 73e5dd7070Spatrick /* These should be provided by the libc implementation. */ 74e5dd7070Spatrick void atomic_thread_fence(memory_order); 75e5dd7070Spatrick void atomic_signal_fence(memory_order); 76e5dd7070Spatrick 77e5dd7070Spatrick #define atomic_thread_fence(order) __c11_atomic_thread_fence(order) 78e5dd7070Spatrick #define atomic_signal_fence(order) __c11_atomic_signal_fence(order) 79e5dd7070Spatrick 80e5dd7070Spatrick /* 7.17.5 Lock-free property */ 81e5dd7070Spatrick 82e5dd7070Spatrick #define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj))) 83e5dd7070Spatrick 84e5dd7070Spatrick /* 7.17.6 Atomic integer types */ 85e5dd7070Spatrick 86e5dd7070Spatrick #ifdef __cplusplus 87e5dd7070Spatrick typedef _Atomic(bool) atomic_bool; 88e5dd7070Spatrick #else 89e5dd7070Spatrick typedef _Atomic(_Bool) atomic_bool; 90e5dd7070Spatrick #endif 91e5dd7070Spatrick typedef _Atomic(char) atomic_char; 92e5dd7070Spatrick typedef _Atomic(signed char) atomic_schar; 93e5dd7070Spatrick typedef _Atomic(unsigned char) atomic_uchar; 94e5dd7070Spatrick typedef _Atomic(short) atomic_short; 95e5dd7070Spatrick typedef _Atomic(unsigned short) atomic_ushort; 96e5dd7070Spatrick typedef _Atomic(int) atomic_int; 97e5dd7070Spatrick typedef _Atomic(unsigned int) atomic_uint; 98e5dd7070Spatrick typedef _Atomic(long) atomic_long; 99e5dd7070Spatrick typedef _Atomic(unsigned long) atomic_ulong; 100e5dd7070Spatrick typedef _Atomic(long long) atomic_llong; 101e5dd7070Spatrick typedef _Atomic(unsigned long long) atomic_ullong; 102e5dd7070Spatrick typedef _Atomic(uint_least16_t) atomic_char16_t; 103e5dd7070Spatrick typedef _Atomic(uint_least32_t) atomic_char32_t; 104e5dd7070Spatrick typedef _Atomic(wchar_t) atomic_wchar_t; 105e5dd7070Spatrick typedef _Atomic(int_least8_t) atomic_int_least8_t; 106e5dd7070Spatrick typedef _Atomic(uint_least8_t) atomic_uint_least8_t; 107e5dd7070Spatrick typedef _Atomic(int_least16_t) atomic_int_least16_t; 108e5dd7070Spatrick typedef _Atomic(uint_least16_t) atomic_uint_least16_t; 109e5dd7070Spatrick typedef _Atomic(int_least32_t) atomic_int_least32_t; 110e5dd7070Spatrick typedef _Atomic(uint_least32_t) atomic_uint_least32_t; 111e5dd7070Spatrick typedef _Atomic(int_least64_t) atomic_int_least64_t; 112e5dd7070Spatrick typedef _Atomic(uint_least64_t) atomic_uint_least64_t; 113e5dd7070Spatrick typedef _Atomic(int_fast8_t) atomic_int_fast8_t; 114e5dd7070Spatrick typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t; 115e5dd7070Spatrick typedef _Atomic(int_fast16_t) atomic_int_fast16_t; 116e5dd7070Spatrick typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t; 117e5dd7070Spatrick typedef _Atomic(int_fast32_t) atomic_int_fast32_t; 118e5dd7070Spatrick typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t; 119e5dd7070Spatrick typedef _Atomic(int_fast64_t) atomic_int_fast64_t; 120e5dd7070Spatrick typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t; 121e5dd7070Spatrick typedef _Atomic(intptr_t) atomic_intptr_t; 122e5dd7070Spatrick typedef _Atomic(uintptr_t) atomic_uintptr_t; 123e5dd7070Spatrick typedef _Atomic(size_t) atomic_size_t; 124e5dd7070Spatrick typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t; 125e5dd7070Spatrick typedef _Atomic(intmax_t) atomic_intmax_t; 126e5dd7070Spatrick typedef _Atomic(uintmax_t) atomic_uintmax_t; 127e5dd7070Spatrick 128e5dd7070Spatrick /* 7.17.7 Operations on atomic types */ 129e5dd7070Spatrick 130e5dd7070Spatrick #define atomic_store(object, desired) __c11_atomic_store(object, desired, __ATOMIC_SEQ_CST) 131e5dd7070Spatrick #define atomic_store_explicit __c11_atomic_store 132e5dd7070Spatrick 133e5dd7070Spatrick #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST) 134e5dd7070Spatrick #define atomic_load_explicit __c11_atomic_load 135e5dd7070Spatrick 136e5dd7070Spatrick #define atomic_exchange(object, desired) __c11_atomic_exchange(object, desired, __ATOMIC_SEQ_CST) 137e5dd7070Spatrick #define atomic_exchange_explicit __c11_atomic_exchange 138e5dd7070Spatrick 139e5dd7070Spatrick #define atomic_compare_exchange_strong(object, expected, desired) __c11_atomic_compare_exchange_strong(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) 140e5dd7070Spatrick #define atomic_compare_exchange_strong_explicit __c11_atomic_compare_exchange_strong 141e5dd7070Spatrick 142e5dd7070Spatrick #define atomic_compare_exchange_weak(object, expected, desired) __c11_atomic_compare_exchange_weak(object, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) 143e5dd7070Spatrick #define atomic_compare_exchange_weak_explicit __c11_atomic_compare_exchange_weak 144e5dd7070Spatrick 145e5dd7070Spatrick #define atomic_fetch_add(object, operand) __c11_atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST) 146e5dd7070Spatrick #define atomic_fetch_add_explicit __c11_atomic_fetch_add 147e5dd7070Spatrick 148e5dd7070Spatrick #define atomic_fetch_sub(object, operand) __c11_atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST) 149e5dd7070Spatrick #define atomic_fetch_sub_explicit __c11_atomic_fetch_sub 150e5dd7070Spatrick 151e5dd7070Spatrick #define atomic_fetch_or(object, operand) __c11_atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST) 152e5dd7070Spatrick #define atomic_fetch_or_explicit __c11_atomic_fetch_or 153e5dd7070Spatrick 154e5dd7070Spatrick #define atomic_fetch_xor(object, operand) __c11_atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST) 155e5dd7070Spatrick #define atomic_fetch_xor_explicit __c11_atomic_fetch_xor 156e5dd7070Spatrick 157e5dd7070Spatrick #define atomic_fetch_and(object, operand) __c11_atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST) 158e5dd7070Spatrick #define atomic_fetch_and_explicit __c11_atomic_fetch_and 159e5dd7070Spatrick 160e5dd7070Spatrick /* 7.17.8 Atomic flag type and operations */ 161e5dd7070Spatrick 162e5dd7070Spatrick typedef struct atomic_flag { atomic_bool _Value; } atomic_flag; 163e5dd7070Spatrick 164e5dd7070Spatrick #define ATOMIC_FLAG_INIT { 0 } 165e5dd7070Spatrick 166e5dd7070Spatrick /* These should be provided by the libc implementation. */ 167e5dd7070Spatrick #ifdef __cplusplus 168e5dd7070Spatrick bool atomic_flag_test_and_set(volatile atomic_flag *); 169e5dd7070Spatrick bool atomic_flag_test_and_set_explicit(volatile atomic_flag *, memory_order); 170e5dd7070Spatrick #else 171e5dd7070Spatrick _Bool atomic_flag_test_and_set(volatile atomic_flag *); 172e5dd7070Spatrick _Bool atomic_flag_test_and_set_explicit(volatile atomic_flag *, memory_order); 173e5dd7070Spatrick #endif 174e5dd7070Spatrick void atomic_flag_clear(volatile atomic_flag *); 175e5dd7070Spatrick void atomic_flag_clear_explicit(volatile atomic_flag *, memory_order); 176e5dd7070Spatrick 177e5dd7070Spatrick #define atomic_flag_test_and_set(object) __c11_atomic_exchange(&(object)->_Value, 1, __ATOMIC_SEQ_CST) 178e5dd7070Spatrick #define atomic_flag_test_and_set_explicit(object, order) __c11_atomic_exchange(&(object)->_Value, 1, order) 179e5dd7070Spatrick 180e5dd7070Spatrick #define atomic_flag_clear(object) __c11_atomic_store(&(object)->_Value, 0, __ATOMIC_SEQ_CST) 181e5dd7070Spatrick #define atomic_flag_clear_explicit(object, order) __c11_atomic_store(&(object)->_Value, 0, order) 182e5dd7070Spatrick 183e5dd7070Spatrick #ifdef __cplusplus 184e5dd7070Spatrick } 185e5dd7070Spatrick #endif 186e5dd7070Spatrick 187e5dd7070Spatrick #endif /* __STDC_HOSTED__ */ 188e5dd7070Spatrick #endif /* __CLANG_STDATOMIC_H */ 189e5dd7070Spatrick 190