]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/powerpc/bits/atomic.h
007-03-20 Jakub Jelinek <jakub@redhat.com>
[thirdparty/glibc.git] / sysdeps / powerpc / bits / atomic.h
CommitLineData
94c24227 1/* Atomic operations. PowerPC Common version.
ecb2b2fb 2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
f3c13160
RM
3 This file is part of the GNU C Library.
4 Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
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
94c24227 21/*
949ec764
UD
22 * Never include sysdeps/powerpc/bits/atomic.h directly.
23 * Alway use include/atomic.h which will include either
24 * sysdeps/powerpc/powerpc32/bits/atomic.h
25 * or
26 * sysdeps/powerpc/powerpc64/bits/atomic.h
94c24227
UD
27 * as appropriate and which in turn include this file.
28 */
f3c13160 29
94c24227 30#include <stdint.h>
f3c13160
RM
31
32typedef int32_t atomic32_t;
33typedef uint32_t uatomic32_t;
34typedef int_fast32_t atomic_fast32_t;
35typedef uint_fast32_t uatomic_fast32_t;
36
37typedef int64_t atomic64_t;
38typedef uint64_t uatomic64_t;
39typedef int_fast64_t atomic_fast64_t;
40typedef uint_fast64_t uatomic_fast64_t;
41
42typedef intptr_t atomicptr_t;
43typedef uintptr_t uatomicptr_t;
44typedef intmax_t atomic_max_t;
45typedef uintmax_t uatomic_max_t;
46
949ec764
UD
47/*
48 * Powerpc does not have byte and halfword forms of load and reserve and
94c24227
UD
49 * store conditional. So for powerpc we stub out the 8- and 16-bit forms.
50 */
5a3ab2fc 51#define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \
f3c13160
RM
52 (abort (), 0)
53
5a3ab2fc 54#define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \
f3c13160 55 (abort (), 0)
ecb2b2fb 56
7158eae4
UD
57#define __arch_compare_and_exchange_bool_8_rel(mem, newval, oldval) \
58 (abort (), 0)
59
60#define __arch_compare_and_exchange_bool_16_rel(mem, newval, oldval) \
61 (abort (), 0)
f3c13160
RM
62
63#ifdef UP
f79466a8
UD
64# define __ARCH_ACQ_INSTR ""
65# define __ARCH_REL_INSTR ""
f3c13160 66#else
f79466a8 67# define __ARCH_ACQ_INSTR "isync"
7158eae4
UD
68# ifndef __ARCH_REL_INSTR
69# define __ARCH_REL_INSTR "sync"
70# endif
f3c13160
RM
71#endif
72
94c24227
UD
73#define atomic_full_barrier() __asm ("sync" ::: "memory")
74#define atomic_write_barrier() __asm ("eieio" ::: "memory")
75
7158eae4
UD
76#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
77 ({ \
78 __typeof (*(mem)) __tmp; \
79 __typeof (mem) __memp = (mem); \
80 __asm __volatile ( \
81 "1: lwarx %0,0,%1\n" \
82 " cmpw %0,%2\n" \
83 " bne 2f\n" \
84 " stwcx. %3,0,%1\n" \
85 " bne- 1b\n" \
86 "2: " __ARCH_ACQ_INSTR \
87 : "=&r" (__tmp) \
88 : "b" (__memp), "r" (oldval), "r" (newval) \
89 : "cr0", "memory"); \
90 __tmp; \
91 })
f3c13160 92
7158eae4 93#define __arch_compare_and_exchange_val_32_rel(mem, newval, oldval) \
6087c485
UD
94 ({ \
95 __typeof (*(mem)) __tmp; \
96 __typeof (mem) __memp = (mem); \
97 __asm __volatile (__ARCH_REL_INSTR "\n" \
98 "1: lwarx %0,0,%1\n" \
99 " cmpw %0,%2\n" \
100 " bne 2f\n" \
101 " stwcx. %3,0,%1\n" \
102 " bne- 1b\n" \
7158eae4 103 "2: " \
6087c485
UD
104 : "=&r" (__tmp) \
105 : "b" (__memp), "r" (oldval), "r" (newval) \
106 : "cr0", "memory"); \
107 __tmp; \
108 })
109
7158eae4
UD
110#define __arch_atomic_exchange_32_acq(mem, value) \
111 ({ \
112 __typeof (*mem) __val; \
113 __asm __volatile ( \
114 "1: lwarx %0,0,%2\n" \
115 " stwcx. %3,0,%2\n" \
116 " bne- 1b\n" \
117 " " __ARCH_ACQ_INSTR \
118 : "=&r" (__val), "=m" (*mem) \
ecb2b2fb 119 : "b" (mem), "r" (value), "m" (*mem) \
7158eae4
UD
120 : "cr0", "memory"); \
121 __val; \
122 })
123
124#define __arch_atomic_exchange_32_rel(mem, value) \
3e195d93
RM
125 ({ \
126 __typeof (*mem) __val; \
127 __asm __volatile (__ARCH_REL_INSTR "\n" \
128 "1: lwarx %0,0,%2\n" \
859e708f
RM
129 " stwcx. %3,0,%2\n" \
130 " bne- 1b" \
3e195d93 131 : "=&r" (__val), "=m" (*mem) \
ecb2b2fb 132 : "b" (mem), "r" (value), "m" (*mem) \
7158eae4 133 : "cr0", "memory"); \
3e195d93
RM
134 __val; \
135 })
f79466a8 136
6087c485 137#define __arch_atomic_exchange_and_add_32(mem, value) \
3e195d93
RM
138 ({ \
139 __typeof (*mem) __val, __tmp; \
140 __asm __volatile ("1: lwarx %0,0,%3\n" \
859e708f
RM
141 " add %1,%0,%4\n" \
142 " stwcx. %1,0,%3\n" \
143 " bne- 1b" \
3e195d93 144 : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \
ecb2b2fb 145 : "b" (mem), "r" (value), "m" (*mem) \
7158eae4 146 : "cr0", "memory"); \
3e195d93
RM
147 __val; \
148 })
448163ba 149
7ba0e52c
UD
150#define __arch_atomic_increment_val_32(mem) \
151 ({ \
152 __typeof (*(mem)) __val; \
153 __asm __volatile ("1: lwarx %0,0,%2\n" \
154 " addi %0,%0,1\n" \
155 " stwcx. %0,0,%2\n" \
156 " bne- 1b" \
157 : "=&b" (__val), "=m" (*mem) \
158 : "b" (mem), "m" (*mem) \
159 : "cr0", "memory"); \
160 __val; \
161 })
162
163#define __arch_atomic_decrement_val_32(mem) \
164 ({ \
165 __typeof (*(mem)) __val; \
166 __asm __volatile ("1: lwarx %0,0,%2\n" \
167 " subi %0,%0,1\n" \
168 " stwcx. %0,0,%2\n" \
169 " bne- 1b" \
170 : "=&b" (__val), "=m" (*mem) \
171 : "b" (mem), "m" (*mem) \
172 : "cr0", "memory"); \
173 __val; \
174 })
175
6087c485 176#define __arch_atomic_decrement_if_positive_32(mem) \
3171ae99
UD
177 ({ int __val, __tmp; \
178 __asm __volatile ("1: lwarx %0,0,%3\n" \
179 " cmpwi 0,%0,0\n" \
180 " addi %1,%0,-1\n" \
181 " ble 2f\n" \
182 " stwcx. %1,0,%3\n" \
183 " bne- 1b\n" \
184 "2: " __ARCH_ACQ_INSTR \
185 : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \
ecb2b2fb 186 : "b" (mem), "m" (*mem) \
7158eae4 187 : "cr0", "memory"); \
3171ae99
UD
188 __val; \
189 })
190
6087c485
UD
191#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
192 ({ \
193 __typeof (*(mem)) __result; \
194 if (sizeof (*mem) == 4) \
195 __result = __arch_compare_and_exchange_val_32_acq(mem, newval, oldval); \
196 else if (sizeof (*mem) == 8) \
197 __result = __arch_compare_and_exchange_val_64_acq(mem, newval, oldval); \
198 else \
199 abort (); \
200 __result; \
201 })
ecb2b2fb 202
7158eae4
UD
203#define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
204 ({ \
205 __typeof (*(mem)) __result; \
206 if (sizeof (*mem) == 4) \
207 __result = __arch_compare_and_exchange_val_32_rel(mem, newval, oldval); \
208 else if (sizeof (*mem) == 8) \
209 __result = __arch_compare_and_exchange_val_64_rel(mem, newval, oldval); \
210 else \
211 abort (); \
212 __result; \
213 })
6087c485 214
949ec764 215#define atomic_exchange_acq(mem, value) \
3e195d93
RM
216 ({ \
217 __typeof (*(mem)) __result; \
218 if (sizeof (*mem) == 4) \
7158eae4
UD
219 __result = __arch_atomic_exchange_32_acq (mem, value); \
220 else if (sizeof (*mem) == 8) \
221 __result = __arch_atomic_exchange_64_acq (mem, value); \
222 else \
223 abort (); \
224 __result; \
225 })
226
227#define atomic_exchange_rel(mem, value) \
228 ({ \
229 __typeof (*(mem)) __result; \
230 if (sizeof (*mem) == 4) \
231 __result = __arch_atomic_exchange_32_rel (mem, value); \
3e195d93 232 else if (sizeof (*mem) == 8) \
7158eae4 233 __result = __arch_atomic_exchange_64_rel (mem, value); \
3e195d93
RM
234 else \
235 abort (); \
236 __result; \
237 })
f79466a8 238
6087c485 239#define atomic_exchange_and_add(mem, value) \
3e195d93
RM
240 ({ \
241 __typeof (*(mem)) __result; \
242 if (sizeof (*mem) == 4) \
6087c485 243 __result = __arch_atomic_exchange_and_add_32 (mem, value); \
3e195d93 244 else if (sizeof (*mem) == 8) \
6087c485 245 __result = __arch_atomic_exchange_and_add_64 (mem, value); \
3e195d93 246 else \
f79466a8 247 abort (); \
3e195d93 248 __result; \
f79466a8
UD
249 })
250
7ba0e52c
UD
251#define atomic_increment_val(mem) \
252 ({ \
253 __typeof (*(mem)) __result; \
254 if (sizeof (*(mem)) == 4) \
255 __result = __arch_atomic_increment_val_32 (mem); \
256 else if (sizeof (*(mem)) == 8) \
257 __result = __arch_atomic_increment_val_64 (mem); \
258 else \
259 abort (); \
260 __result; \
261 })
262
263#define atomic_increment(mem) ({ atomic_increment_val (mem); (void) 0; })
264
265#define atomic_decrement_val(mem) \
266 ({ \
267 __typeof (*(mem)) __result; \
268 if (sizeof (*(mem)) == 4) \
269 __result = __arch_atomic_decrement_val_32 (mem); \
270 else if (sizeof (*(mem)) == 8) \
271 __result = __arch_atomic_decrement_val_64 (mem); \
272 else \
273 abort (); \
274 __result; \
275 })
276
277#define atomic_decrement(mem) ({ atomic_decrement_val (mem); (void) 0; })
278
f79466a8
UD
279
280/* Decrement *MEM if it is > 0, and return the old value. */
6087c485 281#define atomic_decrement_if_positive(mem) \
448163ba 282 ({ __typeof (*(mem)) __result; \
3171ae99 283 if (sizeof (*mem) == 4) \
448163ba 284 __result = __arch_atomic_decrement_if_positive_32 (mem); \
3171ae99 285 else if (sizeof (*mem) == 8) \
448163ba
RM
286 __result = __arch_atomic_decrement_if_positive_64 (mem); \
287 else \
f79466a8 288 abort (); \
3171ae99 289 __result; \
f79466a8 290 })