P99
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
p99_atomic.h
Go to the documentation of this file.
00001 /* This may look like nonsense, but it really is -*- mode: C -*-             */
00002 /*                                                                           */
00003 /* Except of parts copied from previous work and as explicitly stated below, */
00004 /* the author and copyright holder for this work is                          */
00005 /* (C) copyright  2011-2012 Jens Gustedt, INRIA, France                      */
00006 /*                                                                           */
00007 /* This file is free software; it is part of the P99 project.                */
00008 /* You can redistribute it and/or modify it under the terms of the QPL as    */
00009 /* given in the file LICENSE. It is distributed without any warranty;        */
00010 /* without even the implied warranty of merchantability or fitness for a     */
00011 /* particular purpose.                                                       */
00012 /*                                                                           */
00013 #ifndef P99_ATOMIC_H
00014 #define P99_ATOMIC_H 1
00015 
00016 #include "p99_enum.h"
00017 #include "p99_generic.h"
00018 #include "p99_block.h"
00019 
00059 #ifdef P99_TEST_ATOMIC
00060 # undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
00061 # undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
00062 # undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
00063 # undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
00064 #endif
00065 
00066 #if defined(__arm__)
00067 # include "p99_atomic_arm.h"
00068 #elif defined(__x86_64__) || defined(__i386__)
00069 # include "p99_atomic_x86.h"
00070 #else
00071 # warning "no support for atomic operations detected for this platform"
00072 # define P00_NO_ATOMICS
00073 #endif
00074 
00079 #if !defined(P00_NO_ATOMICS) || defined(P00_DOXYGEN)
00080 
00105 #ifndef ATOMIC_INT8_LOCK_FREE
00106 #  if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)
00107 #   define ATOMIC_INT8_LOCK_FREE 2
00108 #   define P00_TYPE_LIST_ELEM1 , (1, uint8_t)
00109 #  else
00110 #   define ATOMIC_INT8_LOCK_FREE 0
00111 #   define P00_TYPE_LIST_ELEM1
00112 #  endif
00113 #endif
00114 #ifndef ATOMIC_INT16_LOCK_FREE
00115 #  if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
00116 #   define ATOMIC_INT16_LOCK_FREE 2
00117 #   define P00_TYPE_LIST_ELEM2 , (2, uint16_t)
00118 #  else
00119 #   define ATOMIC_INT16_LOCK_FREE 0
00120 #   define P00_TYPE_LIST_ELEM2
00121 #  endif
00122 #endif
00123 #ifndef ATOMIC_INT32_LOCK_FREE
00124 #  if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
00125 #   define ATOMIC_INT32_LOCK_FREE 2
00126 #   define P00_TYPE_LIST_ELEM4 , (4, uint32_t)
00127 #  else
00128 #   define ATOMIC_INT32_LOCK_FREE 0
00129 #   define P00_TYPE_LIST_ELEM4
00130 #  endif
00131 #endif
00132 #ifndef ATOMIC_INT64_LOCK_FREE
00133 #  if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
00134 #   define ATOMIC_INT64_LOCK_FREE 2
00135 #   define P00_TYPE_LIST_ELEM8 , (8, uint64_t)
00136 #  else
00137 #   define ATOMIC_INT64_LOCK_FREE 0
00138 #   define P00_TYPE_LIST_ELEM8
00139 #  endif
00140 #endif
00141 #ifndef ATOMIC_INT128_LOCK_FREE
00142 #  if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
00143 #   define ATOMIC_INT128_LOCK_FREE 2
00144 #   define P00_TYPE_LIST_ELEM16 , (16, p99x_uint128)
00145 #  else
00146 #   define ATOMIC_INT128_LOCK_FREE 0
00147 #   define P00_TYPE_LIST_ELEM16
00148 #  endif
00149 #endif
00150 
00151 
00152 #ifndef ATOMIC_BOOL_LOCK_FREE
00153 # if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) && (UINT_MAX <= UINT32_MAX)
00154 #define ATOMIC_BOOL_LOCK_FREE 2
00155 # else
00156 #define ATOMIC_BOOL_LOCK_FREE 0
00157 # endif
00158 #endif
00159 #ifndef ATOMIC_CHAR_LOCK_FREE
00160 # define ATOMIC_CHAR_LOCK_FREE ATOMIC_INT8_LOCK_FREE
00161 #endif
00162 #if USHRT_MAX == UINT8_MAX
00163 # define ATOMIC_SHORT_LOCK_FREE ATOMIC_INT8_LOCK_FREE
00164 #elif USHRT_MAX == UINT16_MAX
00165 # define ATOMIC_SHORT_LOCK_FREE ATOMIC_INT16_LOCK_FREE
00166 #elif USHRT_MAX == UINT32_MAX
00167 # define ATOMIC_SHORT_LOCK_FREE ATOMIC_INT32_LOCK_FREE
00168 #elif USHRT_MAX == UINT64_MAX
00169 # define ATOMIC_SHORT_LOCK_FREE ATOMIC_INT64_LOCK_FREE
00170 #elif USHRT_MAX == UINT128_MAX
00171 # define ATOMIC_SHORT_LOCK_FREE ATOMIC_INT128_LOCK_FREE
00172 #else
00173 # define ATOMIC_SHORT_LOCK_FREE 0
00174 #endif
00175 #if UINT_MAX == UINT8_MAX
00176 # define ATOMIC_INT_LOCK_FREE ATOMIC_INT8_LOCK_FREE
00177 #elif UINT_MAX == UINT16_MAX
00178 # define ATOMIC_INT_LOCK_FREE ATOMIC_INT16_LOCK_FREE
00179 #elif UINT_MAX == UINT32_MAX
00180 # define ATOMIC_INT_LOCK_FREE ATOMIC_INT32_LOCK_FREE
00181 #elif UINT_MAX == UINT64_MAX
00182 # define ATOMIC_INT_LOCK_FREE ATOMIC_INT64_LOCK_FREE
00183 #elif UINT_MAX == UINT128_MAX
00184 # define ATOMIC_INT_LOCK_FREE ATOMIC_INT128_LOCK_FREE
00185 #else
00186 # define ATOMIC_INT_LOCK_FREE 0
00187 #endif
00188 #if ULONG_MAX == UINT8_MAX
00189 # define ATOMIC_LONG_LOCK_FREE ATOMIC_INT8_LOCK_FREE
00190 #elif ULONG_MAX == UINT16_MAX
00191 # define ATOMIC_LONG_LOCK_FREE ATOMIC_INT16_LOCK_FREE
00192 #elif ULONG_MAX == UINT32_MAX
00193 # define ATOMIC_LONG_LOCK_FREE ATOMIC_INT32_LOCK_FREE
00194 #elif ULONG_MAX == UINT64_MAX
00195 # define ATOMIC_LONG_LOCK_FREE ATOMIC_INT64_LOCK_FREE
00196 #elif ULONG_MAX == UINT128_MAX
00197 # define ATOMIC_LONG_LOCK_FREE ATOMIC_INT128_LOCK_FREE
00198 #else
00199 # define ATOMIC_LONG_LOCK_FREE 0
00200 #endif
00201 #if ULLONG_MAX == UINT8_MAX
00202 # define ATOMIC_LLONG_LOCK_FREE ATOMIC_INT8_LOCK_FREE
00203 #elif ULLONG_MAX == UINT16_MAX
00204 # define ATOMIC_LLONG_LOCK_FREE ATOMIC_INT16_LOCK_FREE
00205 #elif ULLONG_MAX == UINT32_MAX
00206 # define ATOMIC_LLONG_LOCK_FREE ATOMIC_INT32_LOCK_FREE
00207 #elif ULLONG_MAX == UINT64_MAX
00208 # define ATOMIC_LLONG_LOCK_FREE ATOMIC_INT64_LOCK_FREE
00209 #elif ULLONG_MAX == UINT128_MAX
00210 # define ATOMIC_LLONG_LOCK_FREE ATOMIC_INT128_LOCK_FREE
00211 #else
00212 # define ATOMIC_LLONG_LOCK_FREE 0
00213 #endif
00214 #if UINTPTR_MAX == UINT8_MAX
00215 # define ATOMIC_INTPTR_LOCK_FREE ATOMIC_INT8_LOCK_FREE
00216 #elif UINTPTR_MAX == UINT16_MAX
00217 # define ATOMIC_INTPTR_LOCK_FREE ATOMIC_INT16_LOCK_FREE
00218 #elif UINTPTR_MAX == UINT32_MAX
00219 # define ATOMIC_INTPTR_LOCK_FREE ATOMIC_INT32_LOCK_FREE
00220 #elif UINTPTR_MAX == UINT64_MAX
00221 # define ATOMIC_INTPTR_LOCK_FREE ATOMIC_INT64_LOCK_FREE
00222 #elif UINTPTR_MAX == UINT128_MAX
00223 # define ATOMIC_INTPTR_LOCK_FREE ATOMIC_INT128_LOCK_FREE
00224 #else
00225 # define ATOMIC_INTPTR_LOCK_FREE 0
00226 #endif
00227 #ifndef ATOMIC_POINTER_LOCK_FREE
00228 #define ATOMIC_POINTER_LOCK_FREE ATOMIC_INTPTR_LOCK_FREE
00229 #endif
00230 #if ATOMIC_INTPTR_LOCK_FREE == 2
00231 #if UINTPTR_MAX == UINT8_MAX
00232 # define P00_UINT_TYPE_LIST                                    \
00233   (1, uintptr_t)                                               \
00234   P00_TYPE_LIST_ELEM2                                          \
00235   P00_TYPE_LIST_ELEM4                                          \
00236   P00_TYPE_LIST_ELEM8                                          \
00237   P00_TYPE_LIST_ELEM16
00238 #elif UINTPTR_MAX == UINT16_MAX
00239 # define P00_UINT_TYPE_LIST                                    \
00240   (2, uintptr_t)                                               \
00241   P00_TYPE_LIST_ELEM1                                          \
00242   P00_TYPE_LIST_ELEM4                                          \
00243   P00_TYPE_LIST_ELEM8                                          \
00244   P00_TYPE_LIST_ELEM16
00245 #elif UINTPTR_MAX == UINT32_MAX
00246 # define P00_UINT_TYPE_LIST                                    \
00247   (4, uintptr_t)                                               \
00248   P00_TYPE_LIST_ELEM1                                          \
00249   P00_TYPE_LIST_ELEM2                                          \
00250   P00_TYPE_LIST_ELEM8                                          \
00251   P00_TYPE_LIST_ELEM16
00252 #elif UINTPTR_MAX == UINT64_MAX
00253 # define P00_UINT_TYPE_LIST                                    \
00254   (8, uintptr_t)                                               \
00255   P00_TYPE_LIST_ELEM1                                          \
00256   P00_TYPE_LIST_ELEM2                                          \
00257   P00_TYPE_LIST_ELEM4                                          \
00258   P00_TYPE_LIST_ELEM16
00259 #elif UINTPTR_MAX == UINT128_MAX
00260 # define P00_UINT_TYPE_LIST                                    \
00261   (16, uintptr_t)                                              \
00262   P00_TYPE_LIST_ELEM1                                          \
00263   P00_TYPE_LIST_ELEM2                                          \
00264   P00_TYPE_LIST_ELEM4                                          \
00265   P00_TYPE_LIST_ELEM8
00266 #else
00267 # define P00_UINT_TYPE_LIST                                    \
00268   (1, uint8_t)                                                 \
00269   P00_TYPE_LIST_ELEM2                                          \
00270   P00_TYPE_LIST_ELEM4                                          \
00271   P00_TYPE_LIST_ELEM8                                          \
00272   P00_TYPE_LIST_ELEM16
00273 #endif
00274 #endif
00275 #if UINT_LEAST16_MAX == UINT16_MAX
00276 # define ATOMIC_CHAR16_T_LOCK_FREE ATOMIC_INT16_LOCK_FREE
00277 #elif UINT_LEAST16_MAX == UINT32_MAX
00278 # define ATOMIC_CHAR16_T_LOCK_FREE ATOMIC_INT32_LOCK_FREE
00279 #elif UINT_LEAST16_MAX == UINT64_MAX
00280 # define ATOMIC_CHAR16_T_LOCK_FREE ATOMIC_INT64_LOCK_FREE
00281 #elif UINT_LEAST16_MAX == UINT128_MAX
00282 # define ATOMIC_CHAR16_T_LOCK_FREE ATOMIC_INT128_LOCK_FREE
00283 #else
00284 # define ATOMIC_CHAR16_T_LOCK_FREE 0
00285 #endif
00286 #if UINT_LEAST32_MAX == UINT32_MAX
00287 # define ATOMIC_CHAR32_T_LOCK_FREE ATOMIC_INT32_LOCK_FREE
00288 #elif UINT_LEAST32_MAX == UINT64_MAX
00289 # define ATOMIC_CHAR32_T_LOCK_FREE ATOMIC_INT64_LOCK_FREE
00290 #elif UINT_LEAST32_MAX == UINT128_MAX
00291 # define ATOMIC_CHAR32_T_LOCK_FREE ATOMIC_INT128_LOCK_FREE
00292 #else
00293 # define ATOMIC_CHAR32_T_LOCK_FREE 0
00294 #endif
00295 #if WCHAR_MAX == UINT8_MAX || (!WCHAR_MIN && (WCHAR_MAX == INT8_MAX))
00296 # define ATOMIC_WCHAR_LOCK_FREE ATOMIC_INT8_LOCK_FREE
00297 #elif WCHAR_MAX == UINT16_MAX || (!WCHAR_MIN && (WCHAR_MAX == INT16_MAX))
00298 # define ATOMIC_WCHAR_LOCK_FREE ATOMIC_INT16_LOCK_FREE
00299 #elif WCHAR_MAX == UINT32_MAX || (!WCHAR_MIN && (WCHAR_MAX == INT32_MAX))
00300 # define ATOMIC_WCHAR_LOCK_FREE ATOMIC_INT32_LOCK_FREE
00301 #elif WCHAR_MAX == UINT64_MAX || (!WCHAR_MIN && (WCHAR_MAX == INT64_MAX))
00302 # define ATOMIC_WCHAR_LOCK_FREE ATOMIC_INT64_LOCK_FREE
00303 #elif WCHAR_MAX == UINT128_MAX || (!WCHAR_MIN && (WCHAR_MAX == INT128_MAX))
00304 # define ATOMIC_WCHAR_LOCK_FREE ATOMIC_INT128_LOCK_FREE
00305 #else
00306 # define ATOMIC_WCHAR_LOCK_FREE 0
00307 #endif
00308 
00332 P00_DOCUMENT_TYPE_ARGUMENT(P99_UINT_DEFAULT, 0)
00333 #if defined(P00_UINT_TYPE_LIST) || defined(P00_DOXYGEN)
00334 # define P99_UINT_DEFAULT(T)                                                      \
00335 __typeof__(P99_GENERIC_SIZE_LIT(sizeof(T), (uintptr_t){ 0 }, P00_UINT_TYPE_LIST))
00336 #else
00337 # define P00_UINT_TYPE_LIST
00338 # define P99_UINT_DEFAULT(T) uintptr_t
00339 #endif
00340 
00345 #define ATOMIC_FLAG_INIT P99_ENC_INIT(0)
00346 
00351 #define ATOMIC_VAR_INIT(V) { .p00_xval = { .p00_t = (V), }, }
00352 
00367 #ifndef P99_ATOMIC_LOCK_FREE_TYPES
00368 # define P99_ATOMIC_LOCK_FREE_TYPES P00_ATOMIC_LOCK_FREE_TYPES6_
00369 
00370 #if ATOMIC_BOOL_LOCK_FREE == 2
00371 # define P00_ATOMIC_LOCK_FREE_TYPES0 _Bool
00372 #endif
00373 #if ATOMIC_CHAR_LOCK_FREE == 2
00374 # define P00_ATOMIC_LOCK_FREE_TYPES1 char, signed char, unsigned char
00375 #endif
00376 #if ATOMIC_SHORT_LOCK_FREE == 2
00377 # define P00_ATOMIC_LOCK_FREE_TYPES2 short, unsigned short
00378 #endif
00379 #if ATOMIC_INT_LOCK_FREE == 2
00380 # define P00_ATOMIC_LOCK_FREE_TYPES3 int, unsigned int
00381 #endif
00382 #if ATOMIC_LONG_LOCK_FREE == 2
00383 # define P00_ATOMIC_LOCK_FREE_TYPES4 long, unsigned long
00384 #endif
00385 #if ATOMIC_LLONG_LOCK_FREE == 2
00386 # define P00_ATOMIC_LOCK_FREE_TYPES5 long long, unsigned long long
00387 #endif
00388 #if ATOMIC_POINTER_LOCK_FREE == 2
00389 # define P00_ATOMIC_LOCK_FREE_TYPES6 char*, signed char*, unsigned char*
00390 #endif
00391 
00392 #ifdef P00_ATOMIC_LOCK_FREE_TYPES0
00393 # ifdef P00_ATOMIC_LOCK_FREE_TYPES1
00394 #  define P00_ATOMIC_LOCK_FREE_TYPES1_ P00_ATOMIC_LOCK_FREE_TYPES0, P00_ATOMIC_LOCK_FREE_TYPES1
00395 # else
00396 #  define P00_ATOMIC_LOCK_FREE_TYPES1_ P00_ATOMIC_LOCK_FREE_TYPES0
00397 # endif
00398 #else
00399 # ifdef P00_ATOMIC_LOCK_FREE_TYPES1
00400 #  define P00_ATOMIC_LOCK_FREE_TYPES1_ P00_ATOMIC_LOCK_FREE_TYPES1
00401 # endif
00402 #endif
00403 
00404 #ifdef P00_ATOMIC_LOCK_FREE_TYPES1_
00405 # ifdef P00_ATOMIC_LOCK_FREE_TYPES2
00406 #  define P00_ATOMIC_LOCK_FREE_TYPES2_ P00_ATOMIC_LOCK_FREE_TYPES1_, P00_ATOMIC_LOCK_FREE_TYPES2
00407 # else
00408 #  define P00_ATOMIC_LOCK_FREE_TYPES2_ P00_ATOMIC_LOCK_FREE_TYPES1_
00409 # endif
00410 #else
00411 # ifdef P00_ATOMIC_LOCK_FREE_TYPES2
00412 #  define P00_ATOMIC_LOCK_FREE_TYPES2_ P00_ATOMIC_LOCK_FREE_TYPES2
00413 # endif
00414 #endif
00415 
00416 #ifdef P00_ATOMIC_LOCK_FREE_TYPES2_
00417 # ifdef P00_ATOMIC_LOCK_FREE_TYPES3
00418 #  define P00_ATOMIC_LOCK_FREE_TYPES3_ P00_ATOMIC_LOCK_FREE_TYPES2_, P00_ATOMIC_LOCK_FREE_TYPES3
00419 # else
00420 #  define P00_ATOMIC_LOCK_FREE_TYPES3_ P00_ATOMIC_LOCK_FREE_TYPES2_
00421 # endif
00422 #else
00423 # ifdef P00_ATOMIC_LOCK_FREE_TYPES3
00424 #  define P00_ATOMIC_LOCK_FREE_TYPES3_ P00_ATOMIC_LOCK_FREE_TYPES3
00425 # endif
00426 #endif
00427 
00428 #ifdef P00_ATOMIC_LOCK_FREE_TYPES3_
00429 # ifdef P00_ATOMIC_LOCK_FREE_TYPES4
00430 #  define P00_ATOMIC_LOCK_FREE_TYPES4_ P00_ATOMIC_LOCK_FREE_TYPES3_, P00_ATOMIC_LOCK_FREE_TYPES4
00431 # else
00432 #  define P00_ATOMIC_LOCK_FREE_TYPES4_ P00_ATOMIC_LOCK_FREE_TYPES3_
00433 # endif
00434 #else
00435 # ifdef P00_ATOMIC_LOCK_FREE_TYPES4
00436 #  define P00_ATOMIC_LOCK_FREE_TYPES4_ P00_ATOMIC_LOCK_FREE_TYPES4
00437 # endif
00438 #endif
00439 
00440 #ifdef P00_ATOMIC_LOCK_FREE_TYPES4_
00441 # ifdef P00_ATOMIC_LOCK_FREE_TYPES5
00442 #  define P00_ATOMIC_LOCK_FREE_TYPES5_ P00_ATOMIC_LOCK_FREE_TYPES4_, P00_ATOMIC_LOCK_FREE_TYPES5
00443 # else
00444 #  define P00_ATOMIC_LOCK_FREE_TYPES5_ P00_ATOMIC_LOCK_FREE_TYPES4_
00445 # endif
00446 #else
00447 # ifdef P00_ATOMIC_LOCK_FREE_TYPES5
00448 #  define P00_ATOMIC_LOCK_FREE_TYPES5_ P00_ATOMIC_LOCK_FREE_TYPES5
00449 # endif
00450 #endif
00451 
00452 #ifdef P00_ATOMIC_LOCK_FREE_TYPES5_
00453 # ifdef P00_ATOMIC_LOCK_FREE_TYPES6
00454 #  define P00_ATOMIC_LOCK_FREE_TYPES6_ P00_ATOMIC_LOCK_FREE_TYPES5_, P00_ATOMIC_LOCK_FREE_TYPES6
00455 # else
00456 #  define P00_ATOMIC_LOCK_FREE_TYPES6_ P00_ATOMIC_LOCK_FREE_TYPES5_
00457 # endif
00458 #else
00459 # ifdef P00_ATOMIC_LOCK_FREE_TYPES6
00460 #  define P00_ATOMIC_LOCK_FREE_TYPES6_ P00_ATOMIC_LOCK_FREE_TYPES6
00461 # endif
00462 #endif
00463 #endif
00464 
00465 #ifndef P00_ATOMIC_LOCK_FREE_TYPES6_
00466 # define P00_ATOMIC_LOCK_FREE_TYPES6_
00467 #endif
00468 
00479 P99_DECLARE_ENUM(memory_order,
00480                  memory_order_relaxed,
00481                  memory_order_consume,
00482                  memory_order_acquire,
00483                  memory_order_release,
00484                  memory_order_acq_rel,
00485                  memory_order_seq_cst
00486                 );
00487 
00488 
00513 P99_ENC_DECLARE(uint32_t volatile, atomic_flag);
00514 
00515 #define P00_AX(OBJP) ((OBJP)->p00_xval)
00516 #define P00_AT(OBJP) (P00_AX(OBJP).p00_t)
00517 #define P00_AO(OBJP) (P00_AX(OBJP).p00_o)
00518 #define P00_AM(OBJP) (P00_AX(OBJP).p00_m)
00519 
00520 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P00_DECLARE_ATOMIC_TYPE, 0)
00521 P00_DOCUMENT_TYPE_ARGUMENT(P00_DECLARE_ATOMIC_TYPE, 1)
00522 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P00_DECLARE_ATOMIC_TYPE, 2)
00523 #define P00_DECLARE_ATOMIC_TYPE(TAGGER, TI, T, NAME)                   \
00524 TAGGER P99_PASTE3(NAME, _, TAGGER) {                                   \
00525   atomic_flag p00_lock;                                                \
00526   union {                                                              \
00527     TI p00_o;                                                          \
00528     P99_UINT_DEFAULT(T) p00_m;                                         \
00529     T p00_t;                                                           \
00530   } p00_xval;                                                          \
00531 };                                                                     \
00532 typedef TAGGER P99_PASTE3(NAME, _, TAGGER) P99_PASTE3(NAME, _, TAGGER)
00533 
00534 
00542 P00_DOCUMENT_TYPE_ARGUMENT(P99_DECLARE_ATOMIC_LOCK_FREE, 0)
00543 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_ATOMIC_LOCK_FREE, 1)
00544 #ifdef P00_DOXYGEN
00545 # define P99_DECLARE_ATOMIC_LOCK_FREE(T, NAME)                                                                         \
00546  \
00547 typedef P99_PASTE3(p99_, NAME, _union) NAME
00548 #else
00549 #define P99_DECLARE_ATOMIC_LOCK_FREE(T, NAME)                          \
00550 P00_DECLARE_ATOMIC_TYPE(union, T, T, P99_PASTE2(p99_, NAME));          \
00551 P00_DECLARE_ATOMIC_TYPE(struct, uintptr_t, T, P99_PASTE2(p99_, NAME)); \
00552 typedef P99_PASTE3(p99_, NAME, _union) NAME
00553 #endif
00554 
00555 
00556 #define P00_DECLARE_ATOMIC2(T, ...)                                                                                    \
00557 P00_DECLARE_ATOMIC_TYPE(union, T, T, P99_PASTE(p99_, __VA_ARGS__));                                                    \
00558 P00_DECLARE_ATOMIC_TYPE(struct, uintptr_t, T, P99_PASTE(p99_, __VA_ARGS__));                                           \
00559  \
00560 typedef P99_PASTE(p99_, __VA_ARGS__, _struct) __VA_ARGS__
00561 
00581 P00_DOCUMENT_TYPE_ARGUMENT(P99_DECLARE_ATOMIC, 0)
00582 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_DECLARE_ATOMIC_LOCK_FREE, 1)
00583 #ifdef P00_DOXYGEN
00584 #define P99_DECLARE_ATOMIC(T, NAME)
00585 #else
00586 #define P99_DECLARE_ATOMIC(...)                                                                                        \
00587  \
00588 P99_IF_EQ_1(P99_NARG(__VA_ARGS__))                                                                                     \
00589 (P00_DECLARE_ATOMIC2(__VA_ARGS__, P99_PASTE2(atomic_, __VA_ARGS__)))                                                   \
00590 (P00_DECLARE_ATOMIC2(__VA_ARGS__))
00591 #endif
00592 
00593 #define P00_DECLARE_ATOMIC(T, ...)                                                                                     \
00594  \
00595 typedef P00_ATOMIC_STRUCT(T, __VA_ARGS__) __VA_ARGS__
00596 
00597 #define P00_DECLARE_ATOMIC_CHOICE(MAC, T, NAME)                \
00598 P99_IF_EQ_2(MAC)                                               \
00599 (P99_DECLARE_ATOMIC_LOCK_FREE(T, NAME))                        \
00600 (P99_DECLARE_ATOMIC(T, NAME))
00601 
00602 
00609 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_INT_LOCK_FREE, int, atomic_int);
00610 
00620 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_BOOL_LOCK_FREE, _Bool, atomic_bool);
00621 
00622 
00623 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_CHAR_LOCK_FREE, char, atomic_char);
00624 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_CHAR_LOCK_FREE, signed char, atomic_schar);
00625 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_CHAR_LOCK_FREE, unsigned char, atomic_uchar);
00626 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_SHORT_LOCK_FREE, short, atomic_short);
00627 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_SHORT_LOCK_FREE, unsigned short, atomic_ushort);
00628 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_INT_LOCK_FREE, unsigned int, atomic_uint);
00629 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_LONG_LOCK_FREE, long, atomic_long);
00630 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_LONG_LOCK_FREE, unsigned long, atomic_ulong);
00631 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_LLONG_LOCK_FREE, long long, atomic_llong);
00632 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_LONG_LOCK_FREE, unsigned long long, atomic_ullong);
00633 
00634 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_POINTER_LOCK_FREE, char*, atomic_char_ptr);
00635 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_POINTER_LOCK_FREE, signed char*, atomic_schar_ptr);
00636 P00_DECLARE_ATOMIC_CHOICE(ATOMIC_POINTER_LOCK_FREE, unsigned char*, atomic_uchar_ptr);
00637 
00638 P99_DECLARE_ATOMIC(float, atomic_float);
00639 P99_DECLARE_ATOMIC(double, atomic_double);
00640 P99_DECLARE_ATOMIC(long double, atomic_ldouble);
00641 
00642 #ifndef __STDC_NO_COMPLEX__
00643 P99_DECLARE_ATOMIC(float _Complex, atomic_cfloat);
00644 P99_DECLARE_ATOMIC(double _Complex, atomic_cdouble);
00645 P99_DECLARE_ATOMIC(long double _Complex, atomic_cldouble);
00646 #define P00_ATOMIC_TYPES                                       \
00647   (_Bool, atomic_bool*),                                       \
00648   (char, atomic_char*),                                        \
00649   (signed char, atomic_schar*),                                \
00650   (unsigned char, atomic_uchar*),                              \
00651   (short int, atomic_short*),                                  \
00652   (unsigned short int, atomic_ushort*),                        \
00653   (int, atomic_int*),                                          \
00654   (unsigned int, atomic_uint*),                                \
00655   (long int, atomic_long*),                                    \
00656   (unsigned long int, atomic_ulong*),                          \
00657   (long long int, atomic_llong*),                              \
00658   (unsigned long long int, atomic_ullong*),                    \
00659   (float, atomic_float*),                                      \
00660   (double, atomic_double*),                                    \
00661   (long double, atomic_ldouble*),                              \
00662   (float _Complex, atomic_cfloat*),                            \
00663   (double _Complex, atomic_cdouble*),                          \
00664   (long double _Complex, atomic_cldouble*)
00665 #else
00666 #define P00_ATOMIC_TYPES                                       \
00667   (_Bool, atomic_bool*),                                       \
00668   (char, atomic_char*),                                        \
00669   (signed char, atomic_schar*),                                \
00670   (unsigned char, atomic_uchar*),                              \
00671   (short int, atomic_short*),                                  \
00672   (unsigned short int, atomic_ushort*),                        \
00673   (int, atomic_int*),                                          \
00674   (unsigned int, atomic_uint*),                                \
00675   (long int, atomic_long*),                                    \
00676   (unsigned long int, atomic_ulong*),                          \
00677   (long long int, atomic_llong*),                              \
00678   (unsigned long long int, atomic_ullong*),                    \
00679   (float, atomic_float*),                                      \
00680   (double, atomic_double*),                                    \
00681   (long double, atomic_ldouble*)
00682 #endif
00683 
00684 
00685 P00_DOCUMENT_TYPE_ARGUMENT(P99_ATOMIC_INHERIT, 0)
00686 #define P99_ATOMIC_INHERIT(T)                                                               \
00687 (*P99_GENERIC_LIT                                                                           \
00688  ((T){ 0 },                                                                                 \
00689   P99_GENERIC_SIZE_LIT                                                                      \
00690   (sizeof(T)+1,                                                                             \
00691    (struct P99_PASTE3(p99_atomic_, T, _struct)*){ 0 },                                      \
00692    (1, union P99_PASTE3(p99_atomic_, T, _union)*)                                           \
00693    P99_IF_EQ_2(ATOMIC_INT8_LOCK_FREE)(,(2, union P99_PASTE3(p99_atomic_, T, _union)*))()    \
00694    P99_IF_EQ_2(ATOMIC_INT16_LOCK_FREE)(,(3, union P99_PASTE3(p99_atomic_, T, _union)*))()   \
00695    P99_IF_EQ_2(ATOMIC_INT32_LOCK_FREE)(,(5, union P99_PASTE3(p99_atomic_, T, _union)*))()   \
00696    P99_IF_EQ_2(ATOMIC_INT64_LOCK_FREE)(,(9, union P99_PASTE3(p99_atomic_, T, _union)*))()   \
00697    P99_IF_EQ_2(ATOMIC_INT128_LOCK_FREE)(,(17, union P99_PASTE3(p99_atomic_, T, _union)*))() \
00698    ),                                                                                       \
00699   P00_ATOMIC_TYPES))
00700 
00701 p99_inline
00702 uintptr_t p00_fetch_and_store_ignore(void* x, ...) { return 0; }
00703 
00704 #define P00_FETCH_AND_STORE(X)                                              \
00705 P99_GENERIC_SIZE                                                            \
00706  (sizeof(X),                                                                \
00707   p00_fetch_and_store_ignore,                                               \
00708   (1, p00_atomic_fetch_and_store_1),                                        \
00709   (2, p00_atomic_fetch_and_store_2),                                        \
00710   (4, p00_atomic_fetch_and_store_4)                                         \
00711   P99_IF_EQ_2(ATOMIC_INT64_LOCK_FREE)(,(8, p00_atomic_fetch_and_store_8))() \
00712   )
00713 
00804 #ifdef P00_DOXYGEN
00805 # define _Atomic(T) P99_PASTE2(atomic_, T)
00806 #else
00807 # define _Atomic(T) __typeof__(P99_ATOMIC_INHERIT(T))
00808 #endif
00809 
00810 typedef _Atomic(char16_t) atomic_char16_t;
00811 typedef _Atomic(char32_t) atomic_char32_t;
00812 typedef _Atomic(wchar_t) atomic_wchar_t;
00813 typedef _Atomic(int_least8_t) atomic_int_least8_t;
00814 typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
00815 typedef _Atomic(int_least16_t) atomic_int_least16_t;
00816 typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
00817 typedef _Atomic(int_least32_t) atomic_int_least32_t;
00818 typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
00819 typedef _Atomic(int_least64_t) atomic_int_least64_t;
00820 typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
00821 typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
00822 typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
00823 typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
00824 typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
00825 typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
00826 typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
00827 typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
00828 typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
00829 typedef _Atomic(intptr_t) atomic_intptr_t;
00830 typedef _Atomic(uintptr_t) atomic_uintptr_t;
00831 typedef _Atomic(size_t) atomic_size_t;
00832 typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
00833 typedef _Atomic(intmax_t) atomic_intmax_t;
00834 typedef _Atomic(uintmax_t) atomic_uintmax_t;
00835 
00849 p99_inline
00850 void atomic_thread_fence(memory_order p00_ord) {
00851   switch (p00_ord) {
00852   case memory_order_relaxed: break;
00853   default: p00_mfence(); break;
00854   }
00855 }
00856 
00861 #define atomic_signal_fence atomic_thread_fence
00862 
00879 p99_inline
00880 _Bool atomic_flag_test_and_set_explicit(volatile atomic_flag *p00_objp, memory_order p00_ord) {
00881   _Bool p00_ret;
00882   switch (p00_ord) {
00883     /* This case doesn't require any guarantee. */
00884   case memory_order_relaxed:
00885     p00_ret = P99_ENCP(p00_objp);
00886     P99_ENCP(p00_objp) = 1;
00887     break;
00888     /* For these three the acquire semantics are not sufficient. */
00889   case memory_order_release: ;
00890   case memory_order_acq_rel: ;
00891   case memory_order_seq_cst:
00892     atomic_thread_fence(p00_ord);
00893     p00_ret = p00_sync_lock_test_and_set(&P99_ENCP(p00_objp));
00894     break;
00895   default:
00896     p00_ret = p00_sync_lock_test_and_set(&P99_ENCP(p00_objp));
00897     break;
00898   }
00899   return p00_ret;
00900 }
00901 
00908 p99_inline
00909 _Bool atomic_flag_test_and_set(volatile atomic_flag *p00_objp) {
00910   return atomic_flag_test_and_set_explicit(p00_objp, memory_order_seq_cst);
00911 }
00912 
00924 p99_inline
00925 void atomic_flag_clear_explicit(volatile atomic_flag *p00_objp, memory_order p00_ord) {
00926   switch(p00_ord) {
00927     /* This case doesn't require any guarantee. */
00928   case memory_order_relaxed:
00929     P99_ENCP(p00_objp) = 0;
00930     break;
00931     /* For these three the release semantics are not sufficient. */
00932   case memory_order_acquire: ;
00933   case memory_order_acq_rel: ;
00934   case memory_order_seq_cst:
00935     p00_sync_lock_release(&P99_ENCP(p00_objp));
00936     atomic_thread_fence(p00_ord);
00937     break;
00938   default:
00939     p00_sync_lock_release(&P99_ENCP(p00_objp));
00940     break;
00941   }
00942 }
00943 
00949 p99_inline
00950 void atomic_flag_clear(volatile atomic_flag *p00_objp) {
00951   atomic_flag_clear_explicit(p00_objp, memory_order_seq_cst);
00952 }
00953 
00964 p99_inline
00965 void atomic_flag_lock(volatile atomic_flag *p00_objp) {
00966   while (atomic_flag_test_and_set_explicit(p00_objp, memory_order_acquire));
00967 }
00968 
00980 p99_inline
00981 _Bool atomic_flag_trylock(volatile atomic_flag *p00_objp) {
00982   return !atomic_flag_test_and_set_explicit(p00_objp, memory_order_acquire);
00983 }
00984 
00992 p99_inline
00993 void atomic_flag_unlock(volatile atomic_flag *p00_objp) {
00994   atomic_flag_clear_explicit(p00_objp, memory_order_release);
00995 }
00996 
01020 #define P99_SPIN_EXCLUDE(FLAGP)                                             \
01021 P00_BLK_START                                                               \
01022 P00_BLK_DECL(register atomic_flag volatile*const, P99_FILEID(flg), (FLAGP)) \
01023 P00_BLK_BEFAFT(atomic_flag_lock(P99_FILEID(flg)),                           \
01024                atomic_flag_unlock(P99_FILEID(flg)))                         \
01025 P00_BLK_END
01026 
01041 #define atomic_is_lock_free(OBJP) (!offsetof(__typeof__(*OBJP), p00_xval))
01042 
01043 #define P00_ATOMIC_TERN(OBJP, VAL, ALT) P99_TYPED_TERN(atomic_is_lock_free(OBJP), (VAL), (ALT))
01044 
01055 #define atomic_init(OBJP, VAL)                                 \
01056 p99_extension                                                  \
01057 (void)({                                                       \
01058     P99_MAC_ARGS((p00_objp, OBJP), (p00_val, VAL));            \
01059     /* To take care of the atomic_flag and padding bytes. */   \
01060     memset(p00_objp, 0, sizeof *p00_objp);                     \
01061     P00_AT(p00_objp) = p00_val;                                \
01062   })
01063 
01064 #ifdef P00_DOXYGEN
01065 
01075 #define atomic_fetch_and_store(OBJP, DESIRED)
01076 #else
01077 #define atomic_fetch_and_store(OBJP, DESIRED)                                                           \
01078 p99_extension                                                                                           \
01079 ({                                                                                                      \
01080   P99_MACRO_PVAR(p00_objp, (OBJP));                                                                     \
01081   __typeof__(P00_AT(p00_objp)) p00_des = (DESIRED);                                                     \
01082   __typeof__(P00_AX(p00_objp)) p00_ret = P99_INIT;                                                      \
01083   if (!atomic_is_lock_free(p00_objp))                                                                   \
01084     P99_SPIN_EXCLUDE(&p00_objp->p00_lock) {                                                             \
01085       p00_ret.p00_t = P00_AT(p00_objp);                                                                 \
01086       P00_AT(p00_objp) = p00_des;                                                                       \
01087     }                                                                                                   \
01088   P99_IF_EMPTY(P99_ATOMIC_LOCK_FREE_TYPES)                                                              \
01089     ()                                                                                                  \
01090     (else {                                                                                             \
01091       __typeof__(P00_AX(p00_objp)) p00_desm = { .p00_t = p00_des };                                     \
01092       switch (sizeof(P00_AT(p00_objp))) {                                                               \
01093       case 1:;                                                                                          \
01094       case 2:;                                                                                          \
01095       case 4:;                                                                                          \
01096       case 8:;                                                                                          \
01097         p00_ret.p00_m = P00_FETCH_AND_STORE(P00_AT(p00_objp))(&P00_AM(p00_objp), p00_desm.p00_m);       \
01098         break;                                                                                          \
01099       default:                                                                                          \
01100         p00_ret.p00_m = P00_AM(p00_objp);                                                               \
01101         for (;;) {                                                                                      \
01102           P99_MACRO_VAR(p00_valm,                                                                       \
01103                         __sync_val_compare_and_swap(&P00_AM(p00_objp), p00_ret.p00_m, p00_desm.p00_m)); \
01104           if (P99_LIKELY(p00_valm == p00_ret.p00_m)) break;                                             \
01105           p00_ret.p00_m = p00_valm;                                                                     \
01106         }                                                                                               \
01107       }                                                                                                 \
01108     })                                                                                                  \
01109     p00_ret.p00_t;                                                                                      \
01110  })
01111 #endif
01112 
01121 #define atomic_load(OBJP)                                                     \
01122 p99_extension                                                                 \
01123 ({                                                                            \
01124   P99_MACRO_PVAR(p00_objp, (OBJP));                                           \
01125   __typeof__(P00_AX(p00_objp)) p00_ret;                                       \
01126   if (!atomic_is_lock_free(p00_objp))                                         \
01127     P99_SPIN_EXCLUDE(&p00_objp->p00_lock)                                     \
01128       p00_ret.p00_t = P00_AT(p00_objp);                                       \
01129   P99_IF_EMPTY(P99_ATOMIC_LOCK_FREE_TYPES)                                    \
01130     (else p00_ret.p00_t = P00_AT(p00_objp);)                                  \
01131     (else {                                                                   \
01132       p00_ret.p00_m =                                                         \
01133         P00_ATOMIC_TERN(p00_objp,                                             \
01134                         __sync_val_compare_and_swap(&P00_AM(p00_objp), 0, 0), \
01135                         P00_AM(p00_objp));                                    \
01136     })                                                                        \
01137     /* assign to itself to be sure that the result is an rvalue */            \
01138     p00_ret.p00_t = p00_ret.p00_t;                                            \
01139  })
01140 
01141 #define P00_CVT(EXP) ((void const*)(((struct { void const volatile* a; }){ .a = (EXP) }).a))
01142 
01159 #define atomic_compare_exchange_weak(OBJP, EXPECTED, DESIRED)                                   \
01160 p99_extension                                                                                   \
01161 ({                                                                                              \
01162   P99_MACRO_PVAR(p00_objp, (OBJP));                                                             \
01163   P99_MACRO_PVAR(p00_exp, (EXPECTED));                                                          \
01164   P99_MACRO_VAR(p00_des, DESIRED);                                                              \
01165   _Bool p00_ret = false;                                                                        \
01166   if (!atomic_is_lock_free(p00_objp)) {                                                         \
01167     P99_SPIN_EXCLUDE(&p00_objp->p00_lock) {                                                     \
01168       p00_ret = !memcmp(P00_CVT(p00_exp), P00_CVT(&P00_AT(p00_objp)), sizeof P00_AT(p00_objp)); \
01169       /* Both, *EXPECTED and DESIRED must be assignment compatible                              \
01170          with the base type */                                                                  \
01171       if (p00_ret) P00_AT(p00_objp) = p00_des;                                                  \
01172       else *p00_exp = P00_AT(p00_objp);                                                         \
01173     }                                                                                           \
01174   }                                                                                             \
01175   P99_IF_EMPTY(P99_ATOMIC_LOCK_FREE_TYPES)                                                      \
01176     (else p00_ret = false;)                                                                     \
01177     (else {                                                                                     \
01178       __typeof__(P00_AM(p00_objp))* p00_expm                                                    \
01179         = (__typeof__(P00_AM(p00_objp))*)P00_ATOMIC_TERN(p00_objp, p00_exp, 0);                 \
01180       __typeof__(P00_AX(p00_objp)) p00_desm = { .p00_t = p00_des };                             \
01181       __typeof__(P00_AM(p00_objp)) p00_valm                                                     \
01182         = P00_ATOMIC_TERN                                                                       \
01183         (p00_objp,                                                                              \
01184          __sync_val_compare_and_swap(&P00_AM(p00_objp), *p00_expm, p00_desm.p00_m),             \
01185          0);                                                                                    \
01186       p00_ret = (*p00_expm == p00_valm);                                                        \
01187       if (!p00_ret) *p00_expm = p00_valm;                                                       \
01188     })                                                                                          \
01189   p00_ret;                                                                                      \
01190  })
01191 
01192 #ifdef P00_DOXYGEN
01193 
01203 #define atomic_store(OBJP, DES)
01204 #else
01205 #define atomic_store(OBJP, DES) ((void)atomic_fetch_and_store(OBJP, DES))
01206 #endif
01207 
01208 #define P00_FETCH_OP(OBJP, OPERAND, BUILTIN, OPERATOR)                 \
01209 p99_extension                                                          \
01210 ({                                                                     \
01211   P99_MACRO_PVAR(p00_objp, (OBJP));                                    \
01212   P99_MACRO_VAR(p00_op, OPERAND);                                      \
01213   __typeof__(P00_AT(p00_objp)) p00_ret;                                \
01214   if (!atomic_is_lock_free(p00_objp)) {                                \
01215     P99_SPIN_EXCLUDE(&p00_objp->p00_lock) {                            \
01216       p00_ret = P00_AT(p00_objp);                                      \
01217       P00_AT(p00_objp) OPERATOR p00_op;                                \
01218     }                                                                  \
01219   }                                                                    \
01220   P99_IF_EMPTY(P99_ATOMIC_LOCK_FREE_TYPES)                             \
01221     (else p00_ret = P00_AT(p00_objp);)                                 \
01222     (else {                                                            \
01223       p00_ret =                                                        \
01224         P00_ATOMIC_TERN(p00_objp,                                      \
01225                         BUILTIN(&P00_AO(p00_objp),                     \
01226                                 P00_ATOMIC_TERN(p00_objp, p00_op, 0)), \
01227                         P00_AT(p00_objp));                             \
01228     })                                                                 \
01229     p00_ret;                                                           \
01230  })
01231 
01244 #define atomic_fetch_add(OBJP, OPERAND) P00_FETCH_OP((OBJP), (OPERAND), __sync_fetch_and_add, +=)
01245 
01246 
01259 #define atomic_fetch_sub(OBJP, OPERAND) P00_FETCH_OP((OBJP), (OPERAND), __sync_fetch_and_sub, -=)
01260 
01274 #define atomic_fetch_or(OBJP, OPERAND) P00_FETCH_OP((OBJP), (OPERAND), __sync_fetch_and_or, |=)
01275 
01289 #define atomic_fetch_and(OBJP, OPERAND) P00_FETCH_OP((OBJP), (OPERAND), __sync_fetch_and_and, &=)
01290 
01305 #define atomic_fetch_xor(OBJP, OPERAND) P00_FETCH_OP((OBJP), (OPERAND), __sync_fetch_and_xor, ^=)
01306 
01307 #define atomic_fetch_add_conditional(OBJP, OPERAND)                       \
01308 p99_extension                                                             \
01309 ({                                                                        \
01310   P99_MACRO_PVAR(p00_objp, (OBJP));                                       \
01311   P99_MACRO_VAR(p00_op, (OPERAND));                                       \
01312   P99_MACRO_VAR(p00_ret, atomic_load(p00_objp));                          \
01313   while (p00_ret) {                                                       \
01314     P99_MACRO_VAR(p00_des, p00_ret + p00_op);                             \
01315     if (atomic_compare_exchange_weak(p00_objp, &p00_ret, p00_des)) break; \
01316   }                                                                       \
01317   p00_ret;                                                                \
01318  })
01319 
01320 #define atomic_fetch_max(OBJP, OPERAND)                                 \
01321 p99_extension                                                           \
01322 ({                                                                      \
01323   P99_MACRO_PVAR(p00_objp, (OBJP));                                     \
01324   P99_MACRO_VAR(p00_op, (OPERAND));                                     \
01325   P99_MACRO_VAR(p00_ret, atomic_load(p00_objp));                        \
01326   while (p00_ret <= p00_op) {                                           \
01327     if (atomic_compare_exchange_weak(p00_objp, &p00_ret, p00_op)) break; \
01328   }                                                                     \
01329   p00_ret;                                                              \
01330  })
01331 
01364 P99_BLOCK_DOCUMENT
01365 #define P99_CRITICAL                                                 \
01366 P00_BLK_START                                                        \
01367 P00_BLK_DECL_STATIC(atomic_flag, P99_LINEID(crit), ATOMIC_FLAG_INIT) \
01368 P99_SPIN_EXCLUDE(P99_LINEID(crit))
01369 
01370 
01377 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_TOP, 0)
01378 #define P99_LIFO_TOP(L)  atomic_load(L)
01379 
01386 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_PUSH, 0)
01387 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_PUSH, 1)
01388 #define P99_LIFO_PUSH(L, EL)                                   \
01389 p99_extension                                                  \
01390 ({                                                             \
01391   P99_MACRO_VAR(p00_l, (L));                                   \
01392   P99_MACRO_VAR(p00_el, (EL));                                 \
01393   p00_el->p99_lifo = atomic_fetch_and_store(p00_l, p00_el);    \
01394  })
01395 
01435 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_POP, 0)
01436 #define P99_LIFO_POP(L)                                                                            \
01437 p99_extension                                                                                      \
01438 ({                                                                                                 \
01439   P99_MACRO_VAR(p00_l, (L));                                                                       \
01440   __typeof__(P99_LIFO_TOP(p00_l)) p00_el = P99_LIFO_TOP(p00_l);                                    \
01441   if (P99_LIKELY(p00_el)) {                                                                        \
01442     while (P99_UNLIKELY(!atomic_compare_exchange_weak(p00_l, &p00_el, p00_el->p99_lifo))) P99_NOP; \
01443     p00_el->p99_lifo = 0;                                                                          \
01444   }                                                                                                \
01445   p00_el;                                                                                          \
01446  })
01447 
01456 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_CLEAR, 0)
01457 #define P99_LIFO_CLEAR(L) atomic_fetch_and_store(L, 0)
01458 
01459 P00_DOCUMENT_TYPE_ARGUMENT(P99_LIFO_TABULATE, 0)
01460 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_LIFO_TABULATE, 1)
01461 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_TABULATE, 2)
01462 #define P99_LIFO_TABULATE(TYPE, TAB, L)                        \
01463 size_t P99_FILEID(TAB, _cnt) = 0;                              \
01464 TYPE * P99_FILEID(TAB, _head) = P99_LIFO_CLEAR(L);             \
01465 for (TYPE * p00_e = P99_FILEID(TAB, _head);                    \
01466      p00_e;                                                    \
01467      p00_e = p00_e->p99_lifo)                                  \
01468   ++P99_FILEID(TAB, _cnt);                                     \
01469 TYPE * TAB[P99_FILEID(TAB, _cnt)];                             \
01470 for (TYPE ** p00_t = &(TAB[0]),                                \
01471        * p00_e = P99_FILEID(TAB, _head);                       \
01472      p00_e;                                                    \
01473      p00_e = p00_e->p99_lifo,                                  \
01474        ++p00_t)                                                \
01475   *p00_t = p00_e
01476 
01481 # endif /* P00_NO_ATOMICS */
01482 #undef P00_NO_ATOMICS
01483 
01484 #endif
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines