1 /* Atomic operations used inside libc. Linux/SH version.
2 Copyright (C) 2003-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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 <https://www.gnu.org/licenses/>. */
19 #define __HAVE_64B_ATOMICS 0
20 #define USE_ATOMIC_COMPILER_BUILTINS 0
22 /* XXX Is this actually correct? */
23 #define ATOMIC_EXCHANGE_USES_CAS 1
25 /* SH kernel has implemented a gUSA ("g" User Space Atomicity) support
26 for the user space atomicity. The atomicity macros use this scheme.
29 Niibe Yutaka, "gUSA: Simple and Efficient User Space Atomicity
30 Emulation with Little Kernel Modification", Linux Conference 2002,
31 Japan. http://lc.linux.or.jp/lc2002/papers/niibe0919h.pdf (in
34 B.N. Bershad, D. Redell, and J. Ellis, "Fast Mutual Exclusion for
35 Uniprocessors", Proceedings of the Fifth Architectural Support for
36 Programming Languages and Operating Systems (ASPLOS), pp. 223-233,
37 October 1992. http://www.cs.washington.edu/homes/bershad/Papers/Rcs.ps
40 r15: -(size of atomic instruction sequence) < 0
42 r1: saved stack pointer
45 #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
46 ({ __typeof (*(mem)) __result; \
57 : "=&r" (__result) : "u" (mem), "u" (newval), "u" (oldval) \
58 : "r0", "r1", "t", "memory"); \
61 #define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
62 ({ __typeof (*(mem)) __result; \
74 : "=&r" (__result) : "u" (mem), "u" (newval), "u" (oldval) \
75 : "r0", "r1", "t", "memory"); \
78 #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
79 ({ __typeof (*(mem)) __result; \
90 : "=&r" (__result) : "u" (mem), "u" (newval), "u" (oldval) \
91 : "r0", "r1", "t", "memory"); \
94 /* XXX We do not really need 64-bit compare-and-exchange. At least
95 not in the moment. Using it would mean causing portability
96 problems since not many other 32-bit architectures have support for
97 such an operation. So don't define any code for now. */
99 # define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
100 (abort (), (__typeof (*mem)) 0)
102 #define atomic_exchange_and_add(mem, value) \
103 ({ __typeof (*(mem)) __result, __tmp, __value = (value); \
104 if (sizeof (*(mem)) == 1) \
115 : "=&r" (__result), "=&r" (__tmp) : "u" (mem), "1" (__value) \
116 : "r0", "r1", "r2", "memory"); \
117 else if (sizeof (*(mem)) == 2) \
128 : "=&r" (__result), "=&r" (__tmp) : "u" (mem), "1" (__value) \
129 : "r0", "r1", "r2", "memory"); \
130 else if (sizeof (*(mem)) == 4) \
141 : "=&r" (__result), "=&r" (__tmp) : "u" (mem), "1" (__value) \
142 : "r0", "r1", "r2", "memory"); \
145 __typeof (mem) memp = (mem); \
148 while (__arch_compare_and_exchange_val_64_acq \
149 (memp, __result + __value, __result) == __result); \
154 #define atomic_add(mem, value) \
155 (void) ({ __typeof (*(mem)) __tmp, __value = (value); \
156 if (sizeof (*(mem)) == 1) \
166 : "=&r" (__tmp) : "u" (mem), "0" (__value) \
167 : "r0", "r1", "r2", "memory"); \
168 else if (sizeof (*(mem)) == 2) \
178 : "=&r" (__tmp) : "u" (mem), "0" (__value) \
179 : "r0", "r1", "r2", "memory"); \
180 else if (sizeof (*(mem)) == 4) \
190 : "=&r" (__tmp) : "u" (mem), "0" (__value) \
191 : "r0", "r1", "r2", "memory"); \
194 __typeof (*(mem)) oldval; \
195 __typeof (mem) memp = (mem); \
198 while (__arch_compare_and_exchange_val_64_acq \
199 (memp, oldval + __value, oldval) == oldval); \
204 #define atomic_add_negative(mem, value) \
205 ({ unsigned char __result; \
206 __typeof (*(mem)) __tmp, __value = (value); \
207 if (sizeof (*(mem)) == 1) \
219 : "=r" (__result), "=&r" (__tmp) : "u" (mem), "1" (__value) \
220 : "r0", "r1", "r2", "t", "memory"); \
221 else if (sizeof (*(mem)) == 2) \
233 : "=r" (__result), "=&r" (__tmp) : "u" (mem), "1" (__value) \
234 : "r0", "r1", "r2", "t", "memory"); \
235 else if (sizeof (*(mem)) == 4) \
247 : "=r" (__result), "=&r" (__tmp) : "u" (mem), "1" (__value) \
248 : "r0", "r1", "r2", "t", "memory"); \
253 #define atomic_add_zero(mem, value) \
254 ({ unsigned char __result; \
255 __typeof (*(mem)) __tmp, __value = (value); \
256 if (sizeof (*(mem)) == 1) \
268 : "=r" (__result), "=&r" (__tmp) : "u" (mem), "1" (__value) \
269 : "r0", "r1", "r2", "t", "memory"); \
270 else if (sizeof (*(mem)) == 2) \
282 : "=r" (__result), "=&r" (__tmp) : "u" (mem), "1" (__value) \
283 : "r0", "r1", "r2", "t", "memory"); \
284 else if (sizeof (*(mem)) == 4) \
296 : "=r" (__result), "=&r" (__tmp) : "u" (mem), "1" (__value) \
297 : "r0", "r1", "r2", "t", "memory"); \
302 #define atomic_increment_and_test(mem) atomic_add_zero((mem), 1)
303 #define atomic_decrement_and_test(mem) atomic_add_zero((mem), -1)
305 #define atomic_bit_set(mem, bit) \
306 (void) ({ unsigned int __mask = 1 << (bit); \
307 if (sizeof (*(mem)) == 1) \
317 : : "u" (mem), "u" (__mask) \
318 : "r0", "r1", "r2", "memory"); \
319 else if (sizeof (*(mem)) == 2) \
329 : : "u" (mem), "u" (__mask) \
330 : "r0", "r1", "r2", "memory"); \
331 else if (sizeof (*(mem)) == 4) \
341 : : "u" (mem), "u" (__mask) \
342 : "r0", "r1", "r2", "memory"); \
347 #define atomic_bit_test_set(mem, bit) \
348 ({ unsigned int __mask = 1 << (bit); \
349 unsigned int __result = __mask; \
350 if (sizeof (*(mem)) == 1) \
362 : "=&r" (__result), "=&r" (__mask) \
363 : "u" (mem), "0" (__result), "1" (__mask) \
364 : "r0", "r1", "r2", "r3", "memory"); \
365 else if (sizeof (*(mem)) == 2) \
377 : "=&r" (__result), "=&r" (__mask) \
378 : "u" (mem), "0" (__result), "1" (__mask) \
379 : "r0", "r1", "r2", "r3", "memory"); \
380 else if (sizeof (*(mem)) == 4) \
392 : "=&r" (__result), "=&r" (__mask) \
393 : "u" (mem), "0" (__result), "1" (__mask) \
394 : "r0", "r1", "r2", "r3", "memory"); \