packaging: remove nis/ nss
[platform/upstream/glibc.git] / include / atomic.h
1 /* Internal macros for atomic operations for GNU C Library.
2    Copyright (C) 2002-2023 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18
19 #ifndef _ATOMIC_H
20 #define _ATOMIC_H       1
21
22 /* This header defines three types of macros:
23
24    - atomic arithmetic and logic operation on memory.  They all
25      have the prefix "atomic_".
26
27    - conditionally atomic operations of the same kinds.  These
28      always behave identical but can be faster when atomicity
29      is not really needed since only one thread has access to
30      the memory location.  In that case the code is slower in
31      the multi-thread case.  The interfaces have the prefix
32      "catomic_".
33
34    - support functions like barriers.  They also have the prefix
35      "atomic_".
36
37    Architectures must provide a few lowlevel macros (the compare
38    and exchange definitions).  All others are optional.  They
39    should only be provided if the architecture has specific
40    support for the operation.
41
42    As <atomic.h> macros are usually heavily nested and often use local
43    variables to make sure side-effects are evaluated properly, use for
44    macro local variables a per-macro unique prefix.  This file uses
45    __atgN_ prefix where N is different in each macro.  */
46
47 #include <stdlib.h>
48
49 #include <atomic-machine.h>
50
51 /* Wrapper macros to call pre_NN_post (mem, ...) where NN is the
52    bit width of *MEM.  The calling macro puts parens around MEM
53    and following args.  */
54 #define __atomic_val_bysize(pre, post, mem, ...)                              \
55   ({                                                                          \
56     __typeof ((__typeof (*(mem))) *(mem)) __atg1_result;                      \
57     if (sizeof (*mem) == 1)                                                   \
58       __atg1_result = pre##_8_##post (mem, __VA_ARGS__);                      \
59     else if (sizeof (*mem) == 2)                                              \
60       __atg1_result = pre##_16_##post (mem, __VA_ARGS__);                     \
61     else if (sizeof (*mem) == 4)                                              \
62       __atg1_result = pre##_32_##post (mem, __VA_ARGS__);                     \
63     else if (sizeof (*mem) == 8)                                              \
64       __atg1_result = pre##_64_##post (mem, __VA_ARGS__);                     \
65     else                                                                      \
66       abort ();                                                               \
67     __atg1_result;                                                            \
68   })
69 #define __atomic_bool_bysize(pre, post, mem, ...)                             \
70   ({                                                                          \
71     int __atg2_result;                                                        \
72     if (sizeof (*mem) == 1)                                                   \
73       __atg2_result = pre##_8_##post (mem, __VA_ARGS__);                      \
74     else if (sizeof (*mem) == 2)                                              \
75       __atg2_result = pre##_16_##post (mem, __VA_ARGS__);                     \
76     else if (sizeof (*mem) == 4)                                              \
77       __atg2_result = pre##_32_##post (mem, __VA_ARGS__);                     \
78     else if (sizeof (*mem) == 8)                                              \
79       __atg2_result = pre##_64_##post (mem, __VA_ARGS__);                     \
80     else                                                                      \
81       abort ();                                                               \
82     __atg2_result;                                                            \
83   })
84
85
86 /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
87    Return the old *MEM value.  */
88 #if !defined atomic_compare_and_exchange_val_acq \
89     && defined __arch_compare_and_exchange_val_32_acq
90 # define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
91   __atomic_val_bysize (__arch_compare_and_exchange_val,acq,                   \
92                        mem, newval, oldval)
93 #endif
94
95
96 #ifndef catomic_compare_and_exchange_val_acq
97 # ifdef __arch_c_compare_and_exchange_val_32_acq
98 #  define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \
99   __atomic_val_bysize (__arch_c_compare_and_exchange_val,acq,                 \
100                        mem, newval, oldval)
101 # else
102 #  define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \
103   atomic_compare_and_exchange_val_acq (mem, newval, oldval)
104 # endif
105 #endif
106
107
108 #ifndef catomic_compare_and_exchange_val_rel
109 # ifndef atomic_compare_and_exchange_val_rel
110 #  define catomic_compare_and_exchange_val_rel(mem, newval, oldval)           \
111   catomic_compare_and_exchange_val_acq (mem, newval, oldval)
112 # else
113 #  define catomic_compare_and_exchange_val_rel(mem, newval, oldval)           \
114   atomic_compare_and_exchange_val_rel (mem, newval, oldval)
115 # endif
116 #endif
117
118
119 #ifndef atomic_compare_and_exchange_val_rel
120 # define atomic_compare_and_exchange_val_rel(mem, newval, oldval)             \
121   atomic_compare_and_exchange_val_acq (mem, newval, oldval)
122 #endif
123
124
125 /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
126    Return zero if *MEM was changed or non-zero if no exchange happened.  */
127 #ifndef atomic_compare_and_exchange_bool_acq
128 # ifdef __arch_compare_and_exchange_bool_32_acq
129 #  define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
130   __atomic_bool_bysize (__arch_compare_and_exchange_bool,acq,                 \
131                         mem, newval, oldval)
132 # else
133 #  define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
134   ({ /* Cannot use __oldval here, because macros later in this file might     \
135         call this macro with __oldval argument.  */                           \
136      __typeof (oldval) __atg3_old = (oldval);                                 \
137      atomic_compare_and_exchange_val_acq (mem, newval, __atg3_old)            \
138        != __atg3_old;                                                         \
139   })
140 # endif
141 #endif
142
143
144 #ifndef catomic_compare_and_exchange_bool_acq
145 # ifdef __arch_c_compare_and_exchange_bool_32_acq
146 #  define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
147   __atomic_bool_bysize (__arch_c_compare_and_exchange_bool,acq,               \
148                         mem, newval, oldval)
149 # else
150 #  define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
151   ({ /* Cannot use __oldval here, because macros later in this file might     \
152         call this macro with __oldval argument.  */                           \
153      __typeof (oldval) __atg4_old = (oldval);                                 \
154      catomic_compare_and_exchange_val_acq (mem, newval, __atg4_old)           \
155        != __atg4_old;                                                         \
156   })
157 # endif
158 #endif
159
160
161 /* Store NEWVALUE in *MEM and return the old value.  */
162 #ifndef atomic_exchange_acq
163 # define atomic_exchange_acq(mem, newvalue) \
164   ({ __typeof ((__typeof (*(mem))) *(mem)) __atg5_oldval;                     \
165      __typeof (mem) __atg5_memp = (mem);                                      \
166      __typeof ((__typeof (*(mem))) *(mem)) __atg5_value = (newvalue);         \
167                                                                               \
168      do                                                                       \
169        __atg5_oldval = *__atg5_memp;                                          \
170      while (__builtin_expect                                                  \
171             (atomic_compare_and_exchange_bool_acq (__atg5_memp, __atg5_value, \
172                                                    __atg5_oldval), 0));       \
173                                                                               \
174      __atg5_oldval; })
175 #endif
176
177 #ifndef atomic_exchange_rel
178 # define atomic_exchange_rel(mem, newvalue) atomic_exchange_acq (mem, newvalue)
179 #endif
180
181
182 /* Add VALUE to *MEM and return the old value of *MEM.  */
183 #ifndef atomic_exchange_and_add_acq
184 # ifdef atomic_exchange_and_add
185 #  define atomic_exchange_and_add_acq(mem, value) \
186   atomic_exchange_and_add (mem, value)
187 # else
188 #  define atomic_exchange_and_add_acq(mem, value) \
189   ({ __typeof (*(mem)) __atg6_oldval;                                         \
190      __typeof (mem) __atg6_memp = (mem);                                      \
191      __typeof (*(mem)) __atg6_value = (value);                                \
192                                                                               \
193      do                                                                       \
194        __atg6_oldval = *__atg6_memp;                                          \
195      while (__builtin_expect                                                  \
196             (atomic_compare_and_exchange_bool_acq (__atg6_memp,               \
197                                                    __atg6_oldval              \
198                                                    + __atg6_value,            \
199                                                    __atg6_oldval), 0));       \
200                                                                               \
201      __atg6_oldval; })
202 # endif
203 #endif
204
205 #ifndef atomic_exchange_and_add_rel
206 # define atomic_exchange_and_add_rel(mem, value) \
207   atomic_exchange_and_add_acq(mem, value)
208 #endif
209
210 #ifndef atomic_exchange_and_add
211 # define atomic_exchange_and_add(mem, value) \
212   atomic_exchange_and_add_acq(mem, value)
213 #endif
214
215 #ifndef catomic_exchange_and_add
216 # define catomic_exchange_and_add(mem, value) \
217   ({ __typeof (*(mem)) __atg7_oldv;                                           \
218      __typeof (mem) __atg7_memp = (mem);                                      \
219      __typeof (*(mem)) __atg7_value = (value);                                \
220                                                                               \
221      do                                                                       \
222        __atg7_oldv = *__atg7_memp;                                            \
223      while (__builtin_expect                                                  \
224             (catomic_compare_and_exchange_bool_acq (__atg7_memp,              \
225                                                     __atg7_oldv               \
226                                                     + __atg7_value,           \
227                                                     __atg7_oldv), 0));        \
228                                                                               \
229      __atg7_oldv; })
230 #endif
231
232
233 #ifndef atomic_max
234 # define atomic_max(mem, value) \
235   do {                                                                        \
236     __typeof (*(mem)) __atg8_oldval;                                          \
237     __typeof (mem) __atg8_memp = (mem);                                       \
238     __typeof (*(mem)) __atg8_value = (value);                                 \
239     do {                                                                      \
240       __atg8_oldval = *__atg8_memp;                                           \
241       if (__atg8_oldval >= __atg8_value)                                      \
242         break;                                                                \
243     } while (__builtin_expect                                                 \
244              (atomic_compare_and_exchange_bool_acq (__atg8_memp, __atg8_value,\
245                                                     __atg8_oldval), 0));      \
246   } while (0)
247 #endif
248
249
250 #ifndef catomic_max
251 # define catomic_max(mem, value) \
252   do {                                                                        \
253     __typeof (*(mem)) __atg9_oldv;                                            \
254     __typeof (mem) __atg9_memp = (mem);                                       \
255     __typeof (*(mem)) __atg9_value = (value);                                 \
256     do {                                                                      \
257       __atg9_oldv = *__atg9_memp;                                             \
258       if (__atg9_oldv >= __atg9_value)                                        \
259         break;                                                                \
260     } while (__builtin_expect                                                 \
261              (catomic_compare_and_exchange_bool_acq (__atg9_memp,             \
262                                                      __atg9_value,            \
263                                                      __atg9_oldv), 0));       \
264   } while (0)
265 #endif
266
267
268 #ifndef atomic_min
269 # define atomic_min(mem, value) \
270   do {                                                                        \
271     __typeof (*(mem)) __atg10_oldval;                                         \
272     __typeof (mem) __atg10_memp = (mem);                                      \
273     __typeof (*(mem)) __atg10_value = (value);                                \
274     do {                                                                      \
275       __atg10_oldval = *__atg10_memp;                                         \
276       if (__atg10_oldval <= __atg10_value)                                    \
277         break;                                                                \
278     } while (__builtin_expect                                                 \
279              (atomic_compare_and_exchange_bool_acq (__atg10_memp,             \
280                                                     __atg10_value,            \
281                                                     __atg10_oldval), 0));     \
282   } while (0)
283 #endif
284
285
286 #ifndef atomic_add
287 # define atomic_add(mem, value) (void) atomic_exchange_and_add ((mem), (value))
288 #endif
289
290
291 #ifndef catomic_add
292 # define catomic_add(mem, value) \
293   (void) catomic_exchange_and_add ((mem), (value))
294 #endif
295
296
297 #ifndef atomic_increment
298 # define atomic_increment(mem) atomic_add ((mem), 1)
299 #endif
300
301
302 #ifndef catomic_increment
303 # define catomic_increment(mem) catomic_add ((mem), 1)
304 #endif
305
306
307 #ifndef atomic_increment_val
308 # define atomic_increment_val(mem) (atomic_exchange_and_add ((mem), 1) + 1)
309 #endif
310
311
312 #ifndef catomic_increment_val
313 # define catomic_increment_val(mem) (catomic_exchange_and_add ((mem), 1) + 1)
314 #endif
315
316
317 /* Add one to *MEM and return true iff it's now zero.  */
318 #ifndef atomic_increment_and_test
319 # define atomic_increment_and_test(mem) \
320   (atomic_exchange_and_add ((mem), 1) + 1 == 0)
321 #endif
322
323
324 #ifndef atomic_decrement
325 # define atomic_decrement(mem) atomic_add ((mem), -1)
326 #endif
327
328
329 #ifndef catomic_decrement
330 # define catomic_decrement(mem) catomic_add ((mem), -1)
331 #endif
332
333
334 #ifndef atomic_decrement_val
335 # define atomic_decrement_val(mem) (atomic_exchange_and_add ((mem), -1) - 1)
336 #endif
337
338
339 #ifndef catomic_decrement_val
340 # define catomic_decrement_val(mem) (catomic_exchange_and_add ((mem), -1) - 1)
341 #endif
342
343
344 /* Subtract 1 from *MEM and return true iff it's now zero.  */
345 #ifndef atomic_decrement_and_test
346 # define atomic_decrement_and_test(mem) \
347   (atomic_exchange_and_add ((mem), -1) == 1)
348 #endif
349
350
351 /* Decrement *MEM if it is > 0, and return the old value.  */
352 #ifndef atomic_decrement_if_positive
353 # define atomic_decrement_if_positive(mem) \
354   ({ __typeof (*(mem)) __atg11_oldval;                                        \
355      __typeof (mem) __atg11_memp = (mem);                                     \
356                                                                               \
357      do                                                                       \
358        {                                                                      \
359          __atg11_oldval = *__atg11_memp;                                      \
360          if (__glibc_unlikely (__atg11_oldval <= 0))                          \
361            break;                                                             \
362        }                                                                      \
363      while (__builtin_expect                                                  \
364             (atomic_compare_and_exchange_bool_acq (__atg11_memp,              \
365                                                    __atg11_oldval - 1,        \
366                                                    __atg11_oldval), 0));      \
367      __atg11_oldval; })
368 #endif
369
370
371 #ifndef atomic_add_negative
372 # define atomic_add_negative(mem, value)                                      \
373   ({ __typeof (value) __atg12_value = (value);                                \
374      atomic_exchange_and_add (mem, __atg12_value) < -__atg12_value; })
375 #endif
376
377
378 #ifndef atomic_add_zero
379 # define atomic_add_zero(mem, value)                                          \
380   ({ __typeof (value) __atg13_value = (value);                                \
381      atomic_exchange_and_add (mem, __atg13_value) == -__atg13_value; })
382 #endif
383
384
385 #ifndef atomic_bit_set
386 # define atomic_bit_set(mem, bit) \
387   (void) atomic_bit_test_set(mem, bit)
388 #endif
389
390
391 #ifndef atomic_bit_test_set
392 # define atomic_bit_test_set(mem, bit) \
393   ({ __typeof (*(mem)) __atg14_old;                                           \
394      __typeof (mem) __atg14_memp = (mem);                                     \
395      __typeof (*(mem)) __atg14_mask = ((__typeof (*(mem))) 1 << (bit));       \
396                                                                               \
397      do                                                                       \
398        __atg14_old = (*__atg14_memp);                                         \
399      while (__builtin_expect                                                  \
400             (atomic_compare_and_exchange_bool_acq (__atg14_memp,              \
401                                                    __atg14_old | __atg14_mask,\
402                                                    __atg14_old), 0));         \
403                                                                               \
404      __atg14_old & __atg14_mask; })
405 #endif
406
407 /* Atomically *mem &= mask.  */
408 #ifndef atomic_and
409 # define atomic_and(mem, mask) \
410   do {                                                                        \
411     __typeof (*(mem)) __atg15_old;                                            \
412     __typeof (mem) __atg15_memp = (mem);                                      \
413     __typeof (*(mem)) __atg15_mask = (mask);                                  \
414                                                                               \
415     do                                                                        \
416       __atg15_old = (*__atg15_memp);                                          \
417     while (__builtin_expect                                                   \
418            (atomic_compare_and_exchange_bool_acq (__atg15_memp,               \
419                                                   __atg15_old & __atg15_mask, \
420                                                   __atg15_old), 0));          \
421   } while (0)
422 #endif
423
424 #ifndef catomic_and
425 # define catomic_and(mem, mask) \
426   do {                                                                        \
427     __typeof (*(mem)) __atg20_old;                                            \
428     __typeof (mem) __atg20_memp = (mem);                                      \
429     __typeof (*(mem)) __atg20_mask = (mask);                                  \
430                                                                               \
431     do                                                                        \
432       __atg20_old = (*__atg20_memp);                                          \
433     while (__builtin_expect                                                   \
434            (catomic_compare_and_exchange_bool_acq (__atg20_memp,              \
435                                                    __atg20_old & __atg20_mask,\
436                                                    __atg20_old), 0));         \
437   } while (0)
438 #endif
439
440 /* Atomically *mem &= mask and return the old value of *mem.  */
441 #ifndef atomic_and_val
442 # define atomic_and_val(mem, mask) \
443   ({ __typeof (*(mem)) __atg16_old;                                           \
444      __typeof (mem) __atg16_memp = (mem);                                     \
445      __typeof (*(mem)) __atg16_mask = (mask);                                 \
446                                                                               \
447      do                                                                       \
448        __atg16_old = (*__atg16_memp);                                         \
449      while (__builtin_expect                                                  \
450             (atomic_compare_and_exchange_bool_acq (__atg16_memp,              \
451                                                    __atg16_old & __atg16_mask,\
452                                                    __atg16_old), 0));         \
453                                                                               \
454      __atg16_old; })
455 #endif
456
457 /* Atomically *mem |= mask and return the old value of *mem.  */
458 #ifndef atomic_or
459 # define atomic_or(mem, mask) \
460   do {                                                                        \
461     __typeof (*(mem)) __atg17_old;                                            \
462     __typeof (mem) __atg17_memp = (mem);                                      \
463     __typeof (*(mem)) __atg17_mask = (mask);                                  \
464                                                                               \
465     do                                                                        \
466       __atg17_old = (*__atg17_memp);                                          \
467     while (__builtin_expect                                                   \
468            (atomic_compare_and_exchange_bool_acq (__atg17_memp,               \
469                                                   __atg17_old | __atg17_mask, \
470                                                   __atg17_old), 0));          \
471   } while (0)
472 #endif
473
474 #ifndef catomic_or
475 # define catomic_or(mem, mask) \
476   do {                                                                        \
477     __typeof (*(mem)) __atg18_old;                                            \
478     __typeof (mem) __atg18_memp = (mem);                                      \
479     __typeof (*(mem)) __atg18_mask = (mask);                                  \
480                                                                               \
481     do                                                                        \
482       __atg18_old = (*__atg18_memp);                                          \
483     while (__builtin_expect                                                   \
484            (catomic_compare_and_exchange_bool_acq (__atg18_memp,              \
485                                                    __atg18_old | __atg18_mask,\
486                                                    __atg18_old), 0));         \
487   } while (0)
488 #endif
489
490 /* Atomically *mem |= mask and return the old value of *mem.  */
491 #ifndef atomic_or_val
492 # define atomic_or_val(mem, mask) \
493   ({ __typeof (*(mem)) __atg19_old;                                           \
494      __typeof (mem) __atg19_memp = (mem);                                     \
495      __typeof (*(mem)) __atg19_mask = (mask);                                 \
496                                                                               \
497      do                                                                       \
498        __atg19_old = (*__atg19_memp);                                         \
499      while (__builtin_expect                                                  \
500             (atomic_compare_and_exchange_bool_acq (__atg19_memp,              \
501                                                    __atg19_old | __atg19_mask,\
502                                                    __atg19_old), 0));         \
503                                                                               \
504      __atg19_old; })
505 #endif
506
507 #ifndef atomic_full_barrier
508 # define atomic_full_barrier() __asm ("" ::: "memory")
509 #endif
510
511
512 #ifndef atomic_read_barrier
513 # define atomic_read_barrier() atomic_full_barrier ()
514 #endif
515
516
517 #ifndef atomic_write_barrier
518 # define atomic_write_barrier() atomic_full_barrier ()
519 #endif
520
521
522 #ifndef atomic_forced_read
523 # define atomic_forced_read(x) \
524   ({ __typeof (x) __x; __asm ("" : "=r" (__x) : "0" (x)); __x; })
525 #endif
526
527 /* This is equal to 1 iff the architecture supports 64b atomic operations.  */
528 #ifndef __HAVE_64B_ATOMICS
529 #error Unable to determine if 64-bit atomics are present.
530 #endif
531
532 /* The following functions are a subset of the atomic operations provided by
533    C11.  Usually, a function named atomic_OP_MO(args) is equivalent to C11's
534    atomic_OP_explicit(args, memory_order_MO); exceptions noted below.  */
535
536 /* Each arch can request to use compiler built-ins for C11 atomics.  If it
537    does, all atomics will be based on these.  */
538 #if USE_ATOMIC_COMPILER_BUILTINS
539
540 /* We require 32b atomic operations; some archs also support 64b atomic
541    operations.  */
542 void __atomic_link_error (void);
543 # if __HAVE_64B_ATOMICS == 1
544 #  define __atomic_check_size(mem) \
545    if ((sizeof (*mem) != 4) && (sizeof (*mem) != 8))                          \
546      __atomic_link_error ();
547 # else
548 #  define __atomic_check_size(mem) \
549    if (sizeof (*mem) != 4)                                                    \
550      __atomic_link_error ();
551 # endif
552 /* We additionally provide 8b and 16b atomic loads and stores; we do not yet
553    need other atomic operations of such sizes, and restricting the support to
554    loads and stores makes this easier for archs that do not have native
555    support for atomic operations to less-than-word-sized data.  */
556 # if __HAVE_64B_ATOMICS == 1
557 #  define __atomic_check_size_ls(mem) \
558    if ((sizeof (*mem) != 1) && (sizeof (*mem) != 2) && (sizeof (*mem) != 4)   \
559        && (sizeof (*mem) != 8))                                               \
560      __atomic_link_error ();
561 # else
562 #  define __atomic_check_size_ls(mem) \
563    if ((sizeof (*mem) != 1) && (sizeof (*mem) != 2) && sizeof (*mem) != 4)    \
564      __atomic_link_error ();
565 # endif
566
567 # define atomic_thread_fence_acquire() \
568   __atomic_thread_fence (__ATOMIC_ACQUIRE)
569 # define atomic_thread_fence_release() \
570   __atomic_thread_fence (__ATOMIC_RELEASE)
571 # define atomic_thread_fence_seq_cst() \
572   __atomic_thread_fence (__ATOMIC_SEQ_CST)
573
574 # define atomic_load_relaxed(mem) \
575   ({ __atomic_check_size_ls((mem));                                           \
576      __atomic_load_n ((mem), __ATOMIC_RELAXED); })
577 # define atomic_load_acquire(mem) \
578   ({ __atomic_check_size_ls((mem));                                           \
579      __atomic_load_n ((mem), __ATOMIC_ACQUIRE); })
580
581 # define atomic_store_relaxed(mem, val) \
582   do {                                                                        \
583     __atomic_check_size_ls((mem));                                            \
584     __atomic_store_n ((mem), (val), __ATOMIC_RELAXED);                        \
585   } while (0)
586 # define atomic_store_release(mem, val) \
587   do {                                                                        \
588     __atomic_check_size_ls((mem));                                            \
589     __atomic_store_n ((mem), (val), __ATOMIC_RELEASE);                        \
590   } while (0)
591
592 /* On failure, this CAS has memory_order_relaxed semantics.  */
593 # define atomic_compare_exchange_weak_relaxed(mem, expected, desired) \
594   ({ __atomic_check_size((mem));                                              \
595   __atomic_compare_exchange_n ((mem), (expected), (desired), 1,               \
596     __ATOMIC_RELAXED, __ATOMIC_RELAXED); })
597 # define atomic_compare_exchange_weak_acquire(mem, expected, desired) \
598   ({ __atomic_check_size((mem));                                              \
599   __atomic_compare_exchange_n ((mem), (expected), (desired), 1,               \
600     __ATOMIC_ACQUIRE, __ATOMIC_RELAXED); })
601 # define atomic_compare_exchange_weak_release(mem, expected, desired) \
602   ({ __atomic_check_size((mem));                                              \
603   __atomic_compare_exchange_n ((mem), (expected), (desired), 1,               \
604     __ATOMIC_RELEASE, __ATOMIC_RELAXED); })
605
606 # define atomic_exchange_relaxed(mem, desired) \
607   ({ __atomic_check_size((mem));                                              \
608   __atomic_exchange_n ((mem), (desired), __ATOMIC_RELAXED); })
609 # define atomic_exchange_acquire(mem, desired) \
610   ({ __atomic_check_size((mem));                                              \
611   __atomic_exchange_n ((mem), (desired), __ATOMIC_ACQUIRE); })
612 # define atomic_exchange_release(mem, desired) \
613   ({ __atomic_check_size((mem));                                              \
614   __atomic_exchange_n ((mem), (desired), __ATOMIC_RELEASE); })
615
616 # define atomic_fetch_add_relaxed(mem, operand) \
617   ({ __atomic_check_size((mem));                                              \
618   __atomic_fetch_add ((mem), (operand), __ATOMIC_RELAXED); })
619 # define atomic_fetch_add_acquire(mem, operand) \
620   ({ __atomic_check_size((mem));                                              \
621   __atomic_fetch_add ((mem), (operand), __ATOMIC_ACQUIRE); })
622 # define atomic_fetch_add_release(mem, operand) \
623   ({ __atomic_check_size((mem));                                              \
624   __atomic_fetch_add ((mem), (operand), __ATOMIC_RELEASE); })
625 # define atomic_fetch_add_acq_rel(mem, operand) \
626   ({ __atomic_check_size((mem));                                              \
627   __atomic_fetch_add ((mem), (operand), __ATOMIC_ACQ_REL); })
628
629 # define atomic_fetch_and_relaxed(mem, operand) \
630   ({ __atomic_check_size((mem));                                              \
631   __atomic_fetch_and ((mem), (operand), __ATOMIC_RELAXED); })
632 # define atomic_fetch_and_acquire(mem, operand) \
633   ({ __atomic_check_size((mem));                                              \
634   __atomic_fetch_and ((mem), (operand), __ATOMIC_ACQUIRE); })
635 # define atomic_fetch_and_release(mem, operand) \
636   ({ __atomic_check_size((mem));                                              \
637   __atomic_fetch_and ((mem), (operand), __ATOMIC_RELEASE); })
638
639 # define atomic_fetch_or_relaxed(mem, operand) \
640   ({ __atomic_check_size((mem));                                              \
641   __atomic_fetch_or ((mem), (operand), __ATOMIC_RELAXED); })
642 # define atomic_fetch_or_acquire(mem, operand) \
643   ({ __atomic_check_size((mem));                                              \
644   __atomic_fetch_or ((mem), (operand), __ATOMIC_ACQUIRE); })
645 # define atomic_fetch_or_release(mem, operand) \
646   ({ __atomic_check_size((mem));                                              \
647   __atomic_fetch_or ((mem), (operand), __ATOMIC_RELEASE); })
648
649 # define atomic_fetch_xor_release(mem, operand) \
650   ({ __atomic_check_size((mem));                                              \
651   __atomic_fetch_xor ((mem), (operand), __ATOMIC_RELEASE); })
652
653 #else /* !USE_ATOMIC_COMPILER_BUILTINS  */
654
655 /* By default, we assume that read, write, and full barriers are equivalent
656    to acquire, release, and seq_cst barriers.  Archs for which this does not
657    hold have to provide custom definitions of the fences.  */
658 # ifndef atomic_thread_fence_acquire
659 #  define atomic_thread_fence_acquire() atomic_read_barrier ()
660 # endif
661 # ifndef atomic_thread_fence_release
662 #  define atomic_thread_fence_release() atomic_write_barrier ()
663 # endif
664 # ifndef atomic_thread_fence_seq_cst
665 #  define atomic_thread_fence_seq_cst() atomic_full_barrier ()
666 # endif
667
668 # ifndef atomic_load_relaxed
669 #  define atomic_load_relaxed(mem) \
670    ({ __typeof ((__typeof (*(mem))) *(mem)) __atg100_val;                     \
671    __asm ("" : "=r" (__atg100_val) : "0" (*(mem)));                           \
672    __atg100_val; })
673 # endif
674 # ifndef atomic_load_acquire
675 #  define atomic_load_acquire(mem) \
676    ({ __typeof (*(mem)) __atg101_val = atomic_load_relaxed (mem);             \
677    atomic_thread_fence_acquire ();                                            \
678    __atg101_val; })
679 # endif
680
681 # ifndef atomic_store_relaxed
682 /* XXX Use inline asm here?  */
683 #  define atomic_store_relaxed(mem, val) do { *(mem) = (val); } while (0)
684 # endif
685 # ifndef atomic_store_release
686 #  define atomic_store_release(mem, val) \
687    do {                                                                       \
688      atomic_thread_fence_release ();                                          \
689      atomic_store_relaxed ((mem), (val));                                     \
690    } while (0)
691 # endif
692
693 /* On failure, this CAS has memory_order_relaxed semantics.  */
694 /* XXX This potentially has one branch more than necessary, but archs
695    currently do not define a CAS that returns both the previous value and
696    the success flag.  */
697 # ifndef atomic_compare_exchange_weak_acquire
698 #  define atomic_compare_exchange_weak_acquire(mem, expected, desired) \
699    ({ typeof (*(expected)) __atg102_expected = *(expected);                   \
700    *(expected) =                                                              \
701      atomic_compare_and_exchange_val_acq ((mem), (desired), *(expected));     \
702    *(expected) == __atg102_expected; })
703 # endif
704 # ifndef atomic_compare_exchange_weak_relaxed
705 /* XXX Fall back to CAS with acquire MO because archs do not define a weaker
706    CAS.  */
707 #  define atomic_compare_exchange_weak_relaxed(mem, expected, desired) \
708    atomic_compare_exchange_weak_acquire ((mem), (expected), (desired))
709 # endif
710 # ifndef atomic_compare_exchange_weak_release
711 #  define atomic_compare_exchange_weak_release(mem, expected, desired) \
712    ({ typeof (*(expected)) __atg103_expected = *(expected);                   \
713    *(expected) =                                                              \
714      atomic_compare_and_exchange_val_rel ((mem), (desired), *(expected));     \
715    *(expected) == __atg103_expected; })
716 # endif
717
718 /* XXX Fall back to acquire MO because archs do not define a weaker
719    atomic_exchange.  */
720 # ifndef atomic_exchange_relaxed
721 #  define atomic_exchange_relaxed(mem, val) \
722    atomic_exchange_acq ((mem), (val))
723 # endif
724 # ifndef atomic_exchange_acquire
725 #  define atomic_exchange_acquire(mem, val) \
726    atomic_exchange_acq ((mem), (val))
727 # endif
728 # ifndef atomic_exchange_release
729 #  define atomic_exchange_release(mem, val) \
730    atomic_exchange_rel ((mem), (val))
731 # endif
732
733 # ifndef atomic_fetch_add_acquire
734 #  define atomic_fetch_add_acquire(mem, operand) \
735    atomic_exchange_and_add_acq ((mem), (operand))
736 # endif
737 # ifndef atomic_fetch_add_relaxed
738 /* XXX Fall back to acquire MO because the MO semantics of
739    atomic_exchange_and_add are not documented; the generic version falls back
740    to atomic_exchange_and_add_acq if atomic_exchange_and_add is not defined,
741    and vice versa.  */
742 #  define atomic_fetch_add_relaxed(mem, operand) \
743    atomic_fetch_add_acquire ((mem), (operand))
744 # endif
745 # ifndef atomic_fetch_add_release
746 #  define atomic_fetch_add_release(mem, operand) \
747    atomic_exchange_and_add_rel ((mem), (operand))
748 # endif
749 # ifndef atomic_fetch_add_acq_rel
750 #  define atomic_fetch_add_acq_rel(mem, operand) \
751    ({ atomic_thread_fence_release ();                                         \
752    atomic_exchange_and_add_acq ((mem), (operand)); })
753 # endif
754
755 /* XXX Fall back to acquire MO because archs do not define a weaker
756    atomic_and_val.  */
757 # ifndef atomic_fetch_and_relaxed
758 #  define atomic_fetch_and_relaxed(mem, operand) \
759    atomic_fetch_and_acquire ((mem), (operand))
760 # endif
761 /* XXX The default for atomic_and_val has acquire semantics, but this is not
762    documented.  */
763 # ifndef atomic_fetch_and_acquire
764 #  define atomic_fetch_and_acquire(mem, operand) \
765    atomic_and_val ((mem), (operand))
766 # endif
767 # ifndef atomic_fetch_and_release
768 /* XXX This unnecessarily has acquire MO.  */
769 #  define atomic_fetch_and_release(mem, operand) \
770    ({ atomic_thread_fence_release ();                                         \
771    atomic_and_val ((mem), (operand)); })
772 # endif
773
774 /* XXX The default for atomic_or_val has acquire semantics, but this is not
775    documented.  */
776 # ifndef atomic_fetch_or_acquire
777 #  define atomic_fetch_or_acquire(mem, operand) \
778    atomic_or_val ((mem), (operand))
779 # endif
780 /* XXX Fall back to acquire MO because archs do not define a weaker
781    atomic_or_val.  */
782 # ifndef atomic_fetch_or_relaxed
783 #  define atomic_fetch_or_relaxed(mem, operand) \
784    atomic_fetch_or_acquire ((mem), (operand))
785 # endif
786 /* XXX Contains an unnecessary acquire MO because archs do not define a weaker
787    atomic_or_val.  */
788 # ifndef atomic_fetch_or_release
789 #  define atomic_fetch_or_release(mem, operand) \
790    ({ atomic_thread_fence_release ();                                         \
791    atomic_fetch_or_acquire ((mem), (operand)); })
792 # endif
793
794 # ifndef atomic_fetch_xor_release
795 /* Failing the atomic_compare_exchange_weak_release reloads the value in
796    __atg104_expected, so we need only do the XOR again and retry.  */
797 # define atomic_fetch_xor_release(mem, operand) \
798   ({ __typeof (mem) __atg104_memp = (mem);                                    \
799      __typeof (*(mem)) __atg104_expected = (*__atg104_memp);                  \
800      __typeof (*(mem)) __atg104_desired;                                      \
801      __typeof (*(mem)) __atg104_op = (operand);                               \
802                                                                               \
803      do                                                                       \
804        __atg104_desired = __atg104_expected ^ __atg104_op;                    \
805      while (__glibc_unlikely                                                  \
806             (atomic_compare_exchange_weak_release (                           \
807                __atg104_memp, &__atg104_expected, __atg104_desired)           \
808              == 0));                                                          \
809      __atg104_expected; })
810 #endif
811
812 #endif /* !USE_ATOMIC_COMPILER_BUILTINS  */
813
814 /* This operation does not affect synchronization semantics but can be used
815    in the body of a spin loop to potentially improve its efficiency.  */
816 #ifndef atomic_spin_nop
817 # define atomic_spin_nop() do { /* nothing */ } while (0)
818 #endif
819
820 /* ATOMIC_EXCHANGE_USES_CAS is non-zero if atomic_exchange operations
821    are implemented based on a CAS loop; otherwise, this is zero and we assume
822    that the atomic_exchange operations could provide better performance
823    than a CAS loop.  */
824 #ifndef ATOMIC_EXCHANGE_USES_CAS
825 # error ATOMIC_EXCHANGE_USES_CAS has to be defined.
826 #endif
827
828 #endif  /* atomic.h */