P99
p99_atomic.h
Go to the documentation of this file.
1 /* This may look like nonsense, but it really is -*- mode: C; coding: utf-8 -*- */
2 /* */
3 /* Except for parts copied from previous work and as explicitly stated below, */
4 /* the authors and copyright holders for this work are as follows: */
5 /* (C) copyright 2011-2014 Jens Gustedt, INRIA, France */
6 /* (C) copyright 2012 William Morris */
7 /* */
8 /* This file is free software; it is part of the P99 project. */
9 /* */
10 /* Licensed under the Apache License, Version 2.0 (the "License"); */
11 /* you may not use this file except in compliance with the License. */
12 /* You may obtain a copy of the License at */
13 /* */
14 /* http://www.apache.org/licenses/LICENSE-2.0 */
15 /* */
16 /* Unless required by applicable law or agreed to in writing, software */
17 /* distributed under the License is distributed on an "AS IS" BASIS, */
18 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
19 /* See the License for the specific language governing permissions and */
20 /* limitations under the License. */
21 /* */
22 #ifndef P99_ATOMIC_H
23 #define P99_ATOMIC_H 1
24 
25 #include "p99_enum.h"
26 #include "p99_generic.h"
27 #include P99_ADVANCE_ID
28 
51 #if p99_has_feature(stdatomic_h)
52 # include <stdatomic.h>
53 # include "p99_atomic_flag.h"
54 
55 #define P00_DECLARE_ATOMIC2(T, ...) typedef _Atomic(T) __VA_ARGS__
56 
57 #define P99_DECLARE_ATOMIC(...) \
58  \
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__))
62 
64 P99_DECLARE_ATOMIC(double);
65 
66 #else
67 
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
88 #endif
89 
95 #if defined(P00_DOXYGEN) || !defined(__ATOMIC_RELAXED)
96 P99_DECLARE_ENUM(memory_order,
97  memory_order_relaxed,
98  memory_order_consume,
99  memory_order_acquire,
100  memory_order_release,
101  memory_order_acq_rel,
102  memory_order_seq_cst
103  );
104 #else
105 enum memory_order {
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,
112 };
113 typedef enum memory_order memory_order;
114 #endif
115 
120 #if defined(__GNUC__) && !defined(P00_ATOMIC_NO_GCC)
121 # include "p99_atomic_gcc.h"
122 #elif defined(__arm__)
123 # include "p99_atomic_arm.h"
124 #elif defined(__x86_64__) || defined(__i386__)
125 # include "p99_atomic_x86.h"
126 #else
127 # warning "no support for atomic operations detected for this platform"
128 # define P00_NO_ATOMICS
129 #endif
130 
135 #if !defined(P00_NO_ATOMICS) || defined(P00_DOXYGEN)
136 
161 #ifndef ATOMIC_INT8_LOCK_FREE
162 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)
163 # define ATOMIC_INT8_LOCK_FREE 2
164 # else
165 # define ATOMIC_INT8_LOCK_FREE 0
166 # endif
167 #endif
168 #if ATOMIC_INT8_LOCK_FREE == 2
169 # define P00_TYPE_LIST_ELEM1 , (1, uint8_t)
170 #else
171 # define P00_TYPE_LIST_ELEM1
172 #endif
173 
174 #ifndef ATOMIC_INT16_LOCK_FREE
175 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
176 # define ATOMIC_INT16_LOCK_FREE 2
177 # else
178 # define ATOMIC_INT16_LOCK_FREE 0
179 # endif
180 #endif
181 #if ATOMIC_INT16_LOCK_FREE == 2
182 # define P00_TYPE_LIST_ELEM2 , (2, uint16_t)
183 #else
184 # define P00_TYPE_LIST_ELEM2
185 #endif
186 
187 #ifndef ATOMIC_INT32_LOCK_FREE
188 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
189 # define ATOMIC_INT32_LOCK_FREE 2
190 # else
191 # define ATOMIC_INT32_LOCK_FREE 0
192 # endif
193 #endif
194 #if ATOMIC_INT32_LOCK_FREE == 2
195 # define P00_TYPE_LIST_ELEM4 , (4, uint32_t)
196 #else
197 # define P00_TYPE_LIST_ELEM4
198 #endif
199 
200 #ifndef ATOMIC_INT64_LOCK_FREE
201 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
202 # define ATOMIC_INT64_LOCK_FREE 2
203 # else
204 # define ATOMIC_INT64_LOCK_FREE 0
205 # endif
206 #endif
207 #if ATOMIC_INT64_LOCK_FREE == 2
208 # define P00_TYPE_LIST_ELEM8 , (8, uint64_t)
209 #else
210 # define P00_TYPE_LIST_ELEM8
211 #endif
212 
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
216 # else
217 # define ATOMIC_INT128_LOCK_FREE 0
218 # endif
219 #endif
220 #if ATOMIC_INT128_LOCK_FREE == 2
221 # if defined(UINT128_MAX)
222 # define P00_TYPE_LIST_ELEM16 , (16, uint128_t)
223 # else
224 # define P00_TYPE_LIST_ELEM16 , (16, p99x_uint128)
225 # endif
226 #else
227 # define P00_TYPE_LIST_ELEM16
228 #endif
229 
230 
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
234 # else
235 #define ATOMIC_BOOL_LOCK_FREE 0
236 # endif
237 #endif
238 #ifndef ATOMIC_CHAR_LOCK_FREE
239 # define ATOMIC_CHAR_LOCK_FREE ATOMIC_INT8_LOCK_FREE
240 #endif
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
251 #else
252 # define ATOMIC_SHORT_LOCK_FREE 0
253 #endif
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
264 #else
265 # define ATOMIC_INT_LOCK_FREE 0
266 #endif
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
277 #else
278 # define ATOMIC_LONG_LOCK_FREE 0
279 #endif
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
290 #else
291 # define ATOMIC_LLONG_LOCK_FREE 0
292 #endif
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
303 #else
304 # define ATOMIC_INTPTR_LOCK_FREE 0
305 #endif
306 #ifndef ATOMIC_POINTER_LOCK_FREE
307 #define ATOMIC_POINTER_LOCK_FREE ATOMIC_INTPTR_LOCK_FREE
308 #endif
309 #if ATOMIC_INTPTR_LOCK_FREE == 2
310 #if UINTPTR_MAX == UINT8_MAX
311 # define P00_UINT_TYPE_LIST \
312  (1, uintptr_t) \
313  P00_TYPE_LIST_ELEM2 \
314  P00_TYPE_LIST_ELEM4 \
315  P00_TYPE_LIST_ELEM8 \
316  P00_TYPE_LIST_ELEM16
317 #elif UINTPTR_MAX == UINT16_MAX
318 # define P00_UINT_TYPE_LIST \
319  (2, uintptr_t) \
320  P00_TYPE_LIST_ELEM1 \
321  P00_TYPE_LIST_ELEM4 \
322  P00_TYPE_LIST_ELEM8 \
323  P00_TYPE_LIST_ELEM16
324 #elif UINTPTR_MAX == UINT32_MAX
325 # define P00_UINT_TYPE_LIST \
326  (4, uintptr_t) \
327  P00_TYPE_LIST_ELEM1 \
328  P00_TYPE_LIST_ELEM2 \
329  P00_TYPE_LIST_ELEM8 \
330  P00_TYPE_LIST_ELEM16
331 #elif UINTPTR_MAX == UINT64_MAX
332 # define P00_UINT_TYPE_LIST \
333  (8, uintptr_t) \
334  P00_TYPE_LIST_ELEM1 \
335  P00_TYPE_LIST_ELEM2 \
336  P00_TYPE_LIST_ELEM4 \
337  P00_TYPE_LIST_ELEM16
338 #elif UINTPTR_MAX == UINT128_MAX
339 # define P00_UINT_TYPE_LIST \
340  (16, uintptr_t) \
341  P00_TYPE_LIST_ELEM1 \
342  P00_TYPE_LIST_ELEM2 \
343  P00_TYPE_LIST_ELEM4 \
344  P00_TYPE_LIST_ELEM8
345 #else
346 # define P00_UINT_TYPE_LIST \
347  (1, uint8_t) \
348  P00_TYPE_LIST_ELEM2 \
349  P00_TYPE_LIST_ELEM4 \
350  P00_TYPE_LIST_ELEM8 \
351  P00_TYPE_LIST_ELEM16
352 #endif
353 #endif
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
362 #else
363 # define ATOMIC_CHAR16_T_LOCK_FREE 0
364 #endif
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
371 #else
372 # define ATOMIC_CHAR32_T_LOCK_FREE 0
373 #endif
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
384 #else
385 # define ATOMIC_WCHAR_LOCK_FREE 0
386 #endif
387 
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))
414 #else
415 # define P00_UINT_TYPE_LIST
416 # define P99_UINT_DEFAULT(T) uintptr_t
417 #endif
418 
423 #define ATOMIC_FLAG_INIT P99_ENC_INIT(0)
424 
429 #define ATOMIC_VAR_INIT(...) { .p00_xval = { .p00_t = __VA_ARGS__, }, }
430 
445 #ifndef P99_ATOMIC_LOCK_FREE_TYPES
446 # define P99_ATOMIC_LOCK_FREE_TYPES P00_ATOMIC_LOCK_FREE_TYPES6_
447 
448 #if ATOMIC_BOOL_LOCK_FREE == 2
449 # define P00_ATOMIC_LOCK_FREE_TYPES0 _Bool
450 #endif
451 #if ATOMIC_CHAR_LOCK_FREE == 2
452 # define P00_ATOMIC_LOCK_FREE_TYPES1 char, signed char, unsigned char
453 #endif
454 #if ATOMIC_SHORT_LOCK_FREE == 2
455 # define P00_ATOMIC_LOCK_FREE_TYPES2 short, unsigned short
456 #endif
457 #if ATOMIC_INT_LOCK_FREE == 2
458 # define P00_ATOMIC_LOCK_FREE_TYPES3 int, unsigned int
459 #endif
460 #if ATOMIC_LONG_LOCK_FREE == 2
461 # define P00_ATOMIC_LOCK_FREE_TYPES4 long, unsigned long
462 #endif
463 #if ATOMIC_LLONG_LOCK_FREE == 2
464 # define P00_ATOMIC_LOCK_FREE_TYPES5 long long, unsigned long long
465 #endif
466 #if ATOMIC_POINTER_LOCK_FREE == 2
467 # define P00_ATOMIC_LOCK_FREE_TYPES6 char*, signed char*, unsigned char*
468 #endif
469 
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
473 # else
474 # define P00_ATOMIC_LOCK_FREE_TYPES1_ P00_ATOMIC_LOCK_FREE_TYPES0
475 # endif
476 #else
477 # ifdef P00_ATOMIC_LOCK_FREE_TYPES1
478 # define P00_ATOMIC_LOCK_FREE_TYPES1_ P00_ATOMIC_LOCK_FREE_TYPES1
479 # endif
480 #endif
481 
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
485 # else
486 # define P00_ATOMIC_LOCK_FREE_TYPES2_ P00_ATOMIC_LOCK_FREE_TYPES1_
487 # endif
488 #else
489 # ifdef P00_ATOMIC_LOCK_FREE_TYPES2
490 # define P00_ATOMIC_LOCK_FREE_TYPES2_ P00_ATOMIC_LOCK_FREE_TYPES2
491 # endif
492 #endif
493 
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
497 # else
498 # define P00_ATOMIC_LOCK_FREE_TYPES3_ P00_ATOMIC_LOCK_FREE_TYPES2_
499 # endif
500 #else
501 # ifdef P00_ATOMIC_LOCK_FREE_TYPES3
502 # define P00_ATOMIC_LOCK_FREE_TYPES3_ P00_ATOMIC_LOCK_FREE_TYPES3
503 # endif
504 #endif
505 
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
509 # else
510 # define P00_ATOMIC_LOCK_FREE_TYPES4_ P00_ATOMIC_LOCK_FREE_TYPES3_
511 # endif
512 #else
513 # ifdef P00_ATOMIC_LOCK_FREE_TYPES4
514 # define P00_ATOMIC_LOCK_FREE_TYPES4_ P00_ATOMIC_LOCK_FREE_TYPES4
515 # endif
516 #endif
517 
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
521 # else
522 # define P00_ATOMIC_LOCK_FREE_TYPES5_ P00_ATOMIC_LOCK_FREE_TYPES4_
523 # endif
524 #else
525 # ifdef P00_ATOMIC_LOCK_FREE_TYPES5
526 # define P00_ATOMIC_LOCK_FREE_TYPES5_ P00_ATOMIC_LOCK_FREE_TYPES5
527 # endif
528 #endif
529 
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
533 # else
534 # define P00_ATOMIC_LOCK_FREE_TYPES6_ P00_ATOMIC_LOCK_FREE_TYPES5_
535 # endif
536 #else
537 # ifdef P00_ATOMIC_LOCK_FREE_TYPES6
538 # define P00_ATOMIC_LOCK_FREE_TYPES6_ P00_ATOMIC_LOCK_FREE_TYPES6
539 # endif
540 #endif
541 #endif
542 
543 #ifndef P00_ATOMIC_LOCK_FREE_TYPES6_
544 # define P00_ATOMIC_LOCK_FREE_TYPES6_
545 #endif
546 
556 typedef uint32_t volatile p00_atomic_flag;
557 
573 P99_ENC_DECLARE(p00_atomic_flag, atomic_flag);
574 
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)
579 
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; \
586  union { \
587  TI p00_o; \
588  P99_UINT_DEFAULT(T) p00_m; \
589  T p00_t; \
590  } p00_xval; \
591 }; \
592 typedef TAGGER P99_PASTE3(NAME, _, TAGGER) P99_PASTE3(NAME, _, TAGGER)
593 
594 
602 P00_DOCUMENT_TYPE_ARGUMENT(P99_DECLARE_ATOMIC_LOCK_FREE, 0)
603 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_ATOMIC_LOCK_FREE, 1)
604 #ifdef P00_DOXYGEN
605 # define P99_DECLARE_ATOMIC_LOCK_FREE(T, NAME) \
606  \
607 typedef P99_PASTE3(p99_, NAME, _union) NAME
608 #else
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
613 #endif
614 
615 
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__)); \
619  \
620 typedef P99_PASTE(p99_, __VA_ARGS__, _struct) __VA_ARGS__
621 
641 P00_DOCUMENT_TYPE_ARGUMENT(P99_DECLARE_ATOMIC, 0)
642 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_ATOMIC, 1)
643 #ifdef P00_DOXYGEN
644 #define P99_DECLARE_ATOMIC(T, NAME)
645 #else
646 #define P99_DECLARE_ATOMIC(...) \
647  \
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__))
651 #endif
652 
653 #define P00_DECLARE_ATOMIC(T, ...) \
654  \
655 typedef P00_ATOMIC_STRUCT(T, __VA_ARGS__) __VA_ARGS__
656 
657 #define P00_DECLARE_ATOMIC_CHOICE(MAC, T, NAME) \
658 P99_IF_EQ_2(MAC) \
659 (P99_DECLARE_ATOMIC_LOCK_FREE(T, NAME)) \
660 (P99_DECLARE_ATOMIC(T, NAME))
661 
662 
669 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_INT_LOCK_FREE, int, atomic_int);
670 
680 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_BOOL_LOCK_FREE, _Bool, atomic_bool);
681 
682 
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);
693 
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);
698 
699 P99_DECLARE_ATOMIC(float, atomic_float);
700 P99_DECLARE_ATOMIC(double, atomic_double);
701 P99_DECLARE_ATOMIC(long double, atomic_ldouble);
702 
703 #ifndef __STDC_NO_COMPLEX__
704 P99_DECLARE_ATOMIC(float _Complex, atomic_cfloat);
705 P99_DECLARE_ATOMIC(double _Complex, atomic_cdouble);
706 P99_DECLARE_ATOMIC(long double _Complex, atomic_cldouble);
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*)
726 #else
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*)
743 #endif
744 
745 
746 P00_DOCUMENT_TYPE_ARGUMENT(P99_ATOMIC_INHERIT, 0)
747 #define P99_ATOMIC_INHERIT(T) \
748 (*P99_GENERIC_LIT \
749  ((T){ 0 }, \
750  P99_GENERIC_SIZE_LIT \
751  (sizeof(T)+1, \
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)*))() \
759  ), \
760  P00_ATOMIC_TYPES))
761 
763 P99_CONST_FUNCTION uintptr_t p00_exchange_ignore(void* p00_x, ...) { P99_UNUSED(p00_x); return 0; }
764 
765 #define P00_EXCHANGE(X) \
766 P99_GENERIC_SIZE \
767  (sizeof(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))() \
774  )
775 
866 #ifdef P00_DOXYGEN
867 # define _Atomic(T) P99_PASTE2(atomic_, T)
868 #else
869 # define _Atomic(T) __typeof__(P99_ATOMIC_INHERIT(T))
870 #endif
871 
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;
897 
911 #define atomic_thread_fence p00_mfence
912 
917 #define atomic_signal_fence atomic_thread_fence
918 
935 #define atomic_flag_test_and_set_explicit(OBJ, ORD) p00_sync_lock_test_and_set(&P99_ENCP(OBJ), (ORD))
936 
947 #define atomic_flag_test_and_set(OBJ) p00_sync_lock_test_and_set(&P99_ENCP(OBJ))
948 
960 #define atomic_flag_clear_explicit(OBJ, ORD) p00_sync_lock_release(&P99_ENCP(OBJ), (ORD))
961 
967 #define atomic_flag_clear(OBJ) p00_sync_lock_release(&P99_ENCP(OBJ))
968 
969 #include "p99_atomic_flag.h"
970 
985 #define atomic_is_lock_free(OBJP) (!offsetof(__typeof__(*OBJP), p00_xval))
986 
987 #define P00_ATOMIC_TERN(OBJP, VAL, ALT) P99_TYPED_TERN(atomic_is_lock_free(OBJP), (VAL), (ALT))
988 
999 #define atomic_init(OBJP, VAL) \
1000 p99_extension \
1001 (void)({ \
1002  P99_MAC_ARGS((p00_objp, OBJP), (p00_val, VAL)); \
1003  /* To take care of the atomic_flag and padding bytes. */ \
1004  memset((void*)p00_objp, 0, sizeof *p00_objp); \
1005  P00_AT(p00_objp) = p00_val; \
1006  })
1007 
1008 #ifdef P00_DOXYGEN
1009 
1022 #define atomic_exchange_explicit(OBJP, DESIRED, ORD)
1023 #else
1024 #define atomic_exchange_explicit(OBJP, DESIRED, ORD) \
1025 p99_extension \
1026 ({ \
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; \
1036  } \
1037  } else { \
1038  P99_IF_EMPTY(P99_ATOMIC_LOCK_FREE_TYPES) \
1039  () \
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))); \
1042  } \
1043  p00_ret.p00_t; \
1044  })
1045 #endif
1046 
1058 #define atomic_exchange(OBJP, DESIRED) \
1059 atomic_exchange_explicit((OBJP), (DESIRED), memory_order_seq_cst)
1060 
1061 
1073 #define atomic_load_explicit(OBJP, ORD) \
1074 p99_extension \
1075 ({ \
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); \
1082  } else { \
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))); \
1086  } \
1087  p00_ret.p00_t = p00_ret.p00_t; \
1088  })
1089 
1093 #define atomic_load(OBJP) atomic_load_explicit((OBJP), memory_order_seq_cst)
1094 
1095 
1096 #define P00_CVT(EXP) ((void const*)(((struct { void const volatile* a; }){ .a = (EXP) }).a))
1097 
1117 #define atomic_compare_exchange_weak_explicit(OBJP, EXPECTED, DESIRED, SUCC, FAIL) \
1118  p00_atomic_compare_exchange(true, OBJP, EXPECTED, DESIRED, SUCC, FAIL,)
1119 
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)
1122 
1123 #define atomic_compare_exchange_strong_explicit(OBJP, EXPECTED, DESIRED, SUCC, FAIL) \
1124  p00_atomic_compare_exchange(false, OBJP, EXPECTED, DESIRED, SUCC, FAIL,)
1125 
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)
1128 
1129 #define p00_atomic_compare_exchange(WEAK, OBJP, EXPECTED, DESIRED, SUCC, FAIL, ...) \
1130 p99_extension \
1131 ({ \
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; \
1136  /* Both, *EXPECTED and DESIRED must be assignment compatible with the base type */ \
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); \
1145  } \
1146  } \
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); \
1151  ) \
1152  p00_ret; \
1153  })
1154 
1155 #ifdef P00_DOXYGEN
1156 
1169 #define atomic_store_explicit(OBJP, DES, ORD)
1170 #else
1171 #define atomic_store_explicit(OBJP, DES, ORD) \
1172 p99_extension \
1173 ({ \
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; \
1181  } else { \
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))); \
1185  } \
1186  })
1187 #endif
1188 
1192 #define atomic_store(OBJP, DES) atomic_store_explicit(OBJP, DES, memory_order_seq_cst)
1193 
1194 
1195 #define P00_FETCH_OP(OBJP, OPERAND, BUILTIN, OPERATOR, ORD) \
1196 p99_extension \
1197 ({ \
1198  P99_MACRO_PVAR(p00_objp, (OBJP), volatile); \
1199  P99_MACRO_VAR(p00_op, OPERAND); \
1200  ((!atomic_is_lock_free(p00_objp)) \
1201  ? ({ \
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; \
1206  } \
1207  p00_ret; \
1208  }) \
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), \
1214  (ORD)), \
1215  P00_AT(p00_objp))))); \
1216  })
1217 
1235 #define atomic_fetch_add_explicit(OBJP, OPERAND, ORD) \
1236 P00_FETCH_OP((OBJP), (OPERAND), p00_atomic_fetch_add, +=, (ORD))
1237 
1238 #define atomic_fetch_add(OBJP, OPERAND) atomic_fetch_add_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1239 
1257 #define atomic_fetch_sub_explicit(OBJP, OPERAND, ORD) \
1258 P00_FETCH_OP((OBJP), (OPERAND), p00_atomic_fetch_sub, -=, ORD)
1259 
1260 #define atomic_fetch_sub(OBJP, OPERAND) atomic_fetch_sub_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1261 
1280 #define atomic_fetch_or_explicit(OBJP, OPERAND, ORD) \
1281 P00_FETCH_OP((OBJP), (OPERAND), p00_atomic_fetch_or, |=, (ORD))
1282 
1283 #define atomic_fetch_or(OBJP, OPERAND) atomic_fetch_or_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1284 
1303 #define atomic_fetch_and_explicit(OBJP, OPERAND, ORD) \
1304 P00_FETCH_OP((OBJP), (OPERAND), p00_atomic_fetch_and, &=, (ORD))
1305 
1306 #define atomic_fetch_and(OBJP, OPERAND) atomic_fetch_and_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1307 
1327 #define atomic_fetch_xor_explicit(OBJP, OPERAND, ORD) \
1328 P00_FETCH_OP((OBJP), (OPERAND), p00_atomic_fetch_xor, ^=, (ORD))
1329 
1330 #define atomic_fetch_xor(OBJP, OPERAND) atomic_fetch_xor_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1331 
1332 #define atomic_fetch_add_conditional(OBJP, OPERAND) \
1333 p99_extension \
1334 ({ \
1335  P99_MACRO_VAR(p00_objp, (OBJP)); \
1336  P99_MACRO_VAR(p00_op, (OPERAND)); \
1337  __typeof__(P00_AT(p00_objp)) p00_ret; \
1338  /* be sure that the result can not be used as an lvalue */ \
1339  register __typeof__(p00_ret = p00_ret) p00_r = atomic_load(p00_objp); \
1340  p00_ret = p00_r; \
1341  while (p00_r) { \
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; \
1345  } \
1346  p00_r = p00_ret; \
1347  })
1348 
1354 # endif /* P00_NO_ATOMICS */
1355 #undef P00_NO_ATOMICS
1356 
1357 #endif /* no stdatomic.h*/
1358 
1363 #define atomic_fetch_max(OBJP, OPERAND) atomic_fetch_max_explicit((OBJP), (OPERAND), memory_order_seq_cst)
1364 
1382 #define atomic_fetch_max_explicit(OBJP, OPERAND, ORD) \
1383 p99_extension \
1384 ({ \
1385  P99_MACRO_VAR(p00_objp, (OBJP)); \
1386  P99_MACRO_VAR(p00_op, (OPERAND)); \
1387  __typeof__(atomic_load(p00_objp)) p00_ret; \
1388  /* be sure that the result can not be used as an lvalue */ \
1389  register __typeof__(p00_ret = p00_ret) p00_r = atomic_load(p00_objp); \
1390  p00_ret = p00_r; \
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; \
1394  } \
1395  p00_r = p00_ret; \
1396  })
1397 
1431 #define P99_CRITICAL P00_CRITICAL(P99_UNIQ(crit))
1432 
1433 #define P00_CRITICAL(ID) \
1434 P00_BLK_START \
1435 P00_BLK_DECL_STATIC(atomic_flag, ID, ATOMIC_FLAG_INIT) \
1436 P99_SPIN_EXCLUDE(ID)
1437 
1443 #endif
uintmax_t
uintmax_t
Definition: p99_str.h:117
P99_BLOCK_DOCUMENT
#define P99_BLOCK_DOCUMENT
Add some default documentation and links to the following block macro.
Definition: p99_block.h:732
P99_DECLARE_ATOMIC
#define P99_DECLARE_ATOMIC(...)
Definition: p99_atomic.h:56
ptrdiff_t
ptrdiff_t
Definition: p99_str.h:101
p99_atomic_x86.h
p99_atomic_flag.h
p99_atomic_arm.h
p99_inline
#define p99_inline
Try to force a function always to be inlined.
Definition: p99_compiler.h:496
P99_UNUSED
#define P99_UNUSED(...)
check if the list of expressions is syntactically valid but don't evaluate it
Definition: p99_enum.h:215
P99_DECLARE_ENUM
#define P99_DECLARE_ENUM(T,...)
Declare a simple enumeration type.
Definition: p99_enum.h:139
p99_enum.h
char32_t
uint_least32_t char32_t
Definition: p99_libc.h:221
char16_t
uint_least16_t char16_t
Definition: p99_libc.h:220
P99_ENC_DECLARE
#define P99_ENC_DECLARE(T, NAME)
Encapsulate an object of type T in a new type called NAME.
Definition: p99_type.h:178
P99_CONST_FUNCTION
#define P99_CONST_FUNCTION
On architectures that support this, assert that a function is "const", i.e only depends on parameters...
Definition: p99_compiler.h:622
p99_generic.h
p99_atomic_gcc.h
Implement some of the atomic operations as fallback to gcc' builtins.