00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00884 case memory_order_relaxed:
00885 p00_ret = P99_ENCP(p00_objp);
00886 P99_ENCP(p00_objp) = 1;
00887 break;
00888
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
00928 case memory_order_relaxed:
00929 P99_ENCP(p00_objp) = 0;
00930 break;
00931
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 \
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 \
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
01170 \
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
01482 #undef P00_NO_ATOMICS
01483
01484 #endif