23 #ifndef LELY_LIBC_STDATOMIC_H_
24 #define LELY_LIBC_STDATOMIC_H_
28 #ifndef LELY_HAVE_STDATOMIC_H
29 #if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
30 #define LELY_HAVE_STDATOMIC_H 1
32 #endif // !LELY_HAVE_STDATOMIC_H
34 #if LELY_HAVE_STDATOMIC_H
36 #else // !LELY_HAVE_STDATOMIC_H
38 #if defined(__clang__) && __has_extension(c_atomic)
39 #define LELY_HAVE_CLANG_ATOMIC 1
40 #elif GNUC_PREREQ(4, 7)
41 #define LELY_HAVE_GNUC_ATOMIC 1
42 #elif GNUC_PREREQ(4, 1)
43 #define LELY_HAVE_SYNC_ATOMIC 1
46 #if LELY_HAVE_CLANG_ATOMIC | LELY_HAVE_GNUC_ATOMIC | LELY_HAVE_SYNC_ATOMIC
53 #ifndef LELY_LIBC_STDATOMIC_INLINE
54 #define LELY_LIBC_STDATOMIC_INLINE static inline
57 #ifdef __GCC_ATOMIC_BOOL_LOCK_FREE
58 #define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
60 #define ATOMIC_BOOL_LOCK_FREE 2
63 #ifdef __GCC_ATOMIC_CHAR_LOCK_FREE
64 #define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
66 #define ATOMIC_CHAR_LOCK_FREE 1
69 #ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
70 #define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
72 #define ATOMIC_CHAR16_T_LOCK_FREE 1
75 #ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
76 #define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
78 #define ATOMIC_CHAR32_T_LOCK_FREE 1
81 #ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
82 #define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
84 #define ATOMIC_WCHAR_T_LOCK_FREE 1
87 #ifdef __GCC_ATOMIC_SHORT_LOCK_FREE
88 #define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
90 #define ATOMIC_SHORT_LOCK_FREE 1
93 #ifdef __GCC_ATOMIC_INT_LOCK_FREE
94 #define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
96 #define ATOMIC_INT_LOCK_FREE 1
99 #ifdef __GCC_ATOMIC_LONG_LOCK_FREE
100 #define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
102 #define ATOMIC_LONG_LOCK_FREE 1
105 #ifdef __GCC_ATOMIC_LLONG_LOCK_FREE
106 #define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
108 #define ATOMIC_LLONG_LOCK_FREE 1
111 #ifdef __GCC_ATOMIC_POINTER_LOCK_FREE
112 #define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
114 #define ATOMIC_POINTER_LOCK_FREE 1
120 #define ATOMIC_FLAG_INIT \
128 #ifdef __ATOMIC_RELAXED
137 #ifdef __ATOMIC_CONSUME
146 #ifdef __ATOMIC_ACQUIRE
155 #ifdef __ATOMIC_RELEASE
165 #ifdef __ATOMIC_ACQ_REL
170 #ifdef __ATOMIC_SEQ_CST
178 #ifndef LELY_HAVE_CLANG_ATOMIC
182 T volatile _value_; \
186 #ifndef ATOMIC_BOOL_TYPE
188 #define ATOMIC_BOOL_TYPE bool
190 #define ATOMIC_BOOL_TYPE _Bool
199 _Atomic(ATOMIC_BOOL_TYPE) _value_;
206 #if LELY_HAVE_CLANG_ATOMIC
207 #define ATOMIC_VAR_INIT(value) (value)
209 #define ATOMIC_VAR_INIT(value) \
219 #if LELY_HAVE_CLANG_ATOMIC
220 #define atomic_init(obj, value) __c11_atomic_init(obj, value)
222 #define atomic_init(obj, value) \
223 atomic_store_explicit(obj, value, memory_order_relaxed)
230 #if defined(__GNUC__) || (__clang__)
231 #define kill_dependency(y) \
233 __typeof__(y) _tmp_ = (y); \
237 #define kill_dependency(y)
264 #if LELY_HAVE_CLANG_ATOMIC
265 #define atomic_is_lock_free(obj) (__c11_atomic_is_lock_free(sizeof(*(obj))))
266 #elif LELY_HAVE_GNUC_ATOMIC
267 #define atomic_is_lock_free(obj) \
268 (__atomic_is_lock_free(sizeof((obj)->_value_), &(obj)->_value_))
270 #define atomic_is_lock_free(obj) (sizeof((obj)->_value_) <= sizeof(void *))
273 typedef _Atomic(ATOMIC_BOOL_TYPE) atomic_bool;
274 typedef _Atomic(
char) atomic_char;
275 typedef _Atomic(
signed char) atomic_schar;
276 typedef _Atomic(
unsigned char) atomic_uchar;
277 typedef _Atomic(
short) atomic_short;
278 typedef _Atomic(
unsigned short) atomic_ushort;
279 typedef _Atomic(
int) atomic_int;
280 typedef _Atomic(
unsigned int) atomic_uint;
281 typedef _Atomic(
long) atomic_long;
282 typedef _Atomic(
unsigned long) atomic_ulong;
283 typedef _Atomic(
long long) atomic_llong;
284 typedef _Atomic(
unsigned long long) atomic_ullong;
285 typedef _Atomic(char16_t) atomic_char16_t;
286 typedef _Atomic(char32_t) atomic_char32_t;
287 typedef _Atomic(
wchar_t) atomic_wchar_t;
288 typedef _Atomic(int_least8_t) atomic_int_least8_t;
289 typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
290 typedef _Atomic(int_least16_t) atomic_int_least16_t;
291 typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
292 typedef _Atomic(int_least32_t) atomic_int_least32_t;
293 typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
294 typedef _Atomic(int_least64_t) atomic_int_least64_t;
295 typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
296 typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
297 typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
298 typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
299 typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
300 typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
301 typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
302 typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
303 typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
304 typedef _Atomic(intptr_t) atomic_intptr_t;
305 typedef _Atomic(uintptr_t) atomic_uintptr_t;
306 typedef _Atomic(
size_t) atomic_size_t;
307 typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
308 typedef _Atomic(intmax_t) atomic_intmax_t;
309 typedef _Atomic(uintmax_t) atomic_uintmax_t;
314 #define atomic_store(object, desired) \
315 (atomic_store_explicit((object), (desired), memory_order_seq_cst))
321 #if LELY_HAVE_CLANG_ATOMIC
322 #define atomic_store_explicit(object, desired, order) \
323 (__c11_atomic_store((object), (desired), (order)))
324 #elif LELY_HAVE_GNUC_ATOMIC
325 #define atomic_store_explicit(object, desired, order) \
326 (__atomic_store_n(&(object)->_value_, (desired), (order)))
328 #define atomic_store_explicit(object, desired, order) \
329 ((void)atomic_exchange_explicit((object), (desired), (order)))
333 #define atomic_load(object) \
334 (atomic_load_explicit((object), memory_order_seq_cst))
340 #if LELY_HAVE_CLANG_ATOMIC
341 #define atomic_load_explicit(object, order) \
342 (__c11_atomic_load((object), (order)))
343 #elif LELY_HAVE_GNUC_ATOMIC
344 #define atomic_load_explicit(object, order) \
345 (__atomic_load_n(&(object)->_value_, (order)))
346 #elif LELY_HAVE_SYNC_ATOMIC
347 #define atomic_load_explicit(object, order) \
348 ((void)(order), __sync_fetch_and_add(&(object)->_value_, 0))
355 #define atomic_exchange(object, desired) \
356 (atomic_exchange_explicit((object), (desired), memory_order_seq_cst))
364 #if LELY_HAVE_CLANG_ATOMIC
365 #define atomic_exchange_explicit(object, desired, order) \
366 (__c11_atomic_exchange((object), (desired), (order)))
367 #elif LELY_HAVE_GNUC_ATOMIC
368 #define atomic_exchange_explicit(object, desired, order) \
369 (__atomic_exchange_n(&(object)->_value_, (desired), (order)))
370 #elif LELY_HAVE_SYNC_ATOMIC
371 #define atomic_exchange_explicit(object, desired, order) \
373 __typeof__(object) __object = (object); \
374 __typeof__(desired) __desired = (desired); \
375 atomic_thread_fence(order); \
376 __sync_lock_test_and_set(&(__object)->_value_, __desired); \
384 #define atomic_compare_exchange_strong(object, expected, desired) \
385 (atomic_compare_exchange_strong_explicit((object), (expected), \
386 (desired), memory_order_seq_cst, \
387 memory_order_seq_cst))
399 #if LELY_HAVE_CLANG_ATOMIC
400 #define atomic_compare_exchange_strong_explicit( \
401 object, expected, desired, success, failure) \
402 (__c11_atomic_compare_exchange_strong((object), (expected), (desired), \
403 (success), (failure)))
404 #elif LELY_HAVE_GNUC_ATOMIC
405 #define atomic_compare_exchange_strong_explicit( \
406 object, expected, desired, success, failure) \
407 (__atomic_compare_exchange_n(&(object)->_value_, (expected), \
408 (desired), 0, (success), (failure)))
409 #elif LELY_HAVE_SYNC_ATOMIC
411 #define atomic_compare_exchange_strong_explicit(object, expected, desired, \
416 __typeof__(*(expected)) _expected_ = *(expected); \
417 (ATOMIC_BOOL_TYPE)((*(expected) = __sync_val_compare_and_swap( \
418 &(object)->_value_, _expected_, (desired))) \
428 #define atomic_compare_exchange_weak(object, expected, desired) \
429 (atomic_compare_exchange_weak_explicit((object), (expected), \
430 (desired), memory_order_seq_cst, \
431 memory_order_seq_cst))
446 #if LELY_HAVE_CLANG_ATOMIC
447 #define atomic_compare_exchange_weak_explicit( \
448 object, expected, desired, success, failure) \
449 (__c11_atomic_compare_exchange_weak((object), (expected), (desired), \
450 (success), (failure)))
451 #elif LELY_HAVE_GNUC_ATOMIC
452 #define atomic_compare_exchange_weak_explicit( \
453 object, expected, desired, success, failure) \
454 (__atomic_compare_exchange_n(&(object)->_value_, (expected), \
455 (desired), 1, (success), (failure)))
457 #define atomic_compare_exchange_weak_explicit( \
458 object, expected, desired, success, failure) \
459 (atomic_compare_exchange_strong_explicit((object), (expected), \
460 (desired), (success), (failure)))
467 #define atomic_fetch_add(object, operand) \
468 (atomic_fetch_add_explicit((object), (operand), memory_order_seq_cst))
476 #if LELY_HAVE_CLANG_ATOMIC
477 #define atomic_fetch_add_explicit(object, operand, order) \
478 (__c11_atomic_fetch_add((object), (operand), (order)))
479 #elif LELY_HAVE_GNUC_ATOMIC
480 #define atomic_fetch_add_explicit(object, operand, order) \
481 (__atomic_fetch_add(&(object)->_value_, (operand), (order)))
482 #elif LELY_HAVE_SYNC_ATOMIC
483 #define atomic_fetch_add_explicit(object, operand, order) \
484 ((void)(order), __sync_fetch_and_add(&(object)->_value_, (operand)))
491 #define atomic_fetch_sub(object, operand) \
492 (atomic_fetch_sub_explicit((object), (operand), memory_order_seq_cst))
500 #if LELY_HAVE_CLANG_ATOMIC
501 #define atomic_fetch_sub_explicit(object, operand, order) \
502 (__c11_atomic_fetch_sub((object), (operand), (order)))
503 #elif LELY_HAVE_GNUC_ATOMIC
504 #define atomic_fetch_sub_explicit(object, operand, order) \
505 (__atomic_fetch_sub(&(object)->_value_, (operand), (order)))
506 #elif LELY_HAVE_SYNC_ATOMIC
507 #define atomic_fetch_sub_explicit(object, operand, order) \
508 ((void)(order), __sync_fetch_and_sub(&(object)->_value_, (operand)))
515 #define atomic_fetch_or(object, operand) \
516 (atomic_fetch_or_explicit((object), (operand), memory_order_seq_cst))
524 #if LELY_HAVE_CLANG_ATOMIC
525 #define atomic_fetch_or_explicit(object, operand, order) \
526 (__c11_atomic_fetch_or((object), (operand), (order)))
527 #elif LELY_HAVE_GNUC_ATOMIC
528 #define atomic_fetch_or_explicit(object, operand, order) \
529 (__atomic_fetch_or(&(object)->_value_, (operand), (order)))
530 #elif LELY_HAVE_SYNC_ATOMIC
531 #define atomic_fetch_or_explicit(object, operand, order) \
532 ((void)(order), __sync_fetch_and_or(&(object)->_value_, (operand)))
539 #define atomic_fetch_xor(object, operand) \
540 (atomic_fetch_xor_explicit((object), (operand), memory_order_seq_cst))
548 #if LELY_HAVE_CLANG_ATOMIC
549 #define atomic_fetch_xor_explicit(object, operand, order) \
550 (__c11_atomic_fetch_xor((object), (operand), (order)))
551 #elif LELY_HAVE_GNUC_ATOMIC
552 #define atomic_fetch_xor_explicit(object, operand, order) \
553 (__atomic_fetch_xor(&(object)->_value_, (operand), (order)))
554 #elif LELY_HAVE_SYNC_ATOMIC
555 #define atomic_fetch_xor_explicit(object, operand, order) \
556 ((void)(order), __sync_fetch_and_xor(&(object)->_value_, (operand)))
563 #define atomic_fetch_and(object, operand) \
564 (atomic_fetch_and_explicit((object), (operand), memory_order_seq_cst))
572 #if LELY_HAVE_CLANG_ATOMIC
573 #define atomic_fetch_and_explicit(object, operand, order) \
574 (__c11_atomic_fetch_and((object), (operand), (order)))
575 #elif LELY_HAVE_GNUC_ATOMIC
576 #define atomic_fetch_and_explicit(object, operand, order) \
577 (__atomic_fetch_and(&(object)->_value_, (operand), (order)))
578 #elif LELY_HAVE_SYNC_ATOMIC
579 #define atomic_fetch_and_explicit(object, operand, order) \
580 ((void)(order), __sync_fetch_and_and(&(object)->_value_, (operand)))
619 #if LELY_HAVE_CLANG_ATOMIC
620 __c11_atomic_thread_fence(order);
621 #elif LELY_HAVE_GNUC_ATOMIC
622 __atomic_thread_fence(order);
623 #elif LELY_HAVE_SYNC_ATOMIC
625 __sync_synchronize();
632 #if LELY_HAVE_CLANG_ATOMIC
633 __c11_atomic_signal_fence(order);
634 #elif LELY_HAVE_GNUC_ATOMIC
635 __atomic_signal_fence(order);
636 #elif defined(__GNUC__)
638 __asm
volatile(
"" :::
"memory");
642 inline ATOMIC_BOOL_TYPE
649 inline ATOMIC_BOOL_TYPE
671 #endif // LELY_HAVE_CLANG_ATOMIC | LELY_HAVE_GNUC_ATOMIC | LELY_HAVE_SYNC_ATOMIC
673 #endif // !LELY_HAVE_STDATOMIC_H
675 #endif // !LELY_LIBC_STDATOMIC_H_