]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/atomic.h
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / libc / sysdeps / linux / x86_64 / bits / atomic.h
1 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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    <http://www.gnu.org/licenses/>.  */
18
19 #include <stdint.h>
20
21
22 typedef int8_t atomic8_t;
23 typedef uint8_t uatomic8_t;
24 typedef int_fast8_t atomic_fast8_t;
25 typedef uint_fast8_t uatomic_fast8_t;
26
27 typedef int16_t atomic16_t;
28 typedef uint16_t uatomic16_t;
29 typedef int_fast16_t atomic_fast16_t;
30 typedef uint_fast16_t uatomic_fast16_t;
31
32 typedef int32_t atomic32_t;
33 typedef uint32_t uatomic32_t;
34 typedef int_fast32_t atomic_fast32_t;
35 typedef uint_fast32_t uatomic_fast32_t;
36
37 typedef int64_t atomic64_t;
38 typedef uint64_t uatomic64_t;
39 typedef int_fast64_t atomic_fast64_t;
40 typedef uint_fast64_t uatomic_fast64_t;
41
42 typedef intptr_t atomicptr_t;
43 typedef uintptr_t uatomicptr_t;
44 typedef intmax_t atomic_max_t;
45 typedef uintmax_t uatomic_max_t;
46
47
48 #ifndef LOCK_PREFIX
49 # ifdef UP
50 #  define LOCK_PREFIX   /* nothing */
51 # else
52 #  define LOCK_PREFIX "lock;"
53 # endif
54 #endif
55
56
57 #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
58   ({ __typeof (*mem) ret;                                                     \
59      __asm__ __volatile__ (LOCK_PREFIX "cmpxchgb %b2, %1"                     \
60                        : "=a" (ret), "=m" (*mem)                              \
61                        : "q" (newval), "m" (*mem), "0" (oldval));             \
62      ret; })
63
64 #define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
65   ({ __typeof (*mem) ret;                                                     \
66      __asm__ __volatile__ (LOCK_PREFIX "cmpxchgw %w2, %1"                     \
67                        : "=a" (ret), "=m" (*mem)                              \
68                        : "r" (newval), "m" (*mem), "0" (oldval));             \
69      ret; })
70
71 #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
72   ({ __typeof (*mem) ret;                                                     \
73      __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %1"                      \
74                        : "=a" (ret), "=m" (*mem)                              \
75                        : "r" (newval), "m" (*mem), "0" (oldval));             \
76      ret; })
77
78 #define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
79   ({ __typeof (*mem) ret;                                                     \
80      __asm__ __volatile__ (LOCK_PREFIX "cmpxchgq %q2, %1"                     \
81                        : "=a" (ret), "=m" (*mem)                              \
82                        : "r" ((long) (newval)), "m" (*mem),                   \
83                          "0" ((long) (oldval)));                              \
84      ret; })
85
86
87 /* Note that we need no lock prefix.  */
88 #define atomic_exchange_acq(mem, newvalue) \
89   ({ __typeof (*mem) result;                                                  \
90      if (sizeof (*mem) == 1)                                                  \
91        __asm__ __volatile__ ("xchgb %b0, %1"                                  \
92                          : "=r" (result), "=m" (*mem)                         \
93                          : "0" (newvalue), "m" (*mem));                       \
94      else if (sizeof (*mem) == 2)                                             \
95        __asm__ __volatile__ ("xchgw %w0, %1"                                  \
96                          : "=r" (result), "=m" (*mem)                         \
97                          : "0" (newvalue), "m" (*mem));                       \
98      else if (sizeof (*mem) == 4)                                             \
99        __asm__ __volatile__ ("xchgl %0, %1"                                   \
100                          : "=r" (result), "=m" (*mem)                         \
101                          : "0" (newvalue), "m" (*mem));                       \
102      else                                                                     \
103        __asm__ __volatile__ ("xchgq %q0, %1"                                  \
104                          : "=r" (result), "=m" (*mem)                         \
105                          : "0" ((long) (newvalue)), "m" (*mem));              \
106      result; })
107
108
109 #define atomic_exchange_and_add(mem, value) \
110   ({ __typeof (*mem) result;                                                  \
111      if (sizeof (*mem) == 1)                                                  \
112        __asm__ __volatile__ (LOCK_PREFIX "xaddb %b0, %1"                      \
113                          : "=r" (result), "=m" (*mem)                         \
114                          : "0" (value), "m" (*mem));                          \
115      else if (sizeof (*mem) == 2)                                             \
116        __asm__ __volatile__ (LOCK_PREFIX "xaddw %w0, %1"                      \
117                          : "=r" (result), "=m" (*mem)                         \
118                          : "0" (value), "m" (*mem));                          \
119      else if (sizeof (*mem) == 4)                                             \
120        __asm__ __volatile__ (LOCK_PREFIX "xaddl %0, %1"                       \
121                          : "=r" (result), "=m" (*mem)                         \
122                          : "0" (value), "m" (*mem));                          \
123      else                                                                     \
124        __asm__ __volatile__ (LOCK_PREFIX "xaddq %q0, %1"                      \
125                          : "=r" (result), "=m" (*mem)                         \
126                          : "0" ((long) (value)), "m" (*mem));                 \
127      result; })
128
129
130 #define atomic_add(mem, value) \
131   (void) ({ if (__builtin_constant_p (value) && (value) == 1)                 \
132               atomic_increment (mem);                                         \
133             else if (__builtin_constant_p (value) && (value) == 1)            \
134               atomic_decrement (mem);                                         \
135             else if (sizeof (*mem) == 1)                                      \
136               __asm__ __volatile__ (LOCK_PREFIX "addb %b1, %0"                \
137                                 : "=m" (*mem)                                 \
138                                 : "ir" (value), "m" (*mem));                  \
139             else if (sizeof (*mem) == 2)                                      \
140               __asm__ __volatile__ (LOCK_PREFIX "addw %w1, %0"                \
141                                 : "=m" (*mem)                                 \
142                                 : "ir" (value), "m" (*mem));                  \
143             else if (sizeof (*mem) == 4)                                      \
144               __asm__ __volatile__ (LOCK_PREFIX "addl %1, %0"                 \
145                                 : "=m" (*mem)                                 \
146                                 : "ir" (value), "m" (*mem));                  \
147             else                                                              \
148               __asm__ __volatile__ (LOCK_PREFIX "addq %q1, %0"                \
149                                 : "=m" (*mem)                                 \
150                                 : "ir" ((long) (value)), "m" (*mem));         \
151             })
152
153
154 #define atomic_add_negative(mem, value) \
155   ({ unsigned char __result;                                                  \
156      if (sizeof (*mem) == 1)                                                  \
157        __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; sets %1"              \
158                          : "=m" (*mem), "=qm" (__result)                      \
159                          : "ir" (value), "m" (*mem));                         \
160      else if (sizeof (*mem) == 2)                                             \
161        __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; sets %1"              \
162                          : "=m" (*mem), "=qm" (__result)                      \
163                          : "ir" (value), "m" (*mem));                         \
164      else if (sizeof (*mem) == 4)                                             \
165        __asm__ __volatile__ (LOCK_PREFIX "addl %2, %0; sets %1"               \
166                          : "=m" (*mem), "=qm" (__result)                      \
167                          : "ir" (value), "m" (*mem));                         \
168      else                                                                     \
169        __asm__ __volatile__ (LOCK_PREFIX "addq %q2, %0; sets %1"              \
170                          : "=m" (*mem), "=qm" (__result)                      \
171                          : "ir" ((long) (value)), "m" (*mem));                \
172      __result; })
173
174
175 #define atomic_add_zero(mem, value) \
176   ({ unsigned char __result;                                                  \
177      if (sizeof (*mem) == 1)                                                  \
178        __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; setz %1"              \
179                          : "=m" (*mem), "=qm" (__result)                      \
180                          : "ir" (value), "m" (*mem));                         \
181      else if (sizeof (*mem) == 2)                                             \
182        __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; setz %1"              \
183                          : "=m" (*mem), "=qm" (__result)                      \
184                          : "ir" (value), "m" (*mem));                         \
185      else if (sizeof (*mem) == 4)                                             \
186        __asm__ __volatile__ (LOCK_PREFIX "addl %2, %0; setz %1"               \
187                          : "=m" (*mem), "=qm" (__result)                      \
188                          : "ir" (value), "m" (*mem));                         \
189      else                                                                     \
190        __asm__ __volatile__ (LOCK_PREFIX "addq %q2, %0; setz %1"              \
191                          : "=m" (*mem), "=qm" (__result)                      \
192                          : "ir" ((long) (value)), "m" (*mem));                \
193      __result; })
194
195
196 #define atomic_increment(mem) \
197   (void) ({ if (sizeof (*mem) == 1)                                           \
198               __asm__ __volatile__ (LOCK_PREFIX "incb %b0"                    \
199                                 : "=m" (*mem)                                 \
200                                 : "m" (*mem));                                \
201             else if (sizeof (*mem) == 2)                                      \
202               __asm__ __volatile__ (LOCK_PREFIX "incw %w0"                    \
203                                 : "=m" (*mem)                                 \
204                                 : "m" (*mem));                                \
205             else if (sizeof (*mem) == 4)                                      \
206               __asm__ __volatile__ (LOCK_PREFIX "incl %0"                     \
207                                 : "=m" (*mem)                                 \
208                                 : "m" (*mem));                                \
209             else                                                              \
210               __asm__ __volatile__ (LOCK_PREFIX "incq %q0"                    \
211                                 : "=m" (*mem)                                 \
212                                 : "m" (*mem));                                \
213             })
214
215
216 #define atomic_increment_and_test(mem) \
217   ({ unsigned char __result;                                                  \
218      if (sizeof (*mem) == 1)                                                  \
219        __asm__ __volatile__ (LOCK_PREFIX "incb %b0; sete %1"                  \
220                          : "=m" (*mem), "=qm" (__result)                      \
221                          : "m" (*mem));                                       \
222      else if (sizeof (*mem) == 2)                                             \
223        __asm__ __volatile__ (LOCK_PREFIX "incw %w0; sete %1"                  \
224                          : "=m" (*mem), "=qm" (__result)                      \
225                          : "m" (*mem));                                       \
226      else if (sizeof (*mem) == 4)                                             \
227        __asm__ __volatile__ (LOCK_PREFIX "incl %0; sete %1"                   \
228                          : "=m" (*mem), "=qm" (__result)                      \
229                          : "m" (*mem));                                       \
230      else                                                                     \
231        __asm__ __volatile__ (LOCK_PREFIX "incq %q0; sete %1"                  \
232                          : "=m" (*mem), "=qm" (__result)                      \
233                          : "m" (*mem));                                       \
234      __result; })
235
236
237 #define atomic_decrement(mem) \
238   (void) ({ if (sizeof (*mem) == 1)                                           \
239               __asm__ __volatile__ (LOCK_PREFIX "decb %b0"                    \
240                                 : "=m" (*mem)                                 \
241                                 : "m" (*mem));                                \
242             else if (sizeof (*mem) == 2)                                      \
243               __asm__ __volatile__ (LOCK_PREFIX "decw %w0"                    \
244                                 : "=m" (*mem)                                 \
245                                 : "m" (*mem));                                \
246             else if (sizeof (*mem) == 4)                                      \
247               __asm__ __volatile__ (LOCK_PREFIX "decl %0"                     \
248                                 : "=m" (*mem)                                 \
249                                 : "m" (*mem));                                \
250             else                                                              \
251               __asm__ __volatile__ (LOCK_PREFIX "decq %q0"                    \
252                                 : "=m" (*mem)                                 \
253                                 : "m" (*mem));                                \
254             })
255
256
257 #define atomic_decrement_and_test(mem) \
258   ({ unsigned char __result;                                                  \
259      if (sizeof (*mem) == 1)                                                  \
260        __asm__ __volatile__ (LOCK_PREFIX "decb %b0; sete %1"                  \
261                          : "=m" (*mem), "=qm" (__result)                      \
262                          : "m" (*mem));                                       \
263      else if (sizeof (*mem) == 2)                                             \
264        __asm__ __volatile__ (LOCK_PREFIX "decw %w0; sete %1"                  \
265                          : "=m" (*mem), "=qm" (__result)                      \
266                          : "m" (*mem));                                       \
267      else if (sizeof (*mem) == 4)                                             \
268        __asm__ __volatile__ (LOCK_PREFIX "decl %0; sete %1"                   \
269                          : "=m" (*mem), "=qm" (__result)                      \
270                          : "m" (*mem));                                       \
271      else                                                                     \
272        __asm__ __volatile__ (LOCK_PREFIX "decq %q0; sete %1"                  \
273                          : "=m" (*mem), "=qm" (__result)                      \
274                          : "m" (*mem));                                       \
275      __result; })
276
277
278 #define atomic_bit_set(mem, bit) \
279   (void) ({ if (sizeof (*mem) == 1)                                           \
280               __asm__ __volatile__ (LOCK_PREFIX "orb %b2, %0"                 \
281                                 : "=m" (*mem)                                 \
282                                 : "m" (*mem), "ir" (1L << (bit)));            \
283             else if (sizeof (*mem) == 2)                                      \
284               __asm__ __volatile__ (LOCK_PREFIX "orw %w2, %0"                 \
285                                 : "=m" (*mem)                                 \
286                                 : "m" (*mem), "ir" (1L << (bit)));            \
287             else if (sizeof (*mem) == 4)                                      \
288               __asm__ __volatile__ (LOCK_PREFIX "orl %2, %0"                  \
289                                 : "=m" (*mem)                                 \
290                                 : "m" (*mem), "ir" (1L << (bit)));            \
291             else if (__builtin_constant_p (bit) && (bit) < 32)                \
292               __asm__ __volatile__ (LOCK_PREFIX "orq %2, %0"                  \
293                                 : "=m" (*mem)                                 \
294                                 : "m" (*mem), "i" (1L << (bit)));             \
295             else                                                              \
296               __asm__ __volatile__ (LOCK_PREFIX "orq %q2, %0"                 \
297                                 : "=m" (*mem)                                 \
298                                 : "m" (*mem), "r" (1UL << (bit)));            \
299             })
300
301
302 #define atomic_bit_test_set(mem, bit) \
303   ({ unsigned char __result;                                                  \
304      if (sizeof (*mem) == 1)                                                  \
305        __asm__ __volatile__ (LOCK_PREFIX "btsb %3, %1; setc %0"               \
306                          : "=q" (__result), "=m" (*mem)                       \
307                          : "m" (*mem), "ir" (bit));                           \
308      else if (sizeof (*mem) == 2)                                             \
309        __asm__ __volatile__ (LOCK_PREFIX "btsw %3, %1; setc %0"               \
310                          : "=q" (__result), "=m" (*mem)                       \
311                          : "m" (*mem), "ir" (bit));                           \
312      else if (sizeof (*mem) == 4)                                             \
313        __asm__ __volatile__ (LOCK_PREFIX "btsl %3, %1; setc %0"               \
314                          : "=q" (__result), "=m" (*mem)                       \
315                          : "m" (*mem), "ir" (bit));                           \
316      else                                                                     \
317        __asm__ __volatile__ (LOCK_PREFIX "btsq %3, %1; setc %0"               \
318                          : "=q" (__result), "=m" (*mem)                       \
319                          : "m" (*mem), "ir" (bit));                           \
320      __result; })
321
322
323 #define atomic_delay() __asm__ ("rep; nop")