]> git.ipfire.org Git - thirdparty/glibc.git/blob - include/atomic.h
2.5-18.1
[thirdparty/glibc.git] / include / atomic.h
1 /* Internal macros for atomic operations for GNU C Library.
2 Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
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
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
20
21 #ifndef _ATOMIC_H
22 #define _ATOMIC_H 1
23
24 #include <stdlib.h>
25
26 #include <bits/atomic.h>
27
28 /* Wrapper macros to call pre_NN_post (mem, ...) where NN is the
29 bit width of *MEM. The calling macro puts parens around MEM
30 and following args. */
31 #define __atomic_val_bysize(pre, post, mem, ...) \
32 ({ \
33 __typeof (*mem) __result; \
34 if (sizeof (*mem) == 1) \
35 __result = pre##_8_##post (mem, __VA_ARGS__); \
36 else if (sizeof (*mem) == 2) \
37 __result = pre##_16_##post (mem, __VA_ARGS__); \
38 else if (sizeof (*mem) == 4) \
39 __result = pre##_32_##post (mem, __VA_ARGS__); \
40 else if (sizeof (*mem) == 8) \
41 __result = pre##_64_##post (mem, __VA_ARGS__); \
42 else \
43 abort (); \
44 __result; \
45 })
46 #define __atomic_bool_bysize(pre, post, mem, ...) \
47 ({ \
48 int __result; \
49 if (sizeof (*mem) == 1) \
50 __result = pre##_8_##post (mem, __VA_ARGS__); \
51 else if (sizeof (*mem) == 2) \
52 __result = pre##_16_##post (mem, __VA_ARGS__); \
53 else if (sizeof (*mem) == 4) \
54 __result = pre##_32_##post (mem, __VA_ARGS__); \
55 else if (sizeof (*mem) == 8) \
56 __result = pre##_64_##post (mem, __VA_ARGS__); \
57 else \
58 abort (); \
59 __result; \
60 })
61
62
63 /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
64 Return the old *MEM value. */
65 #if !defined atomic_compare_and_exchange_val_acq \
66 && defined __arch_compare_and_exchange_val_32_acq
67 # define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
68 __atomic_val_bysize (__arch_compare_and_exchange_val,acq, \
69 mem, newval, oldval)
70 #endif
71
72
73 #ifndef atomic_compare_and_exchange_val_rel
74 # define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
75 atomic_compare_and_exchange_val_acq (mem, newval, oldval)
76 #endif
77
78
79 /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
80 Return zero if *MEM was changed or non-zero if no exchange happened. */
81 #ifndef atomic_compare_and_exchange_bool_acq
82 # ifdef __arch_compare_and_exchange_bool_32_acq
83 # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
84 __atomic_bool_bysize (__arch_compare_and_exchange_bool,acq, \
85 mem, newval, oldval)
86 # else
87 # define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
88 ({ /* Cannot use __oldval here, because macros later in this file might \
89 call this macro with __oldval argument. */ \
90 __typeof (oldval) __old = (oldval); \
91 atomic_compare_and_exchange_val_acq (mem, newval, __old) != __old; \
92 })
93 # endif
94 #endif
95
96
97 #ifndef atomic_compare_and_exchange_bool_rel
98 # define atomic_compare_and_exchange_bool_rel(mem, newval, oldval) \
99 atomic_compare_and_exchange_bool_acq (mem, newval, oldval)
100 #endif
101
102
103 /* Store NEWVALUE in *MEM and return the old value. */
104 #ifndef atomic_exchange_acq
105 # define atomic_exchange_acq(mem, newvalue) \
106 ({ __typeof (*(mem)) __oldval; \
107 __typeof (mem) __memp = (mem); \
108 __typeof (*(mem)) __value = (newvalue); \
109 \
110 do \
111 __oldval = *__memp; \
112 while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
113 __value, \
114 __oldval),\
115 0)); \
116 \
117 __oldval; })
118 #endif
119
120 #ifndef atomic_exchange_rel
121 # define atomic_exchange_rel(mem, newvalue) atomic_exchange_acq (mem, newvalue)
122 #endif
123
124
125 /* Add VALUE to *MEM and return the old value of *MEM. */
126 #ifndef atomic_exchange_and_add
127 # define atomic_exchange_and_add(mem, value) \
128 ({ __typeof (*(mem)) __oldval; \
129 __typeof (mem) __memp = (mem); \
130 __typeof (*(mem)) __value = (value); \
131 \
132 do \
133 __oldval = *__memp; \
134 while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
135 __oldval \
136 + __value,\
137 __oldval),\
138 0)); \
139 \
140 __oldval; })
141 #endif
142
143
144
145 #ifndef atomic_max
146 # define atomic_max(mem, value) \
147 do { \
148 __typeof (*(mem)) __oldval; \
149 __typeof (mem) __memp = (mem); \
150 __typeof (*(mem)) __value = (value); \
151 do { \
152 __oldval = *__memp; \
153 if (__oldval >= __value) \
154 break; \
155 } while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
156 __value, \
157 __oldval),\
158 0)); \
159 } while (0)
160 #endif
161
162 #ifndef atomic_min
163 # define atomic_min(mem, value) \
164 do { \
165 __typeof (*(mem)) __oldval; \
166 __typeof (mem) __memp = (mem); \
167 __typeof (*(mem)) __value = (value); \
168 do { \
169 __oldval = *__memp; \
170 if (__oldval <= __value) \
171 break; \
172 } while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
173 __value, \
174 __oldval),\
175 0)); \
176 } while (0)
177 #endif
178
179 #ifndef atomic_add
180 # define atomic_add(mem, value) (void) atomic_exchange_and_add ((mem), (value))
181 #endif
182
183
184 #ifndef atomic_increment
185 # define atomic_increment(mem) atomic_add ((mem), 1)
186 #endif
187
188
189 #ifndef atomic_increment_val
190 # define atomic_increment_val(mem) (atomic_exchange_and_add ((mem), 1) + 1)
191 #endif
192
193
194 /* Add one to *MEM and return true iff it's now zero. */
195 #ifndef atomic_increment_and_test
196 # define atomic_increment_and_test(mem) \
197 (atomic_exchange_and_add ((mem), 1) + 1 == 0)
198 #endif
199
200
201 #ifndef atomic_decrement
202 # define atomic_decrement(mem) atomic_add ((mem), -1)
203 #endif
204
205
206 #ifndef atomic_decrement_val
207 # define atomic_decrement_val(mem) (atomic_exchange_and_add ((mem), -1) - 1)
208 #endif
209
210
211 /* Subtract 1 from *MEM and return true iff it's now zero. */
212 #ifndef atomic_decrement_and_test
213 # define atomic_decrement_and_test(mem) \
214 (atomic_exchange_and_add ((mem), -1) == 1)
215 #endif
216
217
218 /* Decrement *MEM if it is > 0, and return the old value. */
219 #ifndef atomic_decrement_if_positive
220 # define atomic_decrement_if_positive(mem) \
221 ({ __typeof (*(mem)) __oldval; \
222 __typeof (mem) __memp = (mem); \
223 \
224 do \
225 { \
226 __oldval = *__memp; \
227 if (__builtin_expect (__oldval <= 0, 0)) \
228 break; \
229 } \
230 while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
231 __oldval \
232 - 1, \
233 __oldval),\
234 0));\
235 __oldval; })
236 #endif
237
238
239 #ifndef atomic_add_negative
240 # define atomic_add_negative(mem, value) \
241 ({ __typeof (value) __aan_value = (value); \
242 atomic_exchange_and_add (mem, __aan_value) < -__aan_value; })
243 #endif
244
245
246 #ifndef atomic_add_zero
247 # define atomic_add_zero(mem, value) \
248 ({ __typeof (value) __aaz_value = (value); \
249 atomic_exchange_and_add (mem, __aaz_value) == -__aaz_value; })
250 #endif
251
252
253 #ifndef atomic_bit_set
254 # define atomic_bit_set(mem, bit) \
255 (void) atomic_bit_test_set(mem, bit)
256 #endif
257
258
259 #ifndef atomic_bit_test_set
260 # define atomic_bit_test_set(mem, bit) \
261 ({ __typeof (*(mem)) __oldval; \
262 __typeof (mem) __memp = (mem); \
263 __typeof (*(mem)) __mask = ((__typeof (*(mem))) 1 << (bit)); \
264 \
265 do \
266 __oldval = (*__memp); \
267 while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
268 __oldval \
269 | __mask, \
270 __oldval),\
271 0)); \
272 \
273 __oldval & __mask; })
274 #endif
275
276 /* Atomically *mem &= mask and return the old value of *mem. */
277 #ifndef atomic_and
278 # define atomic_and(mem, mask) \
279 ({ __typeof (*(mem)) __oldval; \
280 __typeof (mem) __memp = (mem); \
281 __typeof (*(mem)) __mask = (mask); \
282 \
283 do \
284 __oldval = (*__memp); \
285 while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
286 __oldval \
287 & __mask, \
288 __oldval),\
289 0)); \
290 \
291 __oldval; })
292 #endif
293
294 /* Atomically *mem |= mask and return the old value of *mem. */
295 #ifndef atomic_or
296 # define atomic_or(mem, mask) \
297 ({ __typeof (*(mem)) __oldval; \
298 __typeof (mem) __memp = (mem); \
299 __typeof (*(mem)) __mask = (mask); \
300 \
301 do \
302 __oldval = (*__memp); \
303 while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp, \
304 __oldval \
305 | __mask, \
306 __oldval),\
307 0)); \
308 \
309 __oldval; })
310 #endif
311
312 #ifndef atomic_full_barrier
313 # define atomic_full_barrier() __asm ("" ::: "memory")
314 #endif
315
316
317 #ifndef atomic_read_barrier
318 # define atomic_read_barrier() atomic_full_barrier ()
319 #endif
320
321
322 #ifndef atomic_write_barrier
323 # define atomic_write_barrier() atomic_full_barrier ()
324 #endif
325
326
327 #ifndef atomic_forced_read
328 # define atomic_forced_read(x) \
329 ({ __typeof (x) __x; __asm ("" : "=r" (__x) : "0" (x)); __x; })
330 #endif
331
332
333 #ifndef atomic_delay
334 # define atomic_delay() do { /* nothing */ } while (0)
335 #endif
336
337 #endif /* atomic.h */