Warning: This file is not a C or C++ file. It does not have highlighting.
1 | /* Atomic operations. PowerPC Common version. |
---|---|
2 | Copyright (C) 2003-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
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 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | /* |
20 | * Never include sysdeps/powerpc/atomic-machine.h directly. |
21 | * Alway use include/atomic.h which will include either |
22 | * sysdeps/powerpc/powerpc32/atomic-machine.h |
23 | * or |
24 | * sysdeps/powerpc/powerpc64/atomic-machine.h |
25 | * as appropriate and which in turn include this file. |
26 | */ |
27 | |
28 | /* |
29 | * Powerpc does not have byte and halfword forms of load and reserve and |
30 | * store conditional. So for powerpc we stub out the 8- and 16-bit forms. |
31 | */ |
32 | #define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \ |
33 | (abort (), 0) |
34 | |
35 | #define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \ |
36 | (abort (), 0) |
37 | |
38 | #define __ARCH_ACQ_INSTR "isync" |
39 | #ifndef __ARCH_REL_INSTR |
40 | # define __ARCH_REL_INSTR "sync" |
41 | #endif |
42 | |
43 | #ifndef MUTEX_HINT_ACQ |
44 | # define MUTEX_HINT_ACQ |
45 | #endif |
46 | #ifndef MUTEX_HINT_REL |
47 | # define MUTEX_HINT_REL |
48 | #endif |
49 | |
50 | #define atomic_full_barrier() __asm ("sync" ::: "memory") |
51 | |
52 | #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ |
53 | ({ \ |
54 | __typeof (*(mem)) __tmp; \ |
55 | __typeof (mem) __memp = (mem); \ |
56 | __asm __volatile ( \ |
57 | "1: lwarx %0,0,%1" MUTEX_HINT_ACQ "\n" \ |
58 | " cmpw %0,%2\n" \ |
59 | " bne 2f\n" \ |
60 | " stwcx. %3,0,%1\n" \ |
61 | " bne- 1b\n" \ |
62 | "2: " __ARCH_ACQ_INSTR \ |
63 | : "=&r" (__tmp) \ |
64 | : "b" (__memp), "r" (oldval), "r" (newval) \ |
65 | : "cr0", "memory"); \ |
66 | __tmp; \ |
67 | }) |
68 | |
69 | #define __arch_compare_and_exchange_val_32_rel(mem, newval, oldval) \ |
70 | ({ \ |
71 | __typeof (*(mem)) __tmp; \ |
72 | __typeof (mem) __memp = (mem); \ |
73 | __asm __volatile (__ARCH_REL_INSTR "\n" \ |
74 | "1: lwarx %0,0,%1" MUTEX_HINT_REL "\n" \ |
75 | " cmpw %0,%2\n" \ |
76 | " bne 2f\n" \ |
77 | " stwcx. %3,0,%1\n" \ |
78 | " bne- 1b\n" \ |
79 | "2: " \ |
80 | : "=&r" (__tmp) \ |
81 | : "b" (__memp), "r" (oldval), "r" (newval) \ |
82 | : "cr0", "memory"); \ |
83 | __tmp; \ |
84 | }) |
85 | |
86 | #define __arch_atomic_exchange_32_acq(mem, value) \ |
87 | ({ \ |
88 | __typeof (*mem) __val; \ |
89 | __asm __volatile ( \ |
90 | "1: lwarx %0,0,%2" MUTEX_HINT_ACQ "\n" \ |
91 | " stwcx. %3,0,%2\n" \ |
92 | " bne- 1b\n" \ |
93 | " " __ARCH_ACQ_INSTR \ |
94 | : "=&r" (__val), "=m" (*mem) \ |
95 | : "b" (mem), "r" (value), "m" (*mem) \ |
96 | : "cr0", "memory"); \ |
97 | __val; \ |
98 | }) |
99 | |
100 | #define __arch_atomic_exchange_32_rel(mem, value) \ |
101 | ({ \ |
102 | __typeof (*mem) __val; \ |
103 | __asm __volatile (__ARCH_REL_INSTR "\n" \ |
104 | "1: lwarx %0,0,%2" MUTEX_HINT_REL "\n" \ |
105 | " stwcx. %3,0,%2\n" \ |
106 | " bne- 1b" \ |
107 | : "=&r" (__val), "=m" (*mem) \ |
108 | : "b" (mem), "r" (value), "m" (*mem) \ |
109 | : "cr0", "memory"); \ |
110 | __val; \ |
111 | }) |
112 | |
113 | #define __arch_atomic_exchange_and_add_32(mem, value) \ |
114 | ({ \ |
115 | __typeof (*mem) __val, __tmp; \ |
116 | __asm __volatile ("1: lwarx %0,0,%3\n" \ |
117 | " add %1,%0,%4\n" \ |
118 | " stwcx. %1,0,%3\n" \ |
119 | " bne- 1b" \ |
120 | : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ |
121 | : "b" (mem), "r" (value), "m" (*mem) \ |
122 | : "cr0", "memory"); \ |
123 | __val; \ |
124 | }) |
125 | |
126 | #define __arch_atomic_exchange_and_add_32_acq(mem, value) \ |
127 | ({ \ |
128 | __typeof (*mem) __val, __tmp; \ |
129 | __asm __volatile ("1: lwarx %0,0,%3" MUTEX_HINT_ACQ "\n" \ |
130 | " add %1,%0,%4\n" \ |
131 | " stwcx. %1,0,%3\n" \ |
132 | " bne- 1b\n" \ |
133 | __ARCH_ACQ_INSTR \ |
134 | : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ |
135 | : "b" (mem), "r" (value), "m" (*mem) \ |
136 | : "cr0", "memory"); \ |
137 | __val; \ |
138 | }) |
139 | |
140 | #define __arch_atomic_exchange_and_add_32_rel(mem, value) \ |
141 | ({ \ |
142 | __typeof (*mem) __val, __tmp; \ |
143 | __asm __volatile (__ARCH_REL_INSTR "\n" \ |
144 | "1: lwarx %0,0,%3" MUTEX_HINT_REL "\n" \ |
145 | " add %1,%0,%4\n" \ |
146 | " stwcx. %1,0,%3\n" \ |
147 | " bne- 1b" \ |
148 | : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ |
149 | : "b" (mem), "r" (value), "m" (*mem) \ |
150 | : "cr0", "memory"); \ |
151 | __val; \ |
152 | }) |
153 | |
154 | #define __arch_atomic_increment_val_32(mem) \ |
155 | ({ \ |
156 | __typeof (*(mem)) __val; \ |
157 | __asm __volatile ("1: lwarx %0,0,%2\n" \ |
158 | " addi %0,%0,1\n" \ |
159 | " stwcx. %0,0,%2\n" \ |
160 | " bne- 1b" \ |
161 | : "=&b" (__val), "=m" (*mem) \ |
162 | : "b" (mem), "m" (*mem) \ |
163 | : "cr0", "memory"); \ |
164 | __val; \ |
165 | }) |
166 | |
167 | #define __arch_atomic_decrement_val_32(mem) \ |
168 | ({ \ |
169 | __typeof (*(mem)) __val; \ |
170 | __asm __volatile ("1: lwarx %0,0,%2\n" \ |
171 | " subi %0,%0,1\n" \ |
172 | " stwcx. %0,0,%2\n" \ |
173 | " bne- 1b" \ |
174 | : "=&b" (__val), "=m" (*mem) \ |
175 | : "b" (mem), "m" (*mem) \ |
176 | : "cr0", "memory"); \ |
177 | __val; \ |
178 | }) |
179 | |
180 | #define __arch_atomic_decrement_if_positive_32(mem) \ |
181 | ({ int __val, __tmp; \ |
182 | __asm __volatile ("1: lwarx %0,0,%3\n" \ |
183 | " cmpwi 0,%0,0\n" \ |
184 | " addi %1,%0,-1\n" \ |
185 | " ble 2f\n" \ |
186 | " stwcx. %1,0,%3\n" \ |
187 | " bne- 1b\n" \ |
188 | "2: " __ARCH_ACQ_INSTR \ |
189 | : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ |
190 | : "b" (mem), "m" (*mem) \ |
191 | : "cr0", "memory"); \ |
192 | __val; \ |
193 | }) |
194 | |
195 | #define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ |
196 | ({ \ |
197 | __typeof (*(mem)) __result; \ |
198 | if (sizeof (*mem) == 4) \ |
199 | __result = __arch_compare_and_exchange_val_32_acq(mem, newval, oldval); \ |
200 | else if (sizeof (*mem) == 8) \ |
201 | __result = __arch_compare_and_exchange_val_64_acq(mem, newval, oldval); \ |
202 | else \ |
203 | abort (); \ |
204 | __result; \ |
205 | }) |
206 | |
207 | #define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \ |
208 | ({ \ |
209 | __typeof (*(mem)) __result; \ |
210 | if (sizeof (*mem) == 4) \ |
211 | __result = __arch_compare_and_exchange_val_32_rel(mem, newval, oldval); \ |
212 | else if (sizeof (*mem) == 8) \ |
213 | __result = __arch_compare_and_exchange_val_64_rel(mem, newval, oldval); \ |
214 | else \ |
215 | abort (); \ |
216 | __result; \ |
217 | }) |
218 | |
219 | #define atomic_exchange_acq(mem, value) \ |
220 | ({ \ |
221 | __typeof (*(mem)) __result; \ |
222 | if (sizeof (*mem) == 4) \ |
223 | __result = __arch_atomic_exchange_32_acq (mem, value); \ |
224 | else if (sizeof (*mem) == 8) \ |
225 | __result = __arch_atomic_exchange_64_acq (mem, value); \ |
226 | else \ |
227 | abort (); \ |
228 | __result; \ |
229 | }) |
230 | |
231 | #define atomic_exchange_rel(mem, value) \ |
232 | ({ \ |
233 | __typeof (*(mem)) __result; \ |
234 | if (sizeof (*mem) == 4) \ |
235 | __result = __arch_atomic_exchange_32_rel (mem, value); \ |
236 | else if (sizeof (*mem) == 8) \ |
237 | __result = __arch_atomic_exchange_64_rel (mem, value); \ |
238 | else \ |
239 | abort (); \ |
240 | __result; \ |
241 | }) |
242 | |
243 | #define atomic_exchange_and_add(mem, value) \ |
244 | ({ \ |
245 | __typeof (*(mem)) __result; \ |
246 | if (sizeof (*mem) == 4) \ |
247 | __result = __arch_atomic_exchange_and_add_32 (mem, value); \ |
248 | else if (sizeof (*mem) == 8) \ |
249 | __result = __arch_atomic_exchange_and_add_64 (mem, value); \ |
250 | else \ |
251 | abort (); \ |
252 | __result; \ |
253 | }) |
254 | #define atomic_exchange_and_add_acq(mem, value) \ |
255 | ({ \ |
256 | __typeof (*(mem)) __result; \ |
257 | if (sizeof (*mem) == 4) \ |
258 | __result = __arch_atomic_exchange_and_add_32_acq (mem, value); \ |
259 | else if (sizeof (*mem) == 8) \ |
260 | __result = __arch_atomic_exchange_and_add_64_acq (mem, value); \ |
261 | else \ |
262 | abort (); \ |
263 | __result; \ |
264 | }) |
265 | #define atomic_exchange_and_add_rel(mem, value) \ |
266 | ({ \ |
267 | __typeof (*(mem)) __result; \ |
268 | if (sizeof (*mem) == 4) \ |
269 | __result = __arch_atomic_exchange_and_add_32_rel (mem, value); \ |
270 | else if (sizeof (*mem) == 8) \ |
271 | __result = __arch_atomic_exchange_and_add_64_rel (mem, value); \ |
272 | else \ |
273 | abort (); \ |
274 | __result; \ |
275 | }) |
276 | |
277 | #define atomic_increment_val(mem) \ |
278 | ({ \ |
279 | __typeof (*(mem)) __result; \ |
280 | if (sizeof (*(mem)) == 4) \ |
281 | __result = __arch_atomic_increment_val_32 (mem); \ |
282 | else if (sizeof (*(mem)) == 8) \ |
283 | __result = __arch_atomic_increment_val_64 (mem); \ |
284 | else \ |
285 | abort (); \ |
286 | __result; \ |
287 | }) |
288 | |
289 | #define atomic_increment(mem) ({ atomic_increment_val (mem); (void) 0; }) |
290 | |
291 | #define atomic_decrement_val(mem) \ |
292 | ({ \ |
293 | __typeof (*(mem)) __result; \ |
294 | if (sizeof (*(mem)) == 4) \ |
295 | __result = __arch_atomic_decrement_val_32 (mem); \ |
296 | else if (sizeof (*(mem)) == 8) \ |
297 | __result = __arch_atomic_decrement_val_64 (mem); \ |
298 | else \ |
299 | abort (); \ |
300 | __result; \ |
301 | }) |
302 | |
303 | #define atomic_decrement(mem) ({ atomic_decrement_val (mem); (void) 0; }) |
304 | |
305 | |
306 | /* Decrement *MEM if it is > 0, and return the old value. */ |
307 | #define atomic_decrement_if_positive(mem) \ |
308 | ({ __typeof (*(mem)) __result; \ |
309 | if (sizeof (*mem) == 4) \ |
310 | __result = __arch_atomic_decrement_if_positive_32 (mem); \ |
311 | else if (sizeof (*mem) == 8) \ |
312 | __result = __arch_atomic_decrement_if_positive_64 (mem); \ |
313 | else \ |
314 | abort (); \ |
315 | __result; \ |
316 | }) |
317 |
Warning: This file is not a C or C++ file. It does not have highlighting.