]>
Commit | Line | Data |
---|---|---|
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 | |
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 | ||
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 | }) |