]>
git.ipfire.org Git - thirdparty/glibc.git/blob - nptl/sysdeps/x86_64/bits/atomic.h
1 /* Copyright (C) 2002 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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 typedef int8_t atomic8_t
;
24 typedef uint8_t uatomic8_t
;
25 typedef int_fast8_t atomic_fast8_t
;
26 typedef uint_fast8_t uatomic_fast8_t
;
28 typedef int16_t atomic16_t
;
29 typedef uint16_t uatomic16_t
;
30 typedef int_fast16_t atomic_fast16_t
;
31 typedef uint_fast16_t uatomic_fast16_t
;
33 typedef int32_t atomic32_t
;
34 typedef uint32_t uatomic32_t
;
35 typedef int_fast32_t atomic_fast32_t
;
36 typedef uint_fast32_t uatomic_fast32_t
;
38 typedef int64_t atomic64_t
;
39 typedef uint64_t uatomic64_t
;
40 typedef int_fast64_t atomic_fast64_t
;
41 typedef uint_fast64_t uatomic_fast64_t
;
43 typedef intptr_t atomicptr_t
;
44 typedef uintptr_t uatomicptr_t
;
45 typedef intmax_t atomic_max_t
;
46 typedef uintmax_t uatomic_max_t
;
51 # define LOCK /* nothing */
58 #define __arch_compare_and_exchange_8_acq(mem, newval, oldval) \
59 ({ unsigned char ret; \
60 __asm __volatile (LOCK "cmpxchgb %b2, %1; setne %0" \
61 : "=a" (ret), "=m" (*mem) \
62 : "q" (newval), "1" (*mem), "0" (oldval)); \
65 #define __arch_compare_and_exchange_16_acq(mem, newval, oldval) \
66 ({ unsigned char ret; \
67 __asm __volatile (LOCK "cmpxchgw %w2, %1; setne %0" \
68 : "=a" (ret), "=m" (*mem) \
69 : "r" (newval), "1" (*mem), "0" (oldval)); \
72 #define __arch_compare_and_exchange_32_acq(mem, newval, oldval) \
73 ({ unsigned char ret; \
74 __asm __volatile (LOCK "cmpxchgl %2, %1; setne %0" \
75 : "=a" (ret), "=m" (*mem) \
76 : "r" (newval), "1" (*mem), "0" (oldval)); \
79 #define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \
80 ({ unsigned char ret; \
81 __asm __volatile (LOCK "cmpxchgq %q2, %1; setne %0" \
82 : "=a" (ret), "=m" (*mem) \
83 : "r" (newval), "1" (*mem), "0" (oldval)); \
87 #define atomic_exchange_and_add(mem, value) \
88 ({ __typeof (*mem) result; \
89 if (sizeof (*mem) == 1) \
90 __asm __volatile (LOCK "xaddb %b0, %1" \
91 : "=r" (result), "=m" (*mem) \
92 : "0" (value), "1" (*mem)); \
93 else if (sizeof (*mem) == 2) \
94 __asm __volatile (LOCK "xaddw %w0, %1" \
95 : "=r" (result), "=m" (*mem) \
96 : "0" (value), "1" (*mem)); \
97 else if (sizeof (*mem) == 4) \
98 __asm __volatile (LOCK "xaddl %0, %1" \
99 : "=r" (result), "=m" (*mem) \
100 : "0" (value), "1" (*mem)); \
102 __asm __volatile (LOCK "xaddq %q0, %1" \
103 : "=r" (result), "=m" (*mem) \
104 : "0" (value), "1" (*mem)); \
108 #define atomic_add(mem, value) \
109 (void) ({ if (__builtin_constant_p (value) && (value) == 1) \
110 atomic_increment (mem); \
111 else if (__builtin_constant_p (value) && (value) == 1) \
112 atomic_decrement (mem); \
113 else if (sizeof (*mem) == 1) \
114 __asm __volatile (LOCK "addb %b1, %0" \
116 : "ir" (value), "0" (*mem)); \
117 else if (sizeof (*mem) == 2) \
118 __asm __volatile (LOCK "addw %w1, %0" \
120 : "ir" (value), "0" (*mem)); \
121 else if (sizeof (*mem) == 4) \
122 __asm __volatile (LOCK "addl %1, %0" \
124 : "ir" (value), "0" (*mem)); \
126 __asm __volatile (LOCK "addq %q1, %0" \
128 : "ir" (value), "0" (*mem)); \
132 #define atomic_add_negative(mem, value) \
133 ({ unsigned char __result; \
134 if (sizeof (*mem) == 1) \
135 __asm __volatile (LOCK "addb %b2, %0; sets %1" \
136 : "=m" (*mem), "=qm" (__result) \
137 : "ir" (value), "0" (*mem)); \
138 else if (sizeof (*mem) == 2) \
139 __asm __volatile (LOCK "addw %w2, %0; sets %1" \
140 : "=m" (*mem), "=qm" (__result) \
141 : "ir" (value), "0" (*mem)); \
142 else if (sizeof (*mem) == 4) \
143 __asm __volatile (LOCK "addl %2, %0; sets %1" \
144 : "=m" (*mem), "=qm" (__result) \
145 : "ir" (value), "0" (*mem)); \
147 __asm __volatile (LOCK "addq %q2, %0; sets %1" \
148 : "=m" (*mem), "=qm" (__result) \
149 : "ir" (value), "0" (*mem)); \
153 #define atomic_add_zero(mem, value) \
154 ({ unsigned char __result; \
155 if (sizeof (*mem) == 1) \
156 __asm __volatile (LOCK "addb %b2, %0; setz %1" \
157 : "=m" (*mem), "=qm" (__result) \
158 : "ir" (value), "0" (*mem)); \
159 else if (sizeof (*mem) == 2) \
160 __asm __volatile (LOCK "addw %w2, %0; setz %1" \
161 : "=m" (*mem), "=qm" (__result) \
162 : "ir" (value), "0" (*mem)); \
163 else if (sizeof (*mem) == 4) \
164 __asm __volatile (LOCK "addl %2, %0; setz %1" \
165 : "=m" (*mem), "=qm" (__result) \
166 : "ir" (value), "0" (*mem)); \
168 __asm __volatile (LOCK "addq %q2, %0; setz %1" \
169 : "=m" (*mem), "=qm" (__result) \
170 : "ir" (value), "0" (*mem)); \
174 #define atomic_increment(mem) \
175 (void) ({ if (sizeof (*mem) == 1) \
176 __asm __volatile (LOCK "incb %b0" \
179 else if (sizeof (*mem) == 2) \
180 __asm __volatile (LOCK "incw %w0" \
183 else if (sizeof (*mem) == 4) \
184 __asm __volatile (LOCK "incl %0" \
188 __asm __volatile (LOCK "incq %q0" \
194 #define atomic_increment_and_test(mem) \
195 ({ unsigned char __result; \
196 if (sizeof (*mem) == 1) \
197 __asm __volatile (LOCK "incb %b0; sete %1" \
198 : "=m" (*mem), "=qm" (__result) \
200 else if (sizeof (*mem) == 2) \
201 __asm __volatile (LOCK "incw %w0; sete %1" \
202 : "=m" (*mem), "=qm" (__result) \
204 else if (sizeof (*mem) == 4) \
205 __asm __volatile (LOCK "incl %0; sete %1" \
206 : "=m" (*mem), "=qm" (__result) \
209 __asm __volatile (LOCK "incq %q0; sete %1" \
210 : "=m" (*mem), "=qm" (__result) \
215 #define atomic_decrement(mem) \
216 (void) ({ if (sizeof (*mem) == 1) \
217 __asm __volatile (LOCK "decb %b0" \
220 else if (sizeof (*mem) == 2) \
221 __asm __volatile (LOCK "decw %w0" \
224 else if (sizeof (*mem) == 4) \
225 __asm __volatile (LOCK "decl %0" \
229 __asm __volatile (LOCK "decq %q0" \
235 #define atomic_decrement_and_test(mem) \
236 ({ unsigned char __result; \
237 if (sizeof (*mem) == 1) \
238 __asm __volatile (LOCK "decb %b0; sete %1" \
239 : "=m" (*mem), "=qm" (__result) \
241 else if (sizeof (*mem) == 2) \
242 __asm __volatile (LOCK "decw %w0; sete %1" \
243 : "=m" (*mem), "=qm" (__result) \
245 else if (sizeof (*mem) == 4) \
246 __asm __volatile (LOCK "decl %0; sete %1" \
247 : "=m" (*mem), "=qm" (__result) \
250 __asm __volatile (LOCK "decq %q0; sete %1" \
251 : "=m" (*mem), "=qm" (__result) \
256 #define atomic_bit_set(mem, bit) \
257 (void) ({ if (sizeof (*mem) == 1) \
258 __asm __volatile (LOCK "orb %b2, %0" \
260 : "0" (*mem), "i" (1 << (bit))); \
261 else if (sizeof (*mem) == 2) \
262 __asm __volatile (LOCK "orw %w2, %0" \
264 : "0" (*mem), "i" (1 << (bit))); \
265 else if (sizeof (*mem) == 4) \
266 __asm __volatile (LOCK "orl %2, %0" \
268 : "0" (*mem), "i" (1 << (bit))); \
270 __asm __volatile (LOCK "orq %q2, %0" \
272 : "0" (*mem), "i" (1 << (bit))); \
276 #define atomic_bit_test_set(mem, bit) \
277 ({ unsigned char __result; \
278 if (sizeof (*mem) == 1) \
279 __asm __volatile (LOCK "btsb %3, %1; setc %0" \
280 : "=q" (__result), "=m" (*mem) \
281 : "1" (*mem), "i" (bit)); \
282 else if (sizeof (*mem) == 2) \
283 __asm __volatile (LOCK "btsw %3, %1; setc %0" \
284 : "=q" (__result), "=m" (*mem) \
285 : "1" (*mem), "i" (bit)); \
286 else if (sizeof (*mem) == 4) \
287 __asm __volatile (LOCK "btsl %3, %1; setc %0" \
288 : "=q" (__result), "=m" (*mem) \
289 : "1" (*mem), "i" (bit)); \
291 __asm __volatile (LOCK "btsq %3, %1; setc %0" \
292 : "=q" (__result), "=m" (*mem) \
293 : "1" (*mem), "i" (bit)); \