xref: /openbsd-src/gnu/llvm/clang/lib/Headers/stdatomic.h (revision 12c855180aad702bbcca06e0398d774beeafb155)
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