23 #define P99_ATOMIC_H 1
27 #include P99_ADVANCE_ID
51 #if p99_has_feature(stdatomic_h)
52 # include <stdatomic.h>
55 #define P00_DECLARE_ATOMIC2(T, ...) typedef _Atomic(T) __VA_ARGS__
57 #define P99_DECLARE_ATOMIC(...) \
59 P99_IF_EQ_1(P99_NARG(__VA_ARGS__)) \
60 (P00_DECLARE_ATOMIC2(__VA_ARGS__, P99_PASTE2(atomic_, __VA_ARGS__))) \
61 (P00_DECLARE_ATOMIC2(__VA_ARGS__))
83 #ifdef P99_TEST_ATOMIC
84 # undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
85 # undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
86 # undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
87 # undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
95 #if defined(P00_DOXYGEN) || !defined(__ATOMIC_RELAXED)
100 memory_order_release,
101 memory_order_acq_rel,
106 memory_order_relaxed = __ATOMIC_RELAXED,
107 memory_order_consume = __ATOMIC_CONSUME,
108 memory_order_acquire = __ATOMIC_ACQUIRE,
109 memory_order_release = __ATOMIC_RELEASE,
110 memory_order_acq_rel = __ATOMIC_ACQ_REL,
111 memory_order_seq_cst = __ATOMIC_SEQ_CST,
113 typedef enum memory_order memory_order;
120 #if defined(__GNUC__) && !defined(P00_ATOMIC_NO_GCC)
122 #elif defined(__arm__)
124 #elif defined(__x86_64__) || defined(__i386__)
127 # warning "no support for atomic operations detected for this platform"
128 # define P00_NO_ATOMICS
135 #if !defined(P00_NO_ATOMICS) || defined(P00_DOXYGEN)
161 #ifndef ATOMIC_INT8_LOCK_FREE
162 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)
163 # define ATOMIC_INT8_LOCK_FREE 2
165 # define ATOMIC_INT8_LOCK_FREE 0
168 #if ATOMIC_INT8_LOCK_FREE == 2
169 # define P00_TYPE_LIST_ELEM1 , (1, uint8_t)
171 # define P00_TYPE_LIST_ELEM1
174 #ifndef ATOMIC_INT16_LOCK_FREE
175 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
176 # define ATOMIC_INT16_LOCK_FREE 2
178 # define ATOMIC_INT16_LOCK_FREE 0
181 #if ATOMIC_INT16_LOCK_FREE == 2
182 # define P00_TYPE_LIST_ELEM2 , (2, uint16_t)
184 # define P00_TYPE_LIST_ELEM2
187 #ifndef ATOMIC_INT32_LOCK_FREE
188 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
189 # define ATOMIC_INT32_LOCK_FREE 2
191 # define ATOMIC_INT32_LOCK_FREE 0
194 #if ATOMIC_INT32_LOCK_FREE == 2
195 # define P00_TYPE_LIST_ELEM4 , (4, uint32_t)
197 # define P00_TYPE_LIST_ELEM4
200 #ifndef ATOMIC_INT64_LOCK_FREE
201 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
202 # define ATOMIC_INT64_LOCK_FREE 2
204 # define ATOMIC_INT64_LOCK_FREE 0
207 #if ATOMIC_INT64_LOCK_FREE == 2
208 # define P00_TYPE_LIST_ELEM8 , (8, uint64_t)
210 # define P00_TYPE_LIST_ELEM8
213 #ifndef ATOMIC_INT128_LOCK_FREE
214 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) && (defined(UINT128_MAX) || defined(p99x_uint128))
215 # define ATOMIC_INT128_LOCK_FREE 2
217 # define ATOMIC_INT128_LOCK_FREE 0
220 #if ATOMIC_INT128_LOCK_FREE == 2
221 # if defined(UINT128_MAX)
222 # define P00_TYPE_LIST_ELEM16 , (16, uint128_t)
224 # define P00_TYPE_LIST_ELEM16 , (16, p99x_uint128)
227 # define P00_TYPE_LIST_ELEM16
231 #ifndef ATOMIC_BOOL_LOCK_FREE
232 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) && (UINT_MAX <= UINT32_MAX)
233 #define ATOMIC_BOOL_LOCK_FREE 2
235 #define ATOMIC_BOOL_LOCK_FREE 0
238 #ifndef ATOMIC_CHAR_LOCK_FREE
239 # define ATOMIC_CHAR_LOCK_FREE ATOMIC_INT8_LOCK_FREE
241 #if USHRT_MAX == UINT8_MAX
242 # define ATOMIC_SHORT_LOCK_FREE ATOMIC_INT8_LOCK_FREE
243 #elif USHRT_MAX == UINT16_MAX
244 # define ATOMIC_SHORT_LOCK_FREE ATOMIC_INT16_LOCK_FREE
245 #elif USHRT_MAX == UINT32_MAX
246 # define ATOMIC_SHORT_LOCK_FREE ATOMIC_INT32_LOCK_FREE
247 #elif USHRT_MAX == UINT64_MAX
248 # define ATOMIC_SHORT_LOCK_FREE ATOMIC_INT64_LOCK_FREE
249 #elif USHRT_MAX == UINT128_MAX
250 # define ATOMIC_SHORT_LOCK_FREE ATOMIC_INT128_LOCK_FREE
252 # define ATOMIC_SHORT_LOCK_FREE 0
254 #if UINT_MAX == UINT8_MAX
255 # define ATOMIC_INT_LOCK_FREE ATOMIC_INT8_LOCK_FREE
256 #elif UINT_MAX == UINT16_MAX
257 # define ATOMIC_INT_LOCK_FREE ATOMIC_INT16_LOCK_FREE
258 #elif UINT_MAX == UINT32_MAX
259 # define ATOMIC_INT_LOCK_FREE ATOMIC_INT32_LOCK_FREE
260 #elif UINT_MAX == UINT64_MAX
261 # define ATOMIC_INT_LOCK_FREE ATOMIC_INT64_LOCK_FREE
262 #elif UINT_MAX == UINT128_MAX
263 # define ATOMIC_INT_LOCK_FREE ATOMIC_INT128_LOCK_FREE
265 # define ATOMIC_INT_LOCK_FREE 0
267 #if ULONG_MAX == UINT8_MAX
268 # define ATOMIC_LONG_LOCK_FREE ATOMIC_INT8_LOCK_FREE
269 #elif ULONG_MAX == UINT16_MAX
270 # define ATOMIC_LONG_LOCK_FREE ATOMIC_INT16_LOCK_FREE
271 #elif ULONG_MAX == UINT32_MAX
272 # define ATOMIC_LONG_LOCK_FREE ATOMIC_INT32_LOCK_FREE
273 #elif ULONG_MAX == UINT64_MAX
274 # define ATOMIC_LONG_LOCK_FREE ATOMIC_INT64_LOCK_FREE
275 #elif ULONG_MAX == UINT128_MAX
276 # define ATOMIC_LONG_LOCK_FREE ATOMIC_INT128_LOCK_FREE
278 # define ATOMIC_LONG_LOCK_FREE 0
280 #if ULLONG_MAX == UINT8_MAX
281 # define ATOMIC_LLONG_LOCK_FREE ATOMIC_INT8_LOCK_FREE
282 #elif ULLONG_MAX == UINT16_MAX
283 # define ATOMIC_LLONG_LOCK_FREE ATOMIC_INT16_LOCK_FREE
284 #elif ULLONG_MAX == UINT32_MAX
285 # define ATOMIC_LLONG_LOCK_FREE ATOMIC_INT32_LOCK_FREE
286 #elif ULLONG_MAX == UINT64_MAX
287 # define ATOMIC_LLONG_LOCK_FREE ATOMIC_INT64_LOCK_FREE
288 #elif ULLONG_MAX == UINT128_MAX
289 # define ATOMIC_LLONG_LOCK_FREE ATOMIC_INT128_LOCK_FREE
291 # define ATOMIC_LLONG_LOCK_FREE 0
293 #if UINTPTR_MAX == UINT8_MAX
294 # define ATOMIC_INTPTR_LOCK_FREE ATOMIC_INT8_LOCK_FREE
295 #elif UINTPTR_MAX == UINT16_MAX
296 # define ATOMIC_INTPTR_LOCK_FREE ATOMIC_INT16_LOCK_FREE
297 #elif UINTPTR_MAX == UINT32_MAX
298 # define ATOMIC_INTPTR_LOCK_FREE ATOMIC_INT32_LOCK_FREE
299 #elif UINTPTR_MAX == UINT64_MAX
300 # define ATOMIC_INTPTR_LOCK_FREE ATOMIC_INT64_LOCK_FREE
301 #elif UINTPTR_MAX == UINT128_MAX
302 # define ATOMIC_INTPTR_LOCK_FREE ATOMIC_INT128_LOCK_FREE
304 # define ATOMIC_INTPTR_LOCK_FREE 0
306 #ifndef ATOMIC_POINTER_LOCK_FREE
307 #define ATOMIC_POINTER_LOCK_FREE ATOMIC_INTPTR_LOCK_FREE
309 #if ATOMIC_INTPTR_LOCK_FREE == 2
310 #if UINTPTR_MAX == UINT8_MAX
311 # define P00_UINT_TYPE_LIST \
313 P00_TYPE_LIST_ELEM2 \
314 P00_TYPE_LIST_ELEM4 \
315 P00_TYPE_LIST_ELEM8 \
317 #elif UINTPTR_MAX == UINT16_MAX
318 # define P00_UINT_TYPE_LIST \
320 P00_TYPE_LIST_ELEM1 \
321 P00_TYPE_LIST_ELEM4 \
322 P00_TYPE_LIST_ELEM8 \
324 #elif UINTPTR_MAX == UINT32_MAX
325 # define P00_UINT_TYPE_LIST \
327 P00_TYPE_LIST_ELEM1 \
328 P00_TYPE_LIST_ELEM2 \
329 P00_TYPE_LIST_ELEM8 \
331 #elif UINTPTR_MAX == UINT64_MAX
332 # define P00_UINT_TYPE_LIST \
334 P00_TYPE_LIST_ELEM1 \
335 P00_TYPE_LIST_ELEM2 \
336 P00_TYPE_LIST_ELEM4 \
338 #elif UINTPTR_MAX == UINT128_MAX
339 # define P00_UINT_TYPE_LIST \
341 P00_TYPE_LIST_ELEM1 \
342 P00_TYPE_LIST_ELEM2 \
343 P00_TYPE_LIST_ELEM4 \
346 # define P00_UINT_TYPE_LIST \
348 P00_TYPE_LIST_ELEM2 \
349 P00_TYPE_LIST_ELEM4 \
350 P00_TYPE_LIST_ELEM8 \
354 #if UINT_LEAST16_MAX == UINT16_MAX
355 # define ATOMIC_CHAR16_T_LOCK_FREE ATOMIC_INT16_LOCK_FREE
356 #elif UINT_LEAST16_MAX == UINT32_MAX
357 # define ATOMIC_CHAR16_T_LOCK_FREE ATOMIC_INT32_LOCK_FREE
358 #elif UINT_LEAST16_MAX == UINT64_MAX
359 # define ATOMIC_CHAR16_T_LOCK_FREE ATOMIC_INT64_LOCK_FREE
360 #elif UINT_LEAST16_MAX == UINT128_MAX
361 # define ATOMIC_CHAR16_T_LOCK_FREE ATOMIC_INT128_LOCK_FREE
363 # define ATOMIC_CHAR16_T_LOCK_FREE 0
365 #if UINT_LEAST32_MAX == UINT32_MAX
366 # define ATOMIC_CHAR32_T_LOCK_FREE ATOMIC_INT32_LOCK_FREE
367 #elif UINT_LEAST32_MAX == UINT64_MAX
368 # define ATOMIC_CHAR32_T_LOCK_FREE ATOMIC_INT64_LOCK_FREE
369 #elif UINT_LEAST32_MAX == UINT128_MAX
370 # define ATOMIC_CHAR32_T_LOCK_FREE ATOMIC_INT128_LOCK_FREE
372 # define ATOMIC_CHAR32_T_LOCK_FREE 0
374 #if WCHAR_MAX == UINT8_MAX || (!WCHAR_MIN && (WCHAR_MAX == INT8_MAX))
375 # define ATOMIC_WCHAR_LOCK_FREE ATOMIC_INT8_LOCK_FREE
376 #elif WCHAR_MAX == UINT16_MAX || (!WCHAR_MIN && (WCHAR_MAX == INT16_MAX))
377 # define ATOMIC_WCHAR_LOCK_FREE ATOMIC_INT16_LOCK_FREE
378 #elif WCHAR_MAX == UINT32_MAX || (!WCHAR_MIN && (WCHAR_MAX == INT32_MAX))
379 # define ATOMIC_WCHAR_LOCK_FREE ATOMIC_INT32_LOCK_FREE
380 #elif WCHAR_MAX == UINT64_MAX || (!WCHAR_MIN && (WCHAR_MAX == INT64_MAX))
381 # define ATOMIC_WCHAR_LOCK_FREE ATOMIC_INT64_LOCK_FREE
382 #elif WCHAR_MAX == UINT128_MAX || (!WCHAR_MIN && (WCHAR_MAX == INT128_MAX))
383 # define ATOMIC_WCHAR_LOCK_FREE ATOMIC_INT128_LOCK_FREE
385 # define ATOMIC_WCHAR_LOCK_FREE 0
410 P00_DOCUMENT_TYPE_ARGUMENT(P99_UINT_DEFAULT, 0)
411 #if defined(P00_UINT_TYPE_LIST) || defined(P00_DOXYGEN)
412 # define P99_UINT_DEFAULT(T) \
413 __typeof__(P99_GENERIC_SIZE_LIT(sizeof(T), (uintptr_t){ 0 }, P00_UINT_TYPE_LIST))
415 # define P00_UINT_TYPE_LIST
416 # define P99_UINT_DEFAULT(T) uintptr_t
423 #define ATOMIC_FLAG_INIT P99_ENC_INIT(0)
429 #define ATOMIC_VAR_INIT(...) { .p00_xval = { .p00_t = __VA_ARGS__, }, }
445 #ifndef P99_ATOMIC_LOCK_FREE_TYPES
446 # define P99_ATOMIC_LOCK_FREE_TYPES P00_ATOMIC_LOCK_FREE_TYPES6_
448 #if ATOMIC_BOOL_LOCK_FREE == 2
449 # define P00_ATOMIC_LOCK_FREE_TYPES0 _Bool
451 #if ATOMIC_CHAR_LOCK_FREE == 2
452 # define P00_ATOMIC_LOCK_FREE_TYPES1 char, signed char, unsigned char
454 #if ATOMIC_SHORT_LOCK_FREE == 2
455 # define P00_ATOMIC_LOCK_FREE_TYPES2 short, unsigned short
457 #if ATOMIC_INT_LOCK_FREE == 2
458 # define P00_ATOMIC_LOCK_FREE_TYPES3 int, unsigned int
460 #if ATOMIC_LONG_LOCK_FREE == 2
461 # define P00_ATOMIC_LOCK_FREE_TYPES4 long, unsigned long
463 #if ATOMIC_LLONG_LOCK_FREE == 2
464 # define P00_ATOMIC_LOCK_FREE_TYPES5 long long, unsigned long long
466 #if ATOMIC_POINTER_LOCK_FREE == 2
467 # define P00_ATOMIC_LOCK_FREE_TYPES6 char*, signed char*, unsigned char*
470 #ifdef P00_ATOMIC_LOCK_FREE_TYPES0
471 # ifdef P00_ATOMIC_LOCK_FREE_TYPES1
472 # define P00_ATOMIC_LOCK_FREE_TYPES1_ P00_ATOMIC_LOCK_FREE_TYPES0, P00_ATOMIC_LOCK_FREE_TYPES1
474 # define P00_ATOMIC_LOCK_FREE_TYPES1_ P00_ATOMIC_LOCK_FREE_TYPES0
477 # ifdef P00_ATOMIC_LOCK_FREE_TYPES1
478 # define P00_ATOMIC_LOCK_FREE_TYPES1_ P00_ATOMIC_LOCK_FREE_TYPES1
482 #ifdef P00_ATOMIC_LOCK_FREE_TYPES1_
483 # ifdef P00_ATOMIC_LOCK_FREE_TYPES2
484 # define P00_ATOMIC_LOCK_FREE_TYPES2_ P00_ATOMIC_LOCK_FREE_TYPES1_, P00_ATOMIC_LOCK_FREE_TYPES2
486 # define P00_ATOMIC_LOCK_FREE_TYPES2_ P00_ATOMIC_LOCK_FREE_TYPES1_
489 # ifdef P00_ATOMIC_LOCK_FREE_TYPES2
490 # define P00_ATOMIC_LOCK_FREE_TYPES2_ P00_ATOMIC_LOCK_FREE_TYPES2
494 #ifdef P00_ATOMIC_LOCK_FREE_TYPES2_
495 # ifdef P00_ATOMIC_LOCK_FREE_TYPES3
496 # define P00_ATOMIC_LOCK_FREE_TYPES3_ P00_ATOMIC_LOCK_FREE_TYPES2_, P00_ATOMIC_LOCK_FREE_TYPES3
498 # define P00_ATOMIC_LOCK_FREE_TYPES3_ P00_ATOMIC_LOCK_FREE_TYPES2_
501 # ifdef P00_ATOMIC_LOCK_FREE_TYPES3
502 # define P00_ATOMIC_LOCK_FREE_TYPES3_ P00_ATOMIC_LOCK_FREE_TYPES3
506 #ifdef P00_ATOMIC_LOCK_FREE_TYPES3_
507 # ifdef P00_ATOMIC_LOCK_FREE_TYPES4
508 # define P00_ATOMIC_LOCK_FREE_TYPES4_ P00_ATOMIC_LOCK_FREE_TYPES3_, P00_ATOMIC_LOCK_FREE_TYPES4
510 # define P00_ATOMIC_LOCK_FREE_TYPES4_ P00_ATOMIC_LOCK_FREE_TYPES3_
513 # ifdef P00_ATOMIC_LOCK_FREE_TYPES4
514 # define P00_ATOMIC_LOCK_FREE_TYPES4_ P00_ATOMIC_LOCK_FREE_TYPES4
518 #ifdef P00_ATOMIC_LOCK_FREE_TYPES4_
519 # ifdef P00_ATOMIC_LOCK_FREE_TYPES5
520 # define P00_ATOMIC_LOCK_FREE_TYPES5_ P00_ATOMIC_LOCK_FREE_TYPES4_, P00_ATOMIC_LOCK_FREE_TYPES5
522 # define P00_ATOMIC_LOCK_FREE_TYPES5_ P00_ATOMIC_LOCK_FREE_TYPES4_
525 # ifdef P00_ATOMIC_LOCK_FREE_TYPES5
526 # define P00_ATOMIC_LOCK_FREE_TYPES5_ P00_ATOMIC_LOCK_FREE_TYPES5
530 #ifdef P00_ATOMIC_LOCK_FREE_TYPES5_
531 # ifdef P00_ATOMIC_LOCK_FREE_TYPES6
532 # define P00_ATOMIC_LOCK_FREE_TYPES6_ P00_ATOMIC_LOCK_FREE_TYPES5_, P00_ATOMIC_LOCK_FREE_TYPES6
534 # define P00_ATOMIC_LOCK_FREE_TYPES6_ P00_ATOMIC_LOCK_FREE_TYPES5_
537 # ifdef P00_ATOMIC_LOCK_FREE_TYPES6
538 # define P00_ATOMIC_LOCK_FREE_TYPES6_ P00_ATOMIC_LOCK_FREE_TYPES6
543 #ifndef P00_ATOMIC_LOCK_FREE_TYPES6_
544 # define P00_ATOMIC_LOCK_FREE_TYPES6_
556 typedef uint32_t
volatile p00_atomic_flag;
575 #define P00_AX(OBJP) ((OBJP)->p00_xval)
576 #define P00_AT(OBJP) (P00_AX(OBJP).p00_t)
577 #define P00_AO(OBJP) (P00_AX(OBJP).p00_o)
578 #define P00_AM(OBJP) (P00_AX(OBJP).p00_m)
580 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P00_DECLARE_ATOMIC_TYPE, 0)
581 P00_DOCUMENT_TYPE_ARGUMENT(P00_DECLARE_ATOMIC_TYPE, 1)
582 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P00_DECLARE_ATOMIC_TYPE, 2)
583 #define P00_DECLARE_ATOMIC_TYPE(TAGGER, TI, T, NAME) \
584 TAGGER P99_PASTE3(NAME, _, TAGGER) { \
585 atomic_flag p00_lock; \
588 P99_UINT_DEFAULT(T) p00_m; \
592 typedef TAGGER P99_PASTE3(NAME, _, TAGGER) P99_PASTE3(NAME, _, TAGGER)
602 P00_DOCUMENT_TYPE_ARGUMENT(P99_DECLARE_ATOMIC_LOCK_FREE, 0)
603 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_ATOMIC_LOCK_FREE, 1)
605 # define P99_DECLARE_ATOMIC_LOCK_FREE(T, NAME) \
607 typedef P99_PASTE3(p99_, NAME, _union) NAME
609 #define P99_DECLARE_ATOMIC_LOCK_FREE(T, NAME) \
610 P00_DECLARE_ATOMIC_TYPE(union, T, T, P99_PASTE2(p99_, NAME)); \
611 P00_DECLARE_ATOMIC_TYPE(struct, uintptr_t, T, P99_PASTE2(p99_, NAME)); \
612 typedef P99_PASTE3(p99_, NAME, _union) NAME
616 #define P00_DECLARE_ATOMIC2(T, ...) \
617 P00_DECLARE_ATOMIC_TYPE(union, T, T, P99_PASTE(p99_, __VA_ARGS__)); \
618 P00_DECLARE_ATOMIC_TYPE(struct, uintptr_t, T, P99_PASTE(p99_, __VA_ARGS__)); \
620 typedef P99_PASTE(p99_, __VA_ARGS__, _struct) __VA_ARGS__
644 #define P99_DECLARE_ATOMIC(T, NAME)
646 #define P99_DECLARE_ATOMIC(...) \
648 P99_IF_EQ_1(P99_NARG(__VA_ARGS__)) \
649 (P00_DECLARE_ATOMIC2(__VA_ARGS__, P99_PASTE2(atomic_, __VA_ARGS__))) \
650 (P00_DECLARE_ATOMIC2(__VA_ARGS__))
653 #define P00_DECLARE_ATOMIC(T, ...) \
655 typedef P00_ATOMIC_STRUCT(T, __VA_ARGS__) __VA_ARGS__
657 #define P00_DECLARE_ATOMIC_CHOICE(MAC, T, NAME) \
659 (P99_DECLARE_ATOMIC_LOCK_FREE(T, NAME)) \
660 (P99_DECLARE_ATOMIC(T, NAME))
669 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_INT_LOCK_FREE,
int, atomic_int);
680 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_BOOL_LOCK_FREE, _Bool, atomic_bool);
683 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_CHAR_LOCK_FREE,
char, atomic_char);
684 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_CHAR_LOCK_FREE,
signed char, atomic_schar);
685 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_CHAR_LOCK_FREE,
unsigned char, atomic_uchar);
686 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_SHORT_LOCK_FREE,
short, atomic_short);
687 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_SHORT_LOCK_FREE,
unsigned short, atomic_ushort);
688 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_INT_LOCK_FREE,
unsigned int, atomic_uint);
689 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_LONG_LOCK_FREE,
long, atomic_long);
690 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_LONG_LOCK_FREE,
unsigned long, atomic_ulong);
691 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_LLONG_LOCK_FREE,
long long, atomic_llong);
692 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_LONG_LOCK_FREE,
unsigned long long, atomic_ullong);
694 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_POINTER_LOCK_FREE,
void*, atomic_void_ptr);
695 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_POINTER_LOCK_FREE,
char*, atomic_char_ptr);
696 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_POINTER_LOCK_FREE,
signed char*, atomic_schar_ptr);
697 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_POINTER_LOCK_FREE,
unsigned char*, atomic_uchar_ptr);
703 #ifndef __STDC_NO_COMPLEX__
707 #define P00_ATOMIC_TYPES \
708 (_Bool, atomic_bool*), \
709 (char, atomic_char*), \
710 (signed char, atomic_schar*), \
711 (unsigned char, atomic_uchar*), \
712 (short int, atomic_short*), \
713 (unsigned short int, atomic_ushort*), \
714 (int, atomic_int*), \
715 (unsigned int, atomic_uint*), \
716 (long int, atomic_long*), \
717 (unsigned long int, atomic_ulong*), \
718 (long long int, atomic_llong*), \
719 (unsigned long long int, atomic_ullong*), \
720 (float, atomic_float*), \
721 (double, atomic_double*), \
722 (long double, atomic_ldouble*), \
723 (float _Complex, atomic_cfloat*), \
724 (double _Complex, atomic_cdouble*), \
725 (long double _Complex, atomic_cldouble*)
727 #define P00_ATOMIC_TYPES \
728 (_Bool, atomic_bool*), \
729 (char, atomic_char*), \
730 (signed char, atomic_schar*), \
731 (unsigned char, atomic_uchar*), \
732 (short int, atomic_short*), \
733 (unsigned short int, atomic_ushort*), \
734 (int, atomic_int*), \
735 (unsigned int, atomic_uint*), \
736 (long int, atomic_long*), \
737 (unsigned long int, atomic_ulong*), \
738 (long long int, atomic_llong*), \
739 (unsigned long long int, atomic_ullong*), \
740 (float, atomic_float*), \
741 (double, atomic_double*), \
742 (long double, atomic_ldouble*)
746 P00_DOCUMENT_TYPE_ARGUMENT(P99_ATOMIC_INHERIT, 0)
747 #define P99_ATOMIC_INHERIT(T) \
750 P99_GENERIC_SIZE_LIT \
752 (struct P99_PASTE3(p99_atomic_, T, _struct)*){ 0 }, \
753 (1, union P99_PASTE3(p99_atomic_, T, _union)*) \
754 P99_IF_EQ_2(ATOMIC_INT8_LOCK_FREE)(,(2, union P99_PASTE3(p99_atomic_, T, _union)*))() \
755 P99_IF_EQ_2(ATOMIC_INT16_LOCK_FREE)(,(3, union P99_PASTE3(p99_atomic_, T, _union)*))() \
756 P99_IF_EQ_2(ATOMIC_INT32_LOCK_FREE)(,(5, union P99_PASTE3(p99_atomic_, T, _union)*))() \
757 P99_IF_EQ_2(ATOMIC_INT64_LOCK_FREE)(,(9, union P99_PASTE3(p99_atomic_, T, _union)*))() \
758 P99_IF_EQ_2(ATOMIC_INT128_LOCK_FREE)(,(17, union P99_PASTE3(p99_atomic_, T, _union)*))() \
765 #define P00_EXCHANGE(X) \
768 p00_exchange_ignore, \
769 (1, p00_atomic_exchange_1), \
770 (2, p00_atomic_exchange_2), \
771 (4, p00_atomic_exchange_4) \
772 P99_IF_EQ_2(ATOMIC_INT64_LOCK_FREE)(,(8, p00_atomic_exchange_8))() \
773 P99_IF_EQ_2(ATOMIC_INT128_LOCK_FREE)(,(16, p00_atomic_exchange_16))() \
867 # define _Atomic(T) P99_PASTE2(atomic_, T)
869 # define _Atomic(T) __typeof__(P99_ATOMIC_INHERIT(T))
872 typedef _Atomic(
char16_t) atomic_char16_t;
873 typedef _Atomic(
char32_t) atomic_char32_t;
874 typedef _Atomic(
wchar_t) atomic_wchar_t;
875 typedef _Atomic(int_least8_t) atomic_int_least8_t;
876 typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
877 typedef _Atomic(int_least16_t) atomic_int_least16_t;
878 typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
879 typedef _Atomic(int_least32_t) atomic_int_least32_t;
880 typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
881 typedef _Atomic(int_least64_t) atomic_int_least64_t;
882 typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
883 typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
884 typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
885 typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
886 typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
887 typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
888 typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
889 typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
890 typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
891 typedef _Atomic(intptr_t) atomic_intptr_t;
892 typedef _Atomic(uintptr_t) atomic_uintptr_t;
893 typedef _Atomic(
size_t) atomic_size_t;
894 typedef _Atomic(
ptrdiff_t) atomic_ptrdiff_t;
895 typedef _Atomic(intmax_t) atomic_intmax_t;
896 typedef _Atomic(
uintmax_t) atomic_uintmax_t;
911 #define atomic_thread_fence p00_mfence
917 #define atomic_signal_fence atomic_thread_fence
935 #define atomic_flag_test_and_set_explicit(OBJ, ORD) p00_sync_lock_test_and_set(&P99_ENCP(OBJ), (ORD))
947 #define atomic_flag_test_and_set(OBJ) p00_sync_lock_test_and_set(&P99_ENCP(OBJ))
960 #define atomic_flag_clear_explicit(OBJ, ORD) p00_sync_lock_release(&P99_ENCP(OBJ), (ORD))
967 #define atomic_flag_clear(OBJ) p00_sync_lock_release(&P99_ENCP(OBJ))
985 #define atomic_is_lock_free(OBJP) (!offsetof(__typeof__(*OBJP), p00_xval))
987 #define P00_ATOMIC_TERN(OBJP, VAL, ALT) P99_TYPED_TERN(atomic_is_lock_free(OBJP), (VAL), (ALT))
999 #define atomic_init(OBJP, VAL) \
1002 P99_MAC_ARGS((p00_objp, OBJP), (p00_val, VAL)); \
1004 memset((void*)p00_objp, 0, sizeof *p00_objp); \
1005 P00_AT(p00_objp) = p00_val; \
1022 #define atomic_exchange_explicit(OBJP, DESIRED, ORD)
1024 #define atomic_exchange_explicit(OBJP, DESIRED, ORD) \
1027 P99_MACRO_PVAR(p00_objp, (OBJP), volatile); \
1028 typedef __typeof__(P00_AT(p00_objp)) p00_base_t; \
1029 typedef __typeof__(P00_AX(p00_objp)) p00_ubase_t; \
1030 register p00_base_t const p00_des = (DESIRED); \
1031 register p00_ubase_t p00_ret = P99_INIT; \
1032 if (!atomic_is_lock_free(p00_objp)) { \
1033 P99_SPIN_EXCLUDE(&p00_objp->p00_lock) { \
1034 p00_ret.p00_t = P00_AT(p00_objp); \
1035 P00_AT(p00_objp) = p00_des; \
1038 P99_IF_EMPTY(P99_ATOMIC_LOCK_FREE_TYPES) \
1040 (register p00_ubase_t const p00_desm = { .p00_t = p00_des }; \
1041 p00_ret.p00_m = p00_atomic_exchange_n(&P00_AM(p00_objp), p00_desm.p00_m, (ORD))); \
1058 #define atomic_exchange(OBJP, DESIRED) \
1059 atomic_exchange_explicit((OBJP), (DESIRED), memory_order_seq_cst)
1073 #define atomic_load_explicit(OBJP, ORD) \
1076 P99_MACRO_PVAR(p00_objp, (OBJP), volatile); \
1077 typedef __typeof__(P00_AX(p00_objp)) p00_ubase_t; \
1078 register p00_ubase_t p00_ret = P99_INIT; \
1079 if (!atomic_is_lock_free(p00_objp)) { \
1080 P99_SPIN_EXCLUDE(&p00_objp->p00_lock) \
1081 p00_ret.p00_t = P00_AT(p00_objp); \
1083 P99_IF_EMPTY(P99_ATOMIC_LOCK_FREE_TYPES) \
1084 (P00_AT(p00_objp)) \
1085 (p00_ret.p00_m = p00_atomic_load_n(&P00_AM(p00_objp), (ORD))); \
1087 p00_ret.p00_t = p00_ret.p00_t; \
1093 #define atomic_load(OBJP) atomic_load_explicit((OBJP), memory_order_seq_cst)
1096 #define P00_CVT(EXP) ((void const*)(((struct { void const volatile* a; }){ .a = (EXP) }).a))
1117 #define atomic_compare_exchange_weak_explicit(OBJP, EXPECTED, DESIRED, SUCC, FAIL) \
1118 p00_atomic_compare_exchange(true, OBJP, EXPECTED, DESIRED, SUCC, FAIL,)
1120 #define atomic_compare_exchange_weak(OBJP, EXPECTED, DESIRED) \
1121 atomic_compare_exchange_weak_explicit(OBJP, EXPECTED, DESIRED, memory_order_seq_cst, memory_order_seq_cst)
1123 #define atomic_compare_exchange_strong_explicit(OBJP, EXPECTED, DESIRED, SUCC, FAIL) \
1124 p00_atomic_compare_exchange(false, OBJP, EXPECTED, DESIRED, SUCC, FAIL,)
1126 #define atomic_compare_exchange_strong(OBJP, EXPECTED, DESIRED) \
1127 atomic_compare_exchange_strong_explicit(OBJP, EXPECTED, DESIRED, memory_order_seq_cst, memory_order_seq_cst)
1129 #define p00_atomic_compare_exchange(WEAK, OBJP, EXPECTED, DESIRED, SUCC, FAIL, ...) \
1132 P99_MACRO_PVAR(p00_objp, (OBJP), volatile); \
1133 typedef __typeof__(P00_AT(p00_objp)) p00_base_t; \
1134 typedef __typeof__(P00_AX(p00_objp)) p00_ubase_t; \
1135 typedef __typeof__(P00_AM(p00_objp)) p00_mbase_t; \
1137 register p00_base_t volatile* const p00_exp = (EXPECTED); \
1138 register p00_ubase_t const p00_des = { .p00_t = (DESIRED) }; \
1139 register _Bool p00_ret = false; \
1140 if (!atomic_is_lock_free(p00_objp)) { \
1141 P99_SPIN_EXCLUDE(&p00_objp->p00_lock) { \
1142 p00_ret = !memcmp(P00_CVT(p00_exp), P00_CVT(&P00_AT(p00_objp)), sizeof *p00_exp); \
1143 if (p00_ret) P00_AT(p00_objp) = p00_des.p00_t; \
1144 else *p00_exp = P00_AT(p00_objp); \
1147 P99_IF_EMPTY(P99_ATOMIC_LOCK_FREE_TYPES) \
1148 (else p00_ret = false;) \
1149 (else p00_ret = p00_atomic_compare_exchange_n(&P00_AM(p00_objp), ((p00_mbase_t*)p00_exp), p00_des.p00_m, \
1150 (WEAK), memory_order_seq_cst, memory_order_seq_cst); \
1169 #define atomic_store_explicit(OBJP, DES, ORD)
1171 #define atomic_store_explicit(OBJP, DES, ORD) \
1174 P99_MACRO_PVAR(p00_objp, (OBJP), volatile); \
1175 P99_MACRO_VAR(p00_desp, (DES)); \
1176 typedef __typeof__(P00_AX(p00_objp)) p00_ubase_t; \
1177 register p00_ubase_t const p00_des = { .p00_t = (p00_desp) }; \
1178 if (!atomic_is_lock_free(p00_objp)) { \
1179 P99_SPIN_EXCLUDE(&p00_objp->p00_lock) \
1180 P00_AT(p00_objp) = p00_des.p00_t; \
1182 P99_IF_EMPTY(P99_ATOMIC_LOCK_FREE_TYPES) \
1183 (P00_AT(p00_objp)) \
1184 (p00_atomic_store_n(&P00_AM(p00_objp), p00_des.p00_m, (ORD))); \
1192 #define atomic_store(OBJP, DES) atomic_store_explicit(OBJP, DES, memory_order_seq_cst)
1195 #define P00_FETCH_OP(OBJP, OPERAND, BUILTIN, OPERATOR, ORD) \
1198 P99_MACRO_PVAR(p00_objp, (OBJP), volatile); \
1199 P99_MACRO_VAR(p00_op, OPERAND); \
1200 ((!atomic_is_lock_free(p00_objp)) \
1202 register __typeof__(P00_AT(p00_objp)) p00_ret = P99_INIT; \
1203 P99_SPIN_EXCLUDE(&p00_objp->p00_lock) { \
1204 p00_ret = P00_AT(p00_objp); \
1205 P00_AT(p00_objp) OPERATOR p00_op; \
1209 : (P99_IF_EMPTY(P99_ATOMIC_LOCK_FREE_TYPES) \
1210 (P00_AT(p00_objp)) \
1211 (P00_ATOMIC_TERN(p00_objp, \
1212 BUILTIN(&P00_AO(p00_objp), \
1213 P00_ATOMIC_TERN(p00_objp, p00_op, 0), \
1215 P00_AT(p00_objp))))); \
1235 #define atomic_fetch_add_explicit(OBJP, OPERAND, ORD) \
1236 P00_FETCH_OP((OBJP), (OPERAND), p00_atomic_fetch_add, +=, (ORD))
1238 #define atomic_fetch_add(OBJP, OPERAND) atomic_fetch_add_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1257 #define atomic_fetch_sub_explicit(OBJP, OPERAND, ORD) \
1258 P00_FETCH_OP((OBJP), (OPERAND), p00_atomic_fetch_sub, -=, ORD)
1260 #define atomic_fetch_sub(OBJP, OPERAND) atomic_fetch_sub_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1280 #define atomic_fetch_or_explicit(OBJP, OPERAND, ORD) \
1281 P00_FETCH_OP((OBJP), (OPERAND), p00_atomic_fetch_or, |=, (ORD))
1283 #define atomic_fetch_or(OBJP, OPERAND) atomic_fetch_or_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1303 #define atomic_fetch_and_explicit(OBJP, OPERAND, ORD) \
1304 P00_FETCH_OP((OBJP), (OPERAND), p00_atomic_fetch_and, &=, (ORD))
1306 #define atomic_fetch_and(OBJP, OPERAND) atomic_fetch_and_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1327 #define atomic_fetch_xor_explicit(OBJP, OPERAND, ORD) \
1328 P00_FETCH_OP((OBJP), (OPERAND), p00_atomic_fetch_xor, ^=, (ORD))
1330 #define atomic_fetch_xor(OBJP, OPERAND) atomic_fetch_xor_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1332 #define atomic_fetch_add_conditional(OBJP, OPERAND) \
1335 P99_MACRO_VAR(p00_objp, (OBJP)); \
1336 P99_MACRO_VAR(p00_op, (OPERAND)); \
1337 __typeof__(P00_AT(p00_objp)) p00_ret; \
1339 register __typeof__(p00_ret = p00_ret) p00_r = atomic_load(p00_objp); \
1342 P99_MACRO_VAR(p00_des, p00_ret + p00_op); \
1343 if (atomic_compare_exchange_weak(p00_objp, &p00_ret, p00_des)) break; \
1344 else p00_r = p00_ret; \
1355 #undef P00_NO_ATOMICS
1363 #define atomic_fetch_max(OBJP, OPERAND) atomic_fetch_max_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1382 #define atomic_fetch_max_explicit(OBJP, OPERAND, ORD) \
1385 P99_MACRO_VAR(p00_objp, (OBJP)); \
1386 P99_MACRO_VAR(p00_op, (OPERAND)); \
1387 __typeof__(atomic_load(p00_objp)) p00_ret; \
1389 register __typeof__(p00_ret = p00_ret) p00_r = atomic_load(p00_objp); \
1391 while (p00_r <= p00_op) { \
1392 if (atomic_compare_exchange_weak(p00_objp, &p00_ret, p00_op)) break; \
1393 else p00_r = p00_ret; \
1431 #define P99_CRITICAL P00_CRITICAL(P99_UNIQ(crit))
1433 #define P00_CRITICAL(ID) \
1435 P00_BLK_DECL_STATIC(atomic_flag, ID, ATOMIC_FLAG_INIT) \
1436 P99_SPIN_EXCLUDE(ID)