2003-03-22 Roland McGrath <roland@redhat.com>
[kopensolaris-gnu/glibc.git] / include / atomic.h
1 /* Internal macros for atomic operations for GNU C Library.
2    Copyright (C) 2002, 2003 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
29 /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
30    Return the old *MEM value.  */
31 #if !defined atomic_compare_and_exchange_val_acq \
32     && defined __arch_compare_and_exchange_val_32_acq
33 # define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
34   ({ __typeof (*mem) __result;                                                \
35      if (sizeof (*mem) == 1)                                                  \
36        __result = __arch_compare_and_exchange_val_8_acq (mem, newval, oldval);\
37      else if (sizeof (*mem) == 2)                                             \
38        __result = __arch_compare_and_exchange_val_16_acq (mem, newval,oldval);\
39      else if (sizeof (*mem) == 4)                                             \
40        __result = __arch_compare_and_exchange_val_32_acq (mem, newval,oldval);\
41      else if (sizeof (*mem) == 8)                                             \
42        __result = __arch_compare_and_exchange_val_64_acq (mem, newval,oldval);\
43      else                                                                     \
44        abort ();                                                              \
45      __result; })
46 #endif
47
48
49 #ifndef atomic_compare_and_exchange_val_rel
50 # define atomic_compare_and_exchange_val_rel(mem, oldval, newval) \
51   atomic_compare_and_exchange_val_acq (mem, oldval, newval)
52 #endif
53
54
55 /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
56    Return zero if *MEM was changed or non-zero if no exchange happened.  */
57 #ifndef atomic_compare_and_exchange_bool_acq
58 # ifdef __arch_compare_and_exchange_bool_32_acq
59 #  define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
60   ({ __typeof (__arch_compare_and_exchange_bool_32_acq (mem, 0, 0)) __result; \
61      if (sizeof (*mem) == 1)                                                  \
62        __result = __arch_compare_and_exchange_bool_8_acq (mem, newval,        \
63                                                           oldval);            \
64      else if (sizeof (*mem) == 2)                                             \
65        __result = __arch_compare_and_exchange_bool_16_acq (mem, newval,       \
66                                                            oldval);           \
67      else if (sizeof (*mem) == 4)                                             \
68        __result = __arch_compare_and_exchange_bool_32_acq (mem, newval,       \
69                                                            oldval);           \
70      else if (sizeof (*mem) == 8)                                             \
71        __result = __arch_compare_and_exchange_bool_64_acq (mem, newval,       \
72                                                            oldval);           \
73      else                                                                     \
74        abort ();                                                              \
75      __result; })
76 # else
77 #  define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
78   ({ /* Cannot use __oldval here, because macros later in this file might     \
79         call this macro with __oldval argument.  */                           \
80      __typeof (oldval) __old = (oldval);                                      \
81      atomic_compare_and_exchange_val_acq (mem, newval, __old) != __old;       \
82   })
83 # endif
84 #endif
85
86
87 #ifndef atomic_compare_and_exchange_bool_rel
88 # define atomic_compare_and_exchange_bool_rel(mem, oldval, newval) \
89   atomic_compare_and_exchange_bool_acq (mem, oldval, newval)
90 #endif
91
92
93 /* Store NEWVALUE in *MEM and return the old value.  */
94 #ifndef atomic_exchange
95 # define atomic_exchange(mem, newvalue) \
96   ({ __typeof (*mem) __oldval;                                                \
97      __typeof (mem) __memp = (mem);                                           \
98      __typeof (*mem) __value = (newvalue);                                    \
99                                                                               \
100      do                                                                       \
101        __oldval = (*__memp);                                                  \
102      while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp,   \
103                                                                     __value,  \
104                                                                     __oldval),\
105                               0));                                            \
106                                                                               \
107      __oldval; })
108 #endif
109
110
111 /* Add VALUE to *MEM and return the old value of *MEM.  */
112 #ifndef atomic_exchange_and_add
113 # define atomic_exchange_and_add(mem, value) \
114   ({ __typeof (*mem) __oldval;                                                \
115      __typeof (mem) __memp = (mem);                                           \
116      __typeof (*mem) __value = (value);                                       \
117                                                                               \
118      do                                                                       \
119        __oldval = (*__memp);                                                  \
120      while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp,   \
121                                                                     __oldval  \
122                                                                     + __value,\
123                                                                     __oldval),\
124                               0));                                            \
125                                                                               \
126      __oldval; })
127 #endif
128
129
130 #ifndef atomic_add
131 # define atomic_add(mem, value) (void) atomic_exchange_and_add (mem, value)
132 #endif
133
134
135 #ifndef atomic_increment
136 # define atomic_increment(mem) atomic_add (mem, 1)
137 #endif
138
139
140 /* Add one to *MEM and return true iff it's now nonzero.  */
141 #ifndef atomic_increment_and_test
142 # define atomic_increment_and_test(mem) \
143   (atomic_exchange_and_add (mem, 1) != 0)
144 #endif
145
146
147 #ifndef atomic_decrement
148 # define atomic_decrement(mem) atomic_add (mem, -1)
149 #endif
150
151
152 /* Subtract 1 from *MEM and return true iff it's now zero.  */
153 #ifndef atomic_decrement_and_test
154 # define atomic_decrement_and_test(mem) \
155   (atomic_exchange_and_add (mem, -1) == 0)
156 #endif
157
158
159 /* Decrement *MEM if it is > 0, and return the old value.  */
160 #ifndef atomic_decrement_if_positive
161 # define atomic_decrement_if_positive(mem) \
162   ({ __typeof (*mem) __oldval;                                                \
163      __typeof (mem) __memp = (mem);                                           \
164                                                                               \
165      do                                                                       \
166        {                                                                      \
167          __oldval = *__memp;                                                  \
168          if (__builtin_expect (__oldval <= 0, 0))                             \
169            break;                                                             \
170        }                                                                      \
171      while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp,   \
172                                                                     __oldval  \
173                                                                     - 1,      \
174                                                                     __oldval),\
175                               0));\
176      __oldval; })
177 #endif
178
179
180 #ifndef atomic_add_negative
181 # define atomic_add_negative(mem, value) \
182   (atomic_exchange_and_add (mem, value) < 0)
183 #endif
184
185
186 #ifndef atomic_add_zero
187 # define atomic_add_zero(mem, value) \
188   (atomic_exchange_and_add (mem, value) == 0)
189 #endif
190
191
192 #ifndef atomic_bit_set
193 # define atomic_bit_set(mem, bit) \
194   (void) atomic_bit_test_set(mem, bit)
195 #endif
196
197
198 #ifndef atomic_bit_test_set
199 # define atomic_bit_test_set(mem, bit) \
200   ({ __typeof (*mem) __oldval;                                                \
201      __typeof (mem) __memp = (mem);                                           \
202      __typeof (*mem) __mask = ((__typeof (*mem)) 1 << (bit));                 \
203                                                                               \
204      do                                                                       \
205        __oldval = (*__memp);                                                  \
206      while (__builtin_expect (atomic_compare_and_exchange_bool_acq (__memp,   \
207                                                                     __oldval  \
208                                                                     | __mask, \
209                                                                     __oldval),\
210                               0));                                            \
211                                                                               \
212      __oldval & __mask; })
213 #endif
214
215
216 #ifndef atomic_full_barrier
217 # define atomic_full_barrier() __asm ("" ::: "memory")
218 #endif
219
220
221 #ifndef atomic_read_barrier
222 # define atomic_read_barrier() atomic_full_barrier()
223 #endif
224
225
226 #ifndef atomic_write_barrier
227 # define atomic_write_barrier() atomic_full_barrier()
228 #endif
229
230 #endif  /* atomic.h */