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.
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.
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.
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/>. */
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;
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;
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;
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;
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;
50 # define LOCK_PREFIX /* nothing */
52 # define LOCK_PREFIX "lock;"
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)); \
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)); \
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)); \
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))); \
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)); \
103 __asm__ __volatile__ ("xchgq %q0, %1" \
104 : "=r" (result), "=m" (*mem) \
105 : "0" ((long) (newvalue)), "m" (*mem)); \
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)); \
124 __asm__ __volatile__ (LOCK_PREFIX "xaddq %q0, %1" \
125 : "=r" (result), "=m" (*mem) \
126 : "0" ((long) (value)), "m" (*mem)); \
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" \
138 : "ir" (value), "m" (*mem)); \
139 else if (sizeof (*mem) == 2) \
140 __asm__ __volatile__ (LOCK_PREFIX "addw %w1, %0" \
142 : "ir" (value), "m" (*mem)); \
143 else if (sizeof (*mem) == 4) \
144 __asm__ __volatile__ (LOCK_PREFIX "addl %1, %0" \
146 : "ir" (value), "m" (*mem)); \
148 __asm__ __volatile__ (LOCK_PREFIX "addq %q1, %0" \
150 : "ir" ((long) (value)), "m" (*mem)); \
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)); \
169 __asm__ __volatile__ (LOCK_PREFIX "addq %q2, %0; sets %1" \
170 : "=m" (*mem), "=qm" (__result) \
171 : "ir" ((long) (value)), "m" (*mem)); \
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)); \
190 __asm__ __volatile__ (LOCK_PREFIX "addq %q2, %0; setz %1" \
191 : "=m" (*mem), "=qm" (__result) \
192 : "ir" ((long) (value)), "m" (*mem)); \
196 #define atomic_increment(mem) \
197 (void) ({ if (sizeof (*mem) == 1) \
198 __asm__ __volatile__ (LOCK_PREFIX "incb %b0" \
201 else if (sizeof (*mem) == 2) \
202 __asm__ __volatile__ (LOCK_PREFIX "incw %w0" \
205 else if (sizeof (*mem) == 4) \
206 __asm__ __volatile__ (LOCK_PREFIX "incl %0" \
210 __asm__ __volatile__ (LOCK_PREFIX "incq %q0" \
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) \
222 else if (sizeof (*mem) == 2) \
223 __asm__ __volatile__ (LOCK_PREFIX "incw %w0; sete %1" \
224 : "=m" (*mem), "=qm" (__result) \
226 else if (sizeof (*mem) == 4) \
227 __asm__ __volatile__ (LOCK_PREFIX "incl %0; sete %1" \
228 : "=m" (*mem), "=qm" (__result) \
231 __asm__ __volatile__ (LOCK_PREFIX "incq %q0; sete %1" \
232 : "=m" (*mem), "=qm" (__result) \
237 #define atomic_decrement(mem) \
238 (void) ({ if (sizeof (*mem) == 1) \
239 __asm__ __volatile__ (LOCK_PREFIX "decb %b0" \
242 else if (sizeof (*mem) == 2) \
243 __asm__ __volatile__ (LOCK_PREFIX "decw %w0" \
246 else if (sizeof (*mem) == 4) \
247 __asm__ __volatile__ (LOCK_PREFIX "decl %0" \
251 __asm__ __volatile__ (LOCK_PREFIX "decq %q0" \
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) \
263 else if (sizeof (*mem) == 2) \
264 __asm__ __volatile__ (LOCK_PREFIX "decw %w0; sete %1" \
265 : "=m" (*mem), "=qm" (__result) \
267 else if (sizeof (*mem) == 4) \
268 __asm__ __volatile__ (LOCK_PREFIX "decl %0; sete %1" \
269 : "=m" (*mem), "=qm" (__result) \
272 __asm__ __volatile__ (LOCK_PREFIX "decq %q0; sete %1" \
273 : "=m" (*mem), "=qm" (__result) \
278 #define atomic_bit_set(mem, bit) \
279 (void) ({ if (sizeof (*mem) == 1) \
280 __asm__ __volatile__ (LOCK_PREFIX "orb %b2, %0" \
282 : "m" (*mem), "ir" (1L << (bit))); \
283 else if (sizeof (*mem) == 2) \
284 __asm__ __volatile__ (LOCK_PREFIX "orw %w2, %0" \
286 : "m" (*mem), "ir" (1L << (bit))); \
287 else if (sizeof (*mem) == 4) \
288 __asm__ __volatile__ (LOCK_PREFIX "orl %2, %0" \
290 : "m" (*mem), "ir" (1L << (bit))); \
291 else if (__builtin_constant_p (bit) && (bit) < 32) \
292 __asm__ __volatile__ (LOCK_PREFIX "orq %2, %0" \
294 : "m" (*mem), "i" (1L << (bit))); \
296 __asm__ __volatile__ (LOCK_PREFIX "orq %q2, %0" \
298 : "m" (*mem), "r" (1UL << (bit))); \
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)); \
317 __asm__ __volatile__ (LOCK_PREFIX "btsq %3, %1; setc %0" \
318 : "=q" (__result), "=m" (*mem) \
319 : "m" (*mem), "ir" (bit)); \
323 #define atomic_delay() __asm__ ("rep; nop")