]> sourceware.org Git - glibc.git/blame - include/atomic.h
Fix memory overrun in getifaddrs_internal. Fixes bug 15698.
[glibc.git] / include / atomic.h
CommitLineData
d15851ec 1/* Internal macros for atomic operations for GNU C Library.
d4697bc9 2 Copyright (C) 2002-2014 Free Software Foundation, Inc.
76a50749
UD
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
76a50749
UD
19
20#ifndef _ATOMIC_H
21#define _ATOMIC_H 1
22
11bf311e
UD
23/* This header defines three types of macros:
24
25 - atomic arithmetic and logic operation on memory. They all
26 have the prefix "atomic_".
27
28 - conditionally atomic operations of the same kinds. These
29 always behave identical but can be faster when atomicity
30 is not really needed since only one thread has access to
31 the memory location. In that case the code is slower in
32 the multi-thread case. The interfaces have the prefix
33 "catomic_".
34
eaea92f1 35 - support functions like barriers. They also have the prefix
11bf311e
UD
36 "atomic_".
37
38 Architectures must provide a few lowlevel macros (the compare
39 and exchange definitions). All others are optional. They
40 should only be provided if the architecture has specific
41 support for the operation.
42
43 As <atomic.h> macros are usually heavily nested and often use local
44 variables to make sure side-effects are evaluated properly, use for
45 macro local variables a per-macro unique prefix. This file uses
46 __atgN_ prefix where N is different in each macro. */
47
76a50749
UD
48#include <stdlib.h>
49
50#include <bits/atomic.h>
51
fe4610b3
RM
52/* Wrapper macros to call pre_NN_post (mem, ...) where NN is the
53 bit width of *MEM. The calling macro puts parens around MEM
54 and following args. */
55#define __atomic_val_bysize(pre, post, mem, ...) \
56 ({ \
11bf311e 57 __typeof (*mem) __atg1_result; \
fe4610b3 58 if (sizeof (*mem) == 1) \
11bf311e 59 __atg1_result = pre##_8_##post (mem, __VA_ARGS__); \
fe4610b3 60 else if (sizeof (*mem) == 2) \
11bf311e 61 __atg1_result = pre##_16_##post (mem, __VA_ARGS__); \
fe4610b3 62 else if (sizeof (*mem) == 4) \
11bf311e 63 __atg1_result = pre##_32_##post (mem, __VA_ARGS__); \
fe4610b3 64 else if (sizeof (*mem) == 8) \
11bf311e 65 __atg1_result = pre##_64_##post (mem, __VA_ARGS__); \
fe4610b3
RM
66 else \
67 abort (); \
11bf311e 68 __atg1_result; \
fe4610b3
RM
69 })
70#define __atomic_bool_bysize(pre, post, mem, ...) \
71 ({ \
11bf311e 72 int __atg2_result; \
fe4610b3 73 if (sizeof (*mem) == 1) \
11bf311e 74 __atg2_result = pre##_8_##post (mem, __VA_ARGS__); \
fe4610b3 75 else if (sizeof (*mem) == 2) \
11bf311e 76 __atg2_result = pre##_16_##post (mem, __VA_ARGS__); \
fe4610b3 77 else if (sizeof (*mem) == 4) \
11bf311e 78 __atg2_result = pre##_32_##post (mem, __VA_ARGS__); \
fe4610b3 79 else if (sizeof (*mem) == 8) \
11bf311e 80 __atg2_result = pre##_64_##post (mem, __VA_ARGS__); \
fe4610b3
RM
81 else \
82 abort (); \
11bf311e 83 __atg2_result; \
fe4610b3
RM
84 })
85
76a50749 86
d15851ec
RM
87/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
88 Return the old *MEM value. */
89#if !defined atomic_compare_and_exchange_val_acq \
90 && defined __arch_compare_and_exchange_val_32_acq
18627f61 91# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
a1b5424f
UD
92 __atomic_val_bysize (__arch_compare_and_exchange_val,acq, \
93 mem, newval, oldval)
76a50749
UD
94#endif
95
96
3b1b533b
JJ
97#ifndef catomic_compare_and_exchange_val_acq
98# ifdef __arch_c_compare_and_exchange_val_32_acq
99# define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \
11bf311e
UD
100 __atomic_val_bysize (__arch_c_compare_and_exchange_val,acq, \
101 mem, newval, oldval)
3b1b533b
JJ
102# else
103# define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \
11bf311e 104 atomic_compare_and_exchange_val_acq (mem, newval, oldval)
3b1b533b 105# endif
11bf311e
UD
106#endif
107
108
bea0ac1d
JJ
109#ifndef catomic_compare_and_exchange_val_rel
110# ifndef atomic_compare_and_exchange_val_rel
111# define catomic_compare_and_exchange_val_rel(mem, newval, oldval) \
112 catomic_compare_and_exchange_val_acq (mem, newval, oldval)
113# else
114# define catomic_compare_and_exchange_val_rel(mem, newval, oldval) \
115 atomic_compare_and_exchange_val_rel (mem, newval, oldval)
116# endif
18627f61
UD
117#endif
118
119
bea0ac1d
JJ
120#ifndef atomic_compare_and_exchange_val_rel
121# define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
11bf311e
UD
122 atomic_compare_and_exchange_val_acq (mem, newval, oldval)
123#endif
124
125
d15851ec
RM
126/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
127 Return zero if *MEM was changed or non-zero if no exchange happened. */
18627f61
UD
128#ifndef atomic_compare_and_exchange_bool_acq
129# ifdef __arch_compare_and_exchange_bool_32_acq
18627f61 130# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
a1b5424f
UD
131 __atomic_bool_bysize (__arch_compare_and_exchange_bool,acq, \
132 mem, newval, oldval)
3b1b533b
JJ
133# else
134# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
d15851ec
RM
135 ({ /* Cannot use __oldval here, because macros later in this file might \
136 call this macro with __oldval argument. */ \
11bf311e
UD
137 __typeof (oldval) __atg3_old = (oldval); \
138 atomic_compare_and_exchange_val_acq (mem, newval, __atg3_old) \
139 != __atg3_old; \
140 })
141# endif
142#endif
143
144
145#ifndef catomic_compare_and_exchange_bool_acq
146# ifdef __arch_c_compare_and_exchange_bool_32_acq
147# define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
148 __atomic_bool_bysize (__arch_c_compare_and_exchange_bool,acq, \
149 mem, newval, oldval)
3b1b533b
JJ
150# else
151# define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
11bf311e
UD
152 ({ /* Cannot use __oldval here, because macros later in this file might \
153 call this macro with __oldval argument. */ \
154 __typeof (oldval) __atg4_old = (oldval); \
155 catomic_compare_and_exchange_val_acq (mem, newval, __atg4_old) \
156 != __atg4_old; \
8099361e
UD
157 })
158# endif
159#endif
160
161
bea0ac1d
JJ
162#ifndef catomic_compare_and_exchange_bool_rel
163# ifndef atomic_compare_and_exchange_bool_rel
164# define catomic_compare_and_exchange_bool_rel(mem, newval, oldval) \
165 catomic_compare_and_exchange_bool_acq (mem, newval, oldval)
166# else
167# define catomic_compare_and_exchange_bool_rel(mem, newval, oldval) \
168 atomic_compare_and_exchange_bool_rel (mem, newval, oldval)
169# endif
76a50749
UD
170#endif
171
172
bea0ac1d
JJ
173#ifndef atomic_compare_and_exchange_bool_rel
174# define atomic_compare_and_exchange_bool_rel(mem, newval, oldval) \
175 atomic_compare_and_exchange_bool_acq (mem, newval, oldval)
11bf311e
UD
176#endif
177
178
5132931e 179/* Store NEWVALUE in *MEM and return the old value. */
949ec764
UD
180#ifndef atomic_exchange_acq
181# define atomic_exchange_acq(mem, newvalue) \
11bf311e
UD
182 ({ __typeof (*(mem)) __atg5_oldval; \
183 __typeof (mem) __atg5_memp = (mem); \
184 __typeof (*(mem)) __atg5_value = (newvalue); \
5132931e
UD
185 \
186 do \
11bf311e
UD
187 __atg5_oldval = *__atg5_memp; \
188 while (__builtin_expect \
189 (atomic_compare_and_exchange_bool_acq (__atg5_memp, __atg5_value, \
190 __atg5_oldval), 0)); \
5132931e 191 \
11bf311e 192 __atg5_oldval; })
5132931e
UD
193#endif
194
949ec764
UD
195#ifndef atomic_exchange_rel
196# define atomic_exchange_rel(mem, newvalue) atomic_exchange_acq (mem, newvalue)
197#endif
198
5132931e
UD
199
200/* Add VALUE to *MEM and return the old value of *MEM. */
51a9ba86
MK
201#ifndef atomic_exchange_and_add_acq
202# ifdef atomic_exchange_and_add
203# define atomic_exchange_and_add_acq(mem, value) \
204 atomic_exchange_and_add (mem, value)
205# else
206# define atomic_exchange_and_add_acq(mem, value) \
11bf311e
UD
207 ({ __typeof (*(mem)) __atg6_oldval; \
208 __typeof (mem) __atg6_memp = (mem); \
209 __typeof (*(mem)) __atg6_value = (value); \
76a50749
UD
210 \
211 do \
11bf311e
UD
212 __atg6_oldval = *__atg6_memp; \
213 while (__builtin_expect \
214 (atomic_compare_and_exchange_bool_acq (__atg6_memp, \
215 __atg6_oldval \
216 + __atg6_value, \
217 __atg6_oldval), 0)); \
76a50749 218 \
11bf311e 219 __atg6_oldval; })
51a9ba86 220# endif
76a50749
UD
221#endif
222
51a9ba86
MK
223#ifndef atomic_exchange_and_add_rel
224# define atomic_exchange_and_add_rel(mem, value) \
225 atomic_exchange_and_add_acq(mem, value)
226#endif
227
228#ifndef atomic_exchange_and_add
229# define atomic_exchange_and_add(mem, value) \
230 atomic_exchange_and_add_acq(mem, value)
231#endif
76a50749 232
11bf311e
UD
233#ifndef catomic_exchange_and_add
234# define catomic_exchange_and_add(mem, value) \
235 ({ __typeof (*(mem)) __atg7_oldv; \
236 __typeof (mem) __atg7_memp = (mem); \
237 __typeof (*(mem)) __atg7_value = (value); \
238 \
239 do \
240 __atg7_oldv = *__atg7_memp; \
241 while (__builtin_expect \
242 (catomic_compare_and_exchange_bool_acq (__atg7_memp, \
243 __atg7_oldv \
244 + __atg7_value, \
245 __atg7_oldv), 0)); \
246 \
247 __atg7_oldv; })
248#endif
249
d6c7294e
UD
250
251#ifndef atomic_max
252# define atomic_max(mem, value) \
253 do { \
11bf311e
UD
254 __typeof (*(mem)) __atg8_oldval; \
255 __typeof (mem) __atg8_memp = (mem); \
256 __typeof (*(mem)) __atg8_value = (value); \
257 do { \
258 __atg8_oldval = *__atg8_memp; \
259 if (__atg8_oldval >= __atg8_value) \
260 break; \
261 } while (__builtin_expect \
262 (atomic_compare_and_exchange_bool_acq (__atg8_memp, __atg8_value,\
263 __atg8_oldval), 0)); \
264 } while (0)
265#endif
266
267
268#ifndef catomic_max
269# define catomic_max(mem, value) \
270 do { \
271 __typeof (*(mem)) __atg9_oldv; \
272 __typeof (mem) __atg9_memp = (mem); \
273 __typeof (*(mem)) __atg9_value = (value); \
8099361e 274 do { \
11bf311e
UD
275 __atg9_oldv = *__atg9_memp; \
276 if (__atg9_oldv >= __atg9_value) \
8099361e 277 break; \
11bf311e
UD
278 } while (__builtin_expect \
279 (catomic_compare_and_exchange_bool_acq (__atg9_memp, \
280 __atg9_value, \
281 __atg9_oldv), 0)); \
8099361e
UD
282 } while (0)
283#endif
284
11bf311e 285
d6c7294e
UD
286#ifndef atomic_min
287# define atomic_min(mem, value) \
288 do { \
11bf311e
UD
289 __typeof (*(mem)) __atg10_oldval; \
290 __typeof (mem) __atg10_memp = (mem); \
291 __typeof (*(mem)) __atg10_value = (value); \
d6c7294e 292 do { \
11bf311e
UD
293 __atg10_oldval = *__atg10_memp; \
294 if (__atg10_oldval <= __atg10_value) \
d6c7294e 295 break; \
11bf311e
UD
296 } while (__builtin_expect \
297 (atomic_compare_and_exchange_bool_acq (__atg10_memp, \
298 __atg10_value, \
299 __atg10_oldval), 0)); \
d6c7294e
UD
300 } while (0)
301#endif
302
11bf311e 303
76a50749 304#ifndef atomic_add
fe4610b3 305# define atomic_add(mem, value) (void) atomic_exchange_and_add ((mem), (value))
76a50749
UD
306#endif
307
308
11bf311e
UD
309#ifndef catomic_add
310# define catomic_add(mem, value) \
311 (void) catomic_exchange_and_add ((mem), (value))
312#endif
313
314
76a50749 315#ifndef atomic_increment
fe4610b3 316# define atomic_increment(mem) atomic_add ((mem), 1)
76a50749
UD
317#endif
318
319
11bf311e
UD
320#ifndef catomic_increment
321# define catomic_increment(mem) catomic_add ((mem), 1)
322#endif
323
324
f377d022
UD
325#ifndef atomic_increment_val
326# define atomic_increment_val(mem) (atomic_exchange_and_add ((mem), 1) + 1)
327#endif
328
329
11bf311e
UD
330#ifndef catomic_increment_val
331# define catomic_increment_val(mem) (catomic_exchange_and_add ((mem), 1) + 1)
332#endif
333
334
fe4610b3 335/* Add one to *MEM and return true iff it's now zero. */
ec609a8e
UD
336#ifndef atomic_increment_and_test
337# define atomic_increment_and_test(mem) \
fe4610b3 338 (atomic_exchange_and_add ((mem), 1) + 1 == 0)
ec609a8e
UD
339#endif
340
341
76a50749 342#ifndef atomic_decrement
fe4610b3 343# define atomic_decrement(mem) atomic_add ((mem), -1)
76a50749
UD
344#endif
345
346
11bf311e
UD
347#ifndef catomic_decrement
348# define catomic_decrement(mem) catomic_add ((mem), -1)
349#endif
350
351
f377d022
UD
352#ifndef atomic_decrement_val
353# define atomic_decrement_val(mem) (atomic_exchange_and_add ((mem), -1) - 1)
354#endif
355
356
11bf311e
UD
357#ifndef catomic_decrement_val
358# define catomic_decrement_val(mem) (catomic_exchange_and_add ((mem), -1) - 1)
359#endif
360
361
d15851ec 362/* Subtract 1 from *MEM and return true iff it's now zero. */
ec609a8e
UD
363#ifndef atomic_decrement_and_test
364# define atomic_decrement_and_test(mem) \
fe4610b3 365 (atomic_exchange_and_add ((mem), -1) == 1)
ec609a8e
UD
366#endif
367
368
5132931e 369/* Decrement *MEM if it is > 0, and return the old value. */
2ff16e04 370#ifndef atomic_decrement_if_positive
972209dd 371# define atomic_decrement_if_positive(mem) \
11bf311e
UD
372 ({ __typeof (*(mem)) __atg11_oldval; \
373 __typeof (mem) __atg11_memp = (mem); \
972209dd 374 \
5132931e
UD
375 do \
376 { \
11bf311e 377 __atg11_oldval = *__atg11_memp; \
a1ffb40e 378 if (__glibc_unlikely (__atg11_oldval <= 0)) \
5132931e 379 break; \
5132931e 380 } \
11bf311e
UD
381 while (__builtin_expect \
382 (atomic_compare_and_exchange_bool_acq (__atg11_memp, \
383 __atg11_oldval - 1, \
384 __atg11_oldval), 0)); \
385 __atg11_oldval; })
5132931e
UD
386#endif
387
388
5cd09cd6 389#ifndef atomic_add_negative
859e708f 390# define atomic_add_negative(mem, value) \
11bf311e
UD
391 ({ __typeof (value) __atg12_value = (value); \
392 atomic_exchange_and_add (mem, __atg12_value) < -__atg12_value; })
ec609a8e
UD
393#endif
394
395
396#ifndef atomic_add_zero
859e708f 397# define atomic_add_zero(mem, value) \
11bf311e
UD
398 ({ __typeof (value) __atg13_value = (value); \
399 atomic_exchange_and_add (mem, __atg13_value) == -__atg13_value; })
ec609a8e
UD
400#endif
401
402
0289bef9
UD
403#ifndef atomic_bit_set
404# define atomic_bit_set(mem, bit) \
a1b5424f 405 (void) atomic_bit_test_set(mem, bit)
ec609a8e
UD
406#endif
407
408
409#ifndef atomic_bit_test_set
410# define atomic_bit_test_set(mem, bit) \
11bf311e
UD
411 ({ __typeof (*(mem)) __atg14_old; \
412 __typeof (mem) __atg14_memp = (mem); \
413 __typeof (*(mem)) __atg14_mask = ((__typeof (*(mem))) 1 << (bit)); \
ec609a8e
UD
414 \
415 do \
11bf311e
UD
416 __atg14_old = (*__atg14_memp); \
417 while (__builtin_expect \
418 (atomic_compare_and_exchange_bool_acq (__atg14_memp, \
419 __atg14_old | __atg14_mask,\
420 __atg14_old), 0)); \
76a50749 421 \
11bf311e 422 __atg14_old & __atg14_mask; })
76a50749
UD
423#endif
424
11bf311e 425/* Atomically *mem &= mask. */
f1740bc4
UD
426#ifndef atomic_and
427# define atomic_and(mem, mask) \
11bf311e
UD
428 do { \
429 __typeof (*(mem)) __atg15_old; \
430 __typeof (mem) __atg15_memp = (mem); \
431 __typeof (*(mem)) __atg15_mask = (mask); \
432 \
433 do \
434 __atg15_old = (*__atg15_memp); \
435 while (__builtin_expect \
436 (atomic_compare_and_exchange_bool_acq (__atg15_memp, \
437 __atg15_old & __atg15_mask, \
438 __atg15_old), 0)); \
439 } while (0)
440#endif
441
6c03cd11
UD
442#ifndef catomic_and
443# define catomic_and(mem, mask) \
444 do { \
445 __typeof (*(mem)) __atg20_old; \
446 __typeof (mem) __atg20_memp = (mem); \
447 __typeof (*(mem)) __atg20_mask = (mask); \
448 \
449 do \
450 __atg20_old = (*__atg20_memp); \
451 while (__builtin_expect \
452 (catomic_compare_and_exchange_bool_acq (__atg20_memp, \
453 __atg20_old & __atg20_mask,\
454 __atg20_old), 0)); \
455 } while (0)
456#endif
457
11bf311e
UD
458/* Atomically *mem &= mask and return the old value of *mem. */
459#ifndef atomic_and_val
460# define atomic_and_val(mem, mask) \
461 ({ __typeof (*(mem)) __atg16_old; \
462 __typeof (mem) __atg16_memp = (mem); \
463 __typeof (*(mem)) __atg16_mask = (mask); \
f1740bc4
UD
464 \
465 do \
11bf311e
UD
466 __atg16_old = (*__atg16_memp); \
467 while (__builtin_expect \
468 (atomic_compare_and_exchange_bool_acq (__atg16_memp, \
469 __atg16_old & __atg16_mask,\
470 __atg16_old), 0)); \
f1740bc4 471 \
11bf311e 472 __atg16_old; })
f1740bc4
UD
473#endif
474
475/* Atomically *mem |= mask and return the old value of *mem. */
476#ifndef atomic_or
477# define atomic_or(mem, mask) \
11bf311e
UD
478 do { \
479 __typeof (*(mem)) __atg17_old; \
480 __typeof (mem) __atg17_memp = (mem); \
481 __typeof (*(mem)) __atg17_mask = (mask); \
482 \
483 do \
484 __atg17_old = (*__atg17_memp); \
485 while (__builtin_expect \
486 (atomic_compare_and_exchange_bool_acq (__atg17_memp, \
487 __atg17_old | __atg17_mask, \
488 __atg17_old), 0)); \
489 } while (0)
490#endif
491
492#ifndef catomic_or
493# define catomic_or(mem, mask) \
494 do { \
495 __typeof (*(mem)) __atg18_old; \
496 __typeof (mem) __atg18_memp = (mem); \
497 __typeof (*(mem)) __atg18_mask = (mask); \
498 \
499 do \
500 __atg18_old = (*__atg18_memp); \
501 while (__builtin_expect \
502 (catomic_compare_and_exchange_bool_acq (__atg18_memp, \
503 __atg18_old | __atg18_mask,\
504 __atg18_old), 0)); \
505 } while (0)
506#endif
507
508/* Atomically *mem |= mask and return the old value of *mem. */
509#ifndef atomic_or_val
510# define atomic_or_val(mem, mask) \
511 ({ __typeof (*(mem)) __atg19_old; \
512 __typeof (mem) __atg19_memp = (mem); \
513 __typeof (*(mem)) __atg19_mask = (mask); \
f1740bc4
UD
514 \
515 do \
11bf311e
UD
516 __atg19_old = (*__atg19_memp); \
517 while (__builtin_expect \
518 (atomic_compare_and_exchange_bool_acq (__atg19_memp, \
519 __atg19_old | __atg19_mask,\
520 __atg19_old), 0)); \
f1740bc4 521 \
11bf311e 522 __atg19_old; })
f1740bc4 523#endif
76a50749
UD
524
525#ifndef atomic_full_barrier
733f25e6 526# define atomic_full_barrier() __asm ("" ::: "memory")
76a50749
UD
527#endif
528
529
530#ifndef atomic_read_barrier
a1b5424f 531# define atomic_read_barrier() atomic_full_barrier ()
76a50749
UD
532#endif
533
534
535#ifndef atomic_write_barrier
a1b5424f 536# define atomic_write_barrier() atomic_full_barrier ()
76a50749
UD
537#endif
538
f377d022 539
fc242bef
UD
540#ifndef atomic_forced_read
541# define atomic_forced_read(x) \
542 ({ __typeof (x) __x; __asm ("" : "=r" (__x) : "0" (x)); __x; })
543#endif
544
545
f377d022
UD
546#ifndef atomic_delay
547# define atomic_delay() do { /* nothing */ } while (0)
548#endif
549
76a50749 550#endif /* atomic.h */
This page took 0.323486 seconds and 5 git commands to generate.