74 #ifndef _STDATOMIC_H_ // NOLINT
85 #if !defined(__has_feature)
86 #define __has_feature(x) 0
88 #if !defined(__has_builtin)
89 #define __has_builtin(x) 0
91 #if !defined(__GNUC_PREREQ__)
92 #if defined(__GNUC__) && defined(__GNUC_MINOR__)
93 #define __GNUC_PREREQ__(maj, min) \
94 ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
96 #define __GNUC_PREREQ__(maj, min) 0
100 #if !defined(__CLANG_ATOMICS) && !defined(__GNUC_ATOMICS)
101 #if __has_feature(c_atomic)
102 #define __CLANG_ATOMICS
103 #elif __GNUC_PREREQ__(4, 7)
104 #define __GNUC_ATOMICS
105 #elif !defined(__GNUC__)
106 #error "stdatomic.h does not support your compiler"
110 #if !defined(__CLANG_ATOMICS)
111 #define _Atomic(T) struct { volatile __typeof__(T) __val; }
118 #if defined(__CLANG_ATOMICS)
119 #define ATOMIC_VAR_INIT(value) (value)
120 #define atomic_init(obj, value) __c11_atomic_init(obj, value)
122 #define ATOMIC_VAR_INIT(value) { .__val = (value) }
123 #define atomic_init(obj, value) do { \
124 (obj)->__val = (value); \
134 #ifndef __ATOMIC_RELAXED
135 #define __ATOMIC_RELAXED 0
137 #ifndef __ATOMIC_CONSUME
138 #define __ATOMIC_CONSUME 1
140 #ifndef __ATOMIC_ACQUIRE
141 #define __ATOMIC_ACQUIRE 2
143 #ifndef __ATOMIC_RELEASE
144 #define __ATOMIC_RELEASE 3
146 #ifndef __ATOMIC_ACQ_REL
147 #define __ATOMIC_ACQ_REL 4
149 #ifndef __ATOMIC_SEQ_CST
150 #define __ATOMIC_SEQ_CST 5
175 #ifdef __CLANG_ATOMICS
176 #define atomic_thread_fence(order) __c11_atomic_thread_fence(order)
177 #define atomic_signal_fence(order) __c11_atomic_signal_fence(order)
178 #elif defined(__GNUC_ATOMICS)
179 #define atomic_thread_fence(order) __atomic_thread_fence(order)
180 #define atomic_signal_fence(order) __atomic_signal_fence(order)
182 #define atomic_thread_fence(order) __sync_synchronize()
183 #define atomic_signal_fence(order) __asm volatile ("" : : : "memory")
190 #if defined(__CLANG_ATOMICS)
191 #define atomic_is_lock_free(obj) \
192 __c11_atomic_is_lock_free(sizeof(obj))
193 #elif defined(__GNUC_ATOMICS)
194 #define atomic_is_lock_free(obj) \
195 __atomic_is_lock_free(sizeof((obj)->__val))
197 #define atomic_is_lock_free(obj) \
198 (sizeof((obj)->__val) <= sizeof(void *))
205 typedef _Atomic(_Bool) atomic_bool;
206 typedef _Atomic(
char) atomic_char;
207 typedef _Atomic(
signed char) atomic_schar;
208 typedef _Atomic(
unsigned char) atomic_uchar;
209 typedef _Atomic(
short) atomic_short;
210 typedef _Atomic(
unsigned short) atomic_ushort;
211 typedef _Atomic(
int) atomic_int;
212 typedef _Atomic(
unsigned int) atomic_uint;
213 typedef _Atomic(
long) atomic_long;
214 typedef _Atomic(
unsigned long) atomic_ulong;
215 typedef _Atomic(
long long) atomic_llong;
216 typedef _Atomic(
unsigned long long) atomic_ullong;
218 typedef _Atomic(char16_t) atomic_char16_t;
219 typedef _Atomic(char32_t) atomic_char32_t;
221 typedef _Atomic(
wchar_t) atomic_wchar_t;
222 typedef _Atomic(int_least8_t) atomic_int_least8_t;
223 typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
224 typedef _Atomic(int_least16_t) atomic_int_least16_t;
225 typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
226 typedef _Atomic(int_least32_t) atomic_int_least32_t;
227 typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
228 typedef _Atomic(int_least64_t) atomic_int_least64_t;
229 typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
230 typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
231 typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
232 typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
233 typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
234 typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
235 typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
236 typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
237 typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
238 typedef _Atomic(intptr_t) atomic_intptr_t;
239 typedef _Atomic(uintptr_t) atomic_uintptr_t;
240 typedef _Atomic(
size_t) atomic_size_t;
241 typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
242 typedef _Atomic(intmax_t) atomic_intmax_t;
243 typedef _Atomic(uintmax_t) atomic_uintmax_t;
253 #if defined(__CLANG_ATOMICS)
254 #define atomic_compare_exchange_strong_explicit(object, expected, \
255 desired, success, failure) \
256 __c11_atomic_compare_exchange_strong(object, expected, desired, \
258 #define atomic_compare_exchange_weak_explicit(object, expected, \
259 desired, success, failure) \
260 __c11_atomic_compare_exchange_weak(object, expected, desired, \
262 #define atomic_exchange_explicit(object, desired, order) \
263 __c11_atomic_exchange(object, desired, order)
264 #define atomic_fetch_add_explicit(object, operand, order) \
265 __c11_atomic_fetch_add(object, operand, order)
266 #define atomic_fetch_and_explicit(object, operand, order) \
267 __c11_atomic_fetch_and(object, operand, order)
268 #define atomic_fetch_or_explicit(object, operand, order) \
269 __c11_atomic_fetch_or(object, operand, order)
270 #define atomic_fetch_sub_explicit(object, operand, order) \
271 __c11_atomic_fetch_sub(object, operand, order)
272 #define atomic_fetch_xor_explicit(object, operand, order) \
273 __c11_atomic_fetch_xor(object, operand, order)
274 #define atomic_load_explicit(object, order) \
275 __c11_atomic_load(object, order)
276 #define atomic_store_explicit(object, desired, order) \
277 __c11_atomic_store(object, desired, order)
278 #elif defined(__GNUC_ATOMICS)
279 #define atomic_compare_exchange_strong_explicit(object, expected, \
280 desired, success, failure) \
281 __atomic_compare_exchange_n(&(object)->__val, expected, \
282 desired, 0, success, failure)
283 #define atomic_compare_exchange_weak_explicit(object, expected, \
284 desired, success, failure) \
285 __atomic_compare_exchange_n(&(object)->__val, expected, \
286 desired, 1, success, failure)
287 #define atomic_exchange_explicit(object, desired, order) \
288 __atomic_exchange_n(&(object)->__val, desired, order)
289 #define atomic_fetch_add_explicit(object, operand, order) \
290 __atomic_fetch_add(&(object)->__val, operand, order)
291 #define atomic_fetch_and_explicit(object, operand, order) \
292 __atomic_fetch_and(&(object)->__val, operand, order)
293 #define atomic_fetch_or_explicit(object, operand, order) \
294 __atomic_fetch_or(&(object)->__val, operand, order)
295 #define atomic_fetch_sub_explicit(object, operand, order) \
296 __atomic_fetch_sub(&(object)->__val, operand, order)
297 #define atomic_fetch_xor_explicit(object, operand, order) \
298 __atomic_fetch_xor(&(object)->__val, operand, order)
299 #define atomic_load_explicit(object, order) \
300 __atomic_load_n(&(object)->__val, order)
301 #define atomic_store_explicit(object, desired, order) \
302 __atomic_store_n(&(object)->__val, desired, order)
304 #define atomic_compare_exchange_strong_explicit(object, expected, \
305 desired, success, failure) ({ \
306 __typeof__((object)->__val) __v; \
308 __v = __sync_val_compare_and_swap(&(object)->__val, \
309 *(expected), desired); \
310 __r = *(expected) == __v; \
315 #define atomic_compare_exchange_weak_explicit(object, expected, \
316 desired, success, failure) \
317 atomic_compare_exchange_strong_explicit(object, expected, \
318 desired, success, failure)
319 #if __has_builtin(__sync_swap)
321 #define atomic_exchange_explicit(object, desired, order) \
322 __sync_swap(&(object)->__val, desired)
329 #define atomic_exchange_explicit(object, desired, order) ({ \
330 __typeof__((object)->__val) __v; \
331 __v = __sync_lock_test_and_set(&(object)->__val, desired); \
332 __sync_synchronize(); \
336 #define atomic_fetch_add_explicit(object, operand, order) \
337 __sync_fetch_and_add(&(object)->__val, operand)
338 #define atomic_fetch_and_explicit(object, operand, order) \
339 __sync_fetch_and_and(&(object)->__val, operand)
340 #define atomic_fetch_or_explicit(object, operand, order) \
341 __sync_fetch_and_or(&(object)->__val, operand)
342 #define atomic_fetch_sub_explicit(object, operand, order) \
343 __sync_fetch_and_sub(&(object)->__val, operand)
344 #define atomic_fetch_xor_explicit(object, operand, order) \
345 __sync_fetch_and_xor(&(object)->__val, operand)
346 #define atomic_load_explicit(object, order) \
347 __sync_fetch_and_add(&(object)->__val, 0)
348 #define atomic_store_explicit(object, desired, order) do { \
349 __sync_synchronize(); \
350 (object)->__val = (desired); \
351 __sync_synchronize(); \
359 #define atomic_compare_exchange_strong(object, expected, desired) \
360 atomic_compare_exchange_strong_explicit(object, expected, \
361 desired, memory_order_seq_cst, memory_order_seq_cst)
362 #define atomic_compare_exchange_weak(object, expected, desired) \
363 atomic_compare_exchange_weak_explicit(object, expected, \
364 desired, memory_order_seq_cst, memory_order_seq_cst)
365 #define atomic_exchange(object, desired) \
366 atomic_exchange_explicit(object, desired, memory_order_seq_cst)
367 #define atomic_fetch_add(object, operand) \
368 atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
369 #define atomic_fetch_and(object, operand) \
370 atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
371 #define atomic_fetch_or(object, operand) \
372 atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
373 #define atomic_fetch_sub(object, operand) \
374 atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
375 #define atomic_fetch_xor(object, operand) \
376 atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
377 #define atomic_load(object) \
378 atomic_load_explicit(object, memory_order_seq_cst)
379 #define atomic_store(object, desired) \
380 atomic_store_explicit(object, desired, memory_order_seq_cst)
388 #define ATOMIC_FLAG_INIT ATOMIC_VAR_INIT(0)
390 #define atomic_flag_clear_explicit(object, order) \
391 atomic_store_explicit(object, 0, order)
392 #define atomic_flag_test_and_set_explicit(object, order) \
393 atomic_compare_exchange_strong_explicit(object, 0, 1, order, order)
395 #define atomic_flag_clear(object) \
396 atomic_flag_clear_explicit(object, memory_order_seq_cst)
397 #define atomic_flag_test_and_set(object) \
398 atomic_flag_test_and_set_explicit(object, memory_order_seq_cst)