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