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 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 45 #define __STDC_NO_ATOMICS__ 1 48 #if !__STDC_NO_ATOMICS__ 55 #ifndef LELY_LIBC_STDATOMIC_INLINE 56 #define LELY_LIBC_STDATOMIC_INLINE static inline 59 #ifdef __GCC_ATOMIC_BOOL_LOCK_FREE 60 #define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE 62 #define ATOMIC_BOOL_LOCK_FREE 2 65 #ifdef __GCC_ATOMIC_CHAR_LOCK_FREE 66 #define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE 68 #define ATOMIC_CHAR_LOCK_FREE 1 71 #ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE 72 #define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE 74 #define ATOMIC_CHAR16_T_LOCK_FREE 1 77 #ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE 78 #define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE 80 #define ATOMIC_CHAR32_T_LOCK_FREE 1 83 #ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE 84 #define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE 86 #define ATOMIC_WCHAR_T_LOCK_FREE 1 89 #ifdef __GCC_ATOMIC_SHORT_LOCK_FREE 90 #define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE 92 #define ATOMIC_SHORT_LOCK_FREE 1 95 #ifdef __GCC_ATOMIC_INT_LOCK_FREE 96 #define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE 98 #define ATOMIC_INT_LOCK_FREE 1 101 #ifdef __GCC_ATOMIC_LONG_LOCK_FREE 102 #define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE 104 #define ATOMIC_LONG_LOCK_FREE 1 107 #ifdef __GCC_ATOMIC_LLONG_LOCK_FREE 108 #define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE 110 #define ATOMIC_LLONG_LOCK_FREE 1 113 #ifdef __GCC_ATOMIC_POINTER_LOCK_FREE 114 #define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE 116 #define ATOMIC_POINTER_LOCK_FREE 1 122 #define ATOMIC_FLAG_INIT \ 130 #ifdef __ATOMIC_RELAXED 131 memory_order_relaxed = __ATOMIC_RELAXED,
133 memory_order_relaxed = 0,
139 #ifdef __ATOMIC_CONSUME 140 memory_order_consume = __ATOMIC_CONSUME,
142 memory_order_consume = 1,
148 #ifdef __ATOMIC_ACQUIRE 149 memory_order_acquire = __ATOMIC_ACQUIRE,
151 memory_order_acquire = 2,
157 #ifdef __ATOMIC_RELEASE 158 memory_order_release = __ATOMIC_RELEASE,
160 memory_order_release = 3,
167 #ifdef __ATOMIC_ACQ_REL 168 memory_order_acq_rel = __ATOMIC_ACQ_REL,
170 memory_order_acq_rel = 4,
172 #ifdef __ATOMIC_SEQ_CST 174 memory_order_seq_cst = __ATOMIC_SEQ_CST
176 memory_order_seq_cst = 5,
180 #ifndef LELY_HAVE_CLANG_ATOMIC 182 #define _Atomic(T) struct { T volatile _value_; } 185 #ifndef ATOMIC_BOOL_TYPE 187 #define ATOMIC_BOOL_TYPE bool 189 #define ATOMIC_BOOL_TYPE _Bool 198 _Atomic(ATOMIC_BOOL_TYPE) _value_;
205 #if LELY_HAVE_CLANG_ATOMIC 206 #define ATOMIC_VAR_INIT(value) (value) 208 #define ATOMIC_VAR_INIT(value) \ 218 #if LELY_HAVE_CLANG_ATOMIC 219 #define atomic_init(obj, value) __c11_atomic_init(obj, value) 221 #define atomic_init(obj, value) \ 222 atomic_store_explicit(obj, value, memory_order_relaxed) 229 #if defined(__GNUC__) || (__clang__) 230 #define kill_dependency(y) \ 232 __typeof__(y) _tmp_ = (y); \ 236 #define kill_dependency(y) 244 LELY_LIBC_STDATOMIC_INLINE
void atomic_thread_fence(memory_order order);
251 LELY_LIBC_STDATOMIC_INLINE
void atomic_signal_fence(memory_order order);
263 #if LELY_HAVE_CLANG_ATOMIC 264 #define atomic_is_lock_free(obj) (__c11_atomic_is_lock_free(sizeof(*(obj)))) 265 #elif LELY_HAVE_GNUC_ATOMIC 266 #define atomic_is_lock_free(obj) \ 267 (__atomic_is_lock_free(sizeof((obj)->_value_), &(obj)->_value_)) 269 #define atomic_is_lock_free(obj) (sizeof((obj)->_value_) <= sizeof(void *)) 272 typedef _Atomic(ATOMIC_BOOL_TYPE) atomic_bool;
273 typedef _Atomic(
char) atomic_char;
274 typedef _Atomic(
signed char) atomic_schar;
275 typedef _Atomic(
unsigned char) atomic_uchar;
276 typedef _Atomic(
short) atomic_short;
277 typedef _Atomic(
unsigned short) atomic_ushort;
278 typedef _Atomic(
int) atomic_int;
279 typedef _Atomic(
unsigned int) atomic_uint;
280 typedef _Atomic(
long) atomic_long;
281 typedef _Atomic(
unsigned long) atomic_ulong;
282 typedef _Atomic(
long long) atomic_llong;
283 typedef _Atomic(
unsigned long long) atomic_ullong;
284 typedef _Atomic(char16_t) atomic_char16_t;
285 typedef _Atomic(char32_t) atomic_char32_t;
286 typedef _Atomic(
wchar_t) atomic_wchar_t;
287 typedef _Atomic(int_least8_t) atomic_int_least8_t;
288 typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
289 typedef _Atomic(int_least16_t) atomic_int_least16_t;
290 typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
291 typedef _Atomic(int_least32_t) atomic_int_least32_t;
292 typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
293 typedef _Atomic(int_least64_t) atomic_int_least64_t;
294 typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
295 typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
296 typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
297 typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
298 typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
299 typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
300 typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
301 typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
302 typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
303 typedef _Atomic(intptr_t) atomic_intptr_t;
304 typedef _Atomic(uintptr_t) atomic_uintptr_t;
305 typedef _Atomic(
size_t) atomic_size_t;
306 typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
307 typedef _Atomic(intmax_t) atomic_intmax_t;
308 typedef _Atomic(uintmax_t) atomic_uintmax_t;
313 #define atomic_store(object, desired) \ 314 (atomic_store_explicit((object), (desired), memory_order_seq_cst)) 320 #if LELY_HAVE_CLANG_ATOMIC 321 #define atomic_store_explicit(object, desired, order) \ 322 (__c11_atomic_store((object), (desired), (order))) 323 #elif LELY_HAVE_GNUC_ATOMIC 324 #define atomic_store_explicit(object, desired, order) \ 325 (__atomic_store_n(&(object)->_value_, (desired), (order))) 327 #define atomic_store_explicit(object, desired, order) \ 328 ((void)atomic_exchange_explicit((object), (desired), (order))) 332 #define atomic_load(object) \ 333 (atomic_load_explicit((object), memory_order_seq_cst)) 339 #if LELY_HAVE_CLANG_ATOMIC 340 #define atomic_load_explicit(object, order) \ 341 (__c11_atomic_load((object), (order))) 342 #elif LELY_HAVE_GNUC_ATOMIC 343 #define atomic_load_explicit(object, order) \ 344 (__atomic_load_n(&(object)->_value_, (order))) 345 #elif LELY_HAVE_SYNC_ATOMIC 346 #define atomic_load_explicit(object, order) \ 347 ((void)(order), __sync_fetch_and_add(&(object)->_value_, 0)) 354 #define atomic_exchange(object, desired) \ 355 (atomic_exchange_explicit((object), (desired), memory_order_seq_cst)) 363 #if LELY_HAVE_CLANG_ATOMIC 364 #define atomic_exchange_explicit(object, desired, order) \ 365 (__c11_atomic_exchange((object), (desired), (order))) 366 #elif LELY_HAVE_GNUC_ATOMIC 367 #define atomic_exchange_explicit(object, desired, order) \ 368 (__atomic_exchange_n(&(object)->_value_, (desired), (order))) 369 #elif LELY_HAVE_SYNC_ATOMIC 370 #define atomic_exchange_explicit(object, desired, order) \ 372 __typeof__(object) __object = (object); \ 373 __typeof__(desired) __desired = (desired); \ 374 atomic_thread_fence(order); \ 375 __sync_lock_test_and_set(&(__object)->_value_, __desired); \ 383 #define atomic_compare_exchange_strong(object, expected, desired) \ 384 (atomic_compare_exchange_strong_explicit((object), (expected), \ 385 (desired), memory_order_seq_cst, \ 386 memory_order_seq_cst)) 398 #if LELY_HAVE_CLANG_ATOMIC 399 #define atomic_compare_exchange_strong_explicit( \ 400 object, expected, desired, success, failure) \ 401 (__c11_atomic_compare_exchange_strong((object), (expected), (desired), \ 402 (success), (failure))) 403 #elif LELY_HAVE_GNUC_ATOMIC 404 #define atomic_compare_exchange_strong_explicit( \ 405 object, expected, desired, success, failure) \ 406 (__atomic_compare_exchange_n(&(object)->_value_, (expected), \ 407 (desired), 0, (success), (failure))) 408 #elif LELY_HAVE_SYNC_ATOMIC 410 #define atomic_compare_exchange_strong_explicit(object, expected, desired, \ 415 __typeof__(*(expected)) _expected_ = *(expected); \ 416 (ATOMIC_BOOL_TYPE)((*(expected) = __sync_val_compare_and_swap( \ 417 &(object)->_value_, _expected_, (desired))) \ 427 #define atomic_compare_exchange_weak(object, expected, desired) \ 428 (atomic_compare_exchange_weak_explicit((object), (expected), \ 429 (desired), memory_order_seq_cst, \ 430 memory_order_seq_cst)) 445 #if LELY_HAVE_CLANG_ATOMIC 446 #define atomic_compare_exchange_weak_explicit( \ 447 object, expected, desired, success, failure) \ 448 (__c11_atomic_compare_exchange_weak((object), (expected), (desired), \ 449 (success), (failure))) 450 #elif LELY_HAVE_GNUC_ATOMIC 451 #define atomic_compare_exchange_weak_explicit( \ 452 object, expected, desired, success, failure) \ 453 (__atomic_compare_exchange_n(&(object)->_value_, (expected), \ 454 (desired), 1, (success), (failure))) 456 #define atomic_compare_exchange_weak_explicit( \ 457 object, expected, desired, success, failure) \ 458 (atomic_compare_exchange_strong_explicit((object), (expected), \ 459 (desired), (success), (failure))) 466 #define atomic_fetch_add(object, operand) \ 467 (atomic_fetch_add_explicit((object), (operand), memory_order_seq_cst)) 475 #if LELY_HAVE_CLANG_ATOMIC 476 #define atomic_fetch_add_explicit(object, operand, order) \ 477 (__c11_atomic_fetch_add((object), (operand), (order))) 478 #elif LELY_HAVE_GNUC_ATOMIC 479 #define atomic_fetch_add_explicit(object, operand, order) \ 480 (__atomic_fetch_add(&(object)->_value_, (operand), (order))) 481 #elif LELY_HAVE_SYNC_ATOMIC 482 #define atomic_fetch_add_explicit(object, operand, order) \ 483 ((void)(order), __sync_fetch_and_add(&(object)->_value_, (operand))) 490 #define atomic_fetch_sub(object, operand) \ 491 (atomic_fetch_sub_explicit((object), (operand), memory_order_seq_cst)) 499 #if LELY_HAVE_CLANG_ATOMIC 500 #define atomic_fetch_sub_explicit(object, operand, order) \ 501 (__c11_atomic_fetch_sub((object), (operand), (order))) 502 #elif LELY_HAVE_GNUC_ATOMIC 503 #define atomic_fetch_sub_explicit(object, operand, order) \ 504 (__atomic_fetch_sub(&(object)->_value_, (operand), (order))) 505 #elif LELY_HAVE_SYNC_ATOMIC 506 #define atomic_fetch_sub_explicit(object, operand, order) \ 507 ((void)(order), __sync_fetch_and_sub(&(object)->_value_, (operand))) 514 #define atomic_fetch_or(object, operand) \ 515 (atomic_fetch_or_explicit((object), (operand), memory_order_seq_cst)) 523 #if LELY_HAVE_CLANG_ATOMIC 524 #define atomic_fetch_or_explicit(object, operand, order) \ 525 (__c11_atomic_fetch_or((object), (operand), (order))) 526 #elif LELY_HAVE_GNUC_ATOMIC 527 #define atomic_fetch_or_explicit(object, operand, order) \ 528 (__atomic_fetch_or(&(object)->_value_, (operand), (order))) 529 #elif LELY_HAVE_SYNC_ATOMIC 530 #define atomic_fetch_or_explicit(object, operand, order) \ 531 ((void)(order), __sync_fetch_and_or(&(object)->_value_, (operand))) 538 #define atomic_fetch_xor(object, operand) \ 539 (atomic_fetch_xor_explicit((object), (operand), memory_order_seq_cst)) 547 #if LELY_HAVE_CLANG_ATOMIC 548 #define atomic_fetch_xor_explicit(object, operand, order) \ 549 (__c11_atomic_fetch_xor((object), (operand), (order))) 550 #elif LELY_HAVE_GNUC_ATOMIC 551 #define atomic_fetch_xor_explicit(object, operand, order) \ 552 (__atomic_fetch_xor(&(object)->_value_, (operand), (order))) 553 #elif LELY_HAVE_SYNC_ATOMIC 554 #define atomic_fetch_xor_explicit(object, operand, order) \ 555 ((void)(order), __sync_fetch_and_xor(&(object)->_value_, (operand))) 562 #define atomic_fetch_and(object, operand) \ 563 (atomic_fetch_and_explicit((object), (operand), memory_order_seq_cst)) 571 #if LELY_HAVE_CLANG_ATOMIC 572 #define atomic_fetch_and_explicit(object, operand, order) \ 573 (__c11_atomic_fetch_and((object), (operand), (order))) 574 #elif LELY_HAVE_GNUC_ATOMIC 575 #define atomic_fetch_and_explicit(object, operand, order) \ 576 (__atomic_fetch_and(&(object)->_value_, (operand), (order))) 577 #elif LELY_HAVE_SYNC_ATOMIC 578 #define atomic_fetch_and_explicit(object, operand, order) \ 579 ((void)(order), __sync_fetch_and_and(&(object)->_value_, (operand))) 592 LELY_LIBC_STDATOMIC_INLINE ATOMIC_BOOL_TYPE atomic_flag_test_and_set_explicit(
593 volatile atomic_flag *
object, memory_order order);
599 LELY_LIBC_STDATOMIC_INLINE ATOMIC_BOOL_TYPE atomic_flag_test_and_set(
600 volatile atomic_flag *
object);
606 LELY_LIBC_STDATOMIC_INLINE
void atomic_flag_clear_explicit(
607 volatile atomic_flag *
object, memory_order order);
613 LELY_LIBC_STDATOMIC_INLINE
void atomic_flag_clear(
volatile atomic_flag *
object);
616 atomic_thread_fence(memory_order order)
618 #if LELY_HAVE_CLANG_ATOMIC 619 __c11_atomic_thread_fence(order);
620 #elif LELY_HAVE_GNUC_ATOMIC 621 __atomic_thread_fence(order);
622 #elif LELY_HAVE_SYNC_ATOMIC 623 if (order != memory_order_relaxed)
624 __sync_synchronize();
629 atomic_signal_fence(memory_order order)
631 #if LELY_HAVE_CLANG_ATOMIC 632 __c11_atomic_signal_fence(order);
633 #elif LELY_HAVE_GNUC_ATOMIC 634 __atomic_signal_fence(order);
635 #elif defined(__GNUC__) 636 if (order != memory_order_relaxed)
637 __asm
volatile(
"" :::
"memory");
641 inline ATOMIC_BOOL_TYPE
642 atomic_flag_test_and_set_explicit(
643 volatile atomic_flag *
object, memory_order order)
645 return atomic_exchange_explicit(&object->_value_, 1, order);
648 inline ATOMIC_BOOL_TYPE
649 atomic_flag_test_and_set(
volatile atomic_flag *
object)
651 return atomic_flag_test_and_set_explicit(
object, memory_order_seq_cst);
655 atomic_flag_clear_explicit(
volatile atomic_flag *
object, memory_order order)
657 atomic_store_explicit(&object->_value_, 0, order);
661 atomic_flag_clear(
volatile atomic_flag *
object)
663 atomic_flag_test_and_set_explicit(
object, memory_order_seq_cst);
670 #endif // !__STDC_NO_ATOMICS__ 672 #endif // !LELY_HAVE_STDATOMIC_H 674 #endif // !LELY_LIBC_STDATOMIC_H_ This header file is part of the C11 and POSIX compatibility library; it includes <stdatomic.h>, if it exists, and defines any missing functionality.
This header file is part of the C11 and POSIX compatibility library; it includes <stddef.h> and defines any missing functionality.
This header file is part of the C11 and POSIX compatibility library; it includes <uchar.h>, if it exists, and defines any missing functionality.
This header file is part of the C11 and POSIX compatibility library; it includes <stdint.h> and defines any missing functionality.
This header file is part of the Lely libraries; it contains the compiler feature definitions.