~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/loongarch/include/asm/atomic.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 /*
  3  * Atomic operations.
  4  *
  5  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  6  */
  7 #ifndef _ASM_ATOMIC_H
  8 #define _ASM_ATOMIC_H
  9 
 10 #include <linux/types.h>
 11 #include <asm/barrier.h>
 12 #include <asm/cmpxchg.h>
 13 
 14 #if __SIZEOF_LONG__ == 4
 15 #define __LL            "ll.w   "
 16 #define __SC            "sc.w   "
 17 #define __AMADD         "amadd.w        "
 18 #define __AMAND_DB      "amand_db.w     "
 19 #define __AMOR_DB       "amor_db.w      "
 20 #define __AMXOR_DB      "amxor_db.w     "
 21 #elif __SIZEOF_LONG__ == 8
 22 #define __LL            "ll.d   "
 23 #define __SC            "sc.d   "
 24 #define __AMADD         "amadd.d        "
 25 #define __AMAND_DB      "amand_db.d     "
 26 #define __AMOR_DB       "amor_db.d      "
 27 #define __AMXOR_DB      "amxor_db.d     "
 28 #endif
 29 
 30 #define ATOMIC_INIT(i)    { (i) }
 31 
 32 #define arch_atomic_read(v)     READ_ONCE((v)->counter)
 33 #define arch_atomic_set(v, i)   WRITE_ONCE((v)->counter, (i))
 34 
 35 #define ATOMIC_OP(op, I, asm_op)                                        \
 36 static inline void arch_atomic_##op(int i, atomic_t *v)                 \
 37 {                                                                       \
 38         __asm__ __volatile__(                                           \
 39         "am"#asm_op".w" " $zero, %1, %0 \n"                             \
 40         : "+ZB" (v->counter)                                            \
 41         : "r" (I)                                                       \
 42         : "memory");                                                    \
 43 }
 44 
 45 #define ATOMIC_OP_RETURN(op, I, asm_op, c_op, mb, suffix)               \
 46 static inline int arch_atomic_##op##_return##suffix(int i, atomic_t *v) \
 47 {                                                                       \
 48         int result;                                                     \
 49                                                                         \
 50         __asm__ __volatile__(                                           \
 51         "am"#asm_op#mb".w" " %1, %2, %0         \n"                     \
 52         : "+ZB" (v->counter), "=&r" (result)                            \
 53         : "r" (I)                                                       \
 54         : "memory");                                                    \
 55                                                                         \
 56         return result c_op I;                                           \
 57 }
 58 
 59 #define ATOMIC_FETCH_OP(op, I, asm_op, mb, suffix)                      \
 60 static inline int arch_atomic_fetch_##op##suffix(int i, atomic_t *v)    \
 61 {                                                                       \
 62         int result;                                                     \
 63                                                                         \
 64         __asm__ __volatile__(                                           \
 65         "am"#asm_op#mb".w" " %1, %2, %0         \n"                     \
 66         : "+ZB" (v->counter), "=&r" (result)                            \
 67         : "r" (I)                                                       \
 68         : "memory");                                                    \
 69                                                                         \
 70         return result;                                                  \
 71 }
 72 
 73 #define ATOMIC_OPS(op, I, asm_op, c_op)                                 \
 74         ATOMIC_OP(op, I, asm_op)                                        \
 75         ATOMIC_OP_RETURN(op, I, asm_op, c_op, _db,         )            \
 76         ATOMIC_OP_RETURN(op, I, asm_op, c_op,    , _relaxed)            \
 77         ATOMIC_FETCH_OP(op, I, asm_op, _db,         )                   \
 78         ATOMIC_FETCH_OP(op, I, asm_op,    , _relaxed)
 79 
 80 ATOMIC_OPS(add, i, add, +)
 81 ATOMIC_OPS(sub, -i, add, +)
 82 
 83 #define arch_atomic_add_return          arch_atomic_add_return
 84 #define arch_atomic_add_return_acquire  arch_atomic_add_return
 85 #define arch_atomic_add_return_release  arch_atomic_add_return
 86 #define arch_atomic_add_return_relaxed  arch_atomic_add_return_relaxed
 87 #define arch_atomic_sub_return          arch_atomic_sub_return
 88 #define arch_atomic_sub_return_acquire  arch_atomic_sub_return
 89 #define arch_atomic_sub_return_release  arch_atomic_sub_return
 90 #define arch_atomic_sub_return_relaxed  arch_atomic_sub_return_relaxed
 91 #define arch_atomic_fetch_add           arch_atomic_fetch_add
 92 #define arch_atomic_fetch_add_acquire   arch_atomic_fetch_add
 93 #define arch_atomic_fetch_add_release   arch_atomic_fetch_add
 94 #define arch_atomic_fetch_add_relaxed   arch_atomic_fetch_add_relaxed
 95 #define arch_atomic_fetch_sub           arch_atomic_fetch_sub
 96 #define arch_atomic_fetch_sub_acquire   arch_atomic_fetch_sub
 97 #define arch_atomic_fetch_sub_release   arch_atomic_fetch_sub
 98 #define arch_atomic_fetch_sub_relaxed   arch_atomic_fetch_sub_relaxed
 99 
100 #undef ATOMIC_OPS
101 
102 #define ATOMIC_OPS(op, I, asm_op)                                       \
103         ATOMIC_OP(op, I, asm_op)                                        \
104         ATOMIC_FETCH_OP(op, I, asm_op, _db,         )                   \
105         ATOMIC_FETCH_OP(op, I, asm_op,    , _relaxed)
106 
107 ATOMIC_OPS(and, i, and)
108 ATOMIC_OPS(or, i, or)
109 ATOMIC_OPS(xor, i, xor)
110 
111 #define arch_atomic_fetch_and           arch_atomic_fetch_and
112 #define arch_atomic_fetch_and_acquire   arch_atomic_fetch_and
113 #define arch_atomic_fetch_and_release   arch_atomic_fetch_and
114 #define arch_atomic_fetch_and_relaxed   arch_atomic_fetch_and_relaxed
115 #define arch_atomic_fetch_or            arch_atomic_fetch_or
116 #define arch_atomic_fetch_or_acquire    arch_atomic_fetch_or
117 #define arch_atomic_fetch_or_release    arch_atomic_fetch_or
118 #define arch_atomic_fetch_or_relaxed    arch_atomic_fetch_or_relaxed
119 #define arch_atomic_fetch_xor           arch_atomic_fetch_xor
120 #define arch_atomic_fetch_xor_acquire   arch_atomic_fetch_xor
121 #define arch_atomic_fetch_xor_release   arch_atomic_fetch_xor
122 #define arch_atomic_fetch_xor_relaxed   arch_atomic_fetch_xor_relaxed
123 
124 #undef ATOMIC_OPS
125 #undef ATOMIC_FETCH_OP
126 #undef ATOMIC_OP_RETURN
127 #undef ATOMIC_OP
128 
129 static inline int arch_atomic_fetch_add_unless(atomic_t *v, int a, int u)
130 {
131        int prev, rc;
132 
133         __asm__ __volatile__ (
134                 "0:     ll.w    %[p],  %[c]\n"
135                 "       beq     %[p],  %[u], 1f\n"
136                 "       add.w   %[rc], %[p], %[a]\n"
137                 "       sc.w    %[rc], %[c]\n"
138                 "       beqz    %[rc], 0b\n"
139                 "       b       2f\n"
140                 "1:\n"
141                 __WEAK_LLSC_MB
142                 "2:\n"
143                 : [p]"=&r" (prev), [rc]"=&r" (rc),
144                   [c]"=ZB" (v->counter)
145                 : [a]"r" (a), [u]"r" (u)
146                 : "memory");
147 
148         return prev;
149 }
150 #define arch_atomic_fetch_add_unless arch_atomic_fetch_add_unless
151 
152 static inline int arch_atomic_sub_if_positive(int i, atomic_t *v)
153 {
154         int result;
155         int temp;
156 
157         if (__builtin_constant_p(i)) {
158                 __asm__ __volatile__(
159                 "1:     ll.w    %1, %2          # atomic_sub_if_positive\n"
160                 "       addi.w  %0, %1, %3                              \n"
161                 "       move    %1, %0                                  \n"
162                 "       bltz    %0, 2f                                  \n"
163                 "       sc.w    %1, %2                                  \n"
164                 "       beqz    %1, 1b                                  \n"
165                 "2:                                                     \n"
166                 __WEAK_LLSC_MB
167                 : "=&r" (result), "=&r" (temp), "+ZC" (v->counter)
168                 : "I" (-i));
169         } else {
170                 __asm__ __volatile__(
171                 "1:     ll.w    %1, %2          # atomic_sub_if_positive\n"
172                 "       sub.w   %0, %1, %3                              \n"
173                 "       move    %1, %0                                  \n"
174                 "       bltz    %0, 2f                                  \n"
175                 "       sc.w    %1, %2                                  \n"
176                 "       beqz    %1, 1b                                  \n"
177                 "2:                                                     \n"
178                 __WEAK_LLSC_MB
179                 : "=&r" (result), "=&r" (temp), "+ZC" (v->counter)
180                 : "r" (i));
181         }
182 
183         return result;
184 }
185 
186 #define arch_atomic_dec_if_positive(v)  arch_atomic_sub_if_positive(1, v)
187 
188 #ifdef CONFIG_64BIT
189 
190 #define ATOMIC64_INIT(i)    { (i) }
191 
192 #define arch_atomic64_read(v)   READ_ONCE((v)->counter)
193 #define arch_atomic64_set(v, i) WRITE_ONCE((v)->counter, (i))
194 
195 #define ATOMIC64_OP(op, I, asm_op)                                      \
196 static inline void arch_atomic64_##op(long i, atomic64_t *v)            \
197 {                                                                       \
198         __asm__ __volatile__(                                           \
199         "am"#asm_op".d " " $zero, %1, %0        \n"                     \
200         : "+ZB" (v->counter)                                            \
201         : "r" (I)                                                       \
202         : "memory");                                                    \
203 }
204 
205 #define ATOMIC64_OP_RETURN(op, I, asm_op, c_op, mb, suffix)                     \
206 static inline long arch_atomic64_##op##_return##suffix(long i, atomic64_t *v)   \
207 {                                                                               \
208         long result;                                                            \
209         __asm__ __volatile__(                                                   \
210         "am"#asm_op#mb".d " " %1, %2, %0                \n"                     \
211         : "+ZB" (v->counter), "=&r" (result)                                    \
212         : "r" (I)                                                               \
213         : "memory");                                                            \
214                                                                                 \
215         return result c_op I;                                                   \
216 }
217 
218 #define ATOMIC64_FETCH_OP(op, I, asm_op, mb, suffix)                            \
219 static inline long arch_atomic64_fetch_##op##suffix(long i, atomic64_t *v)      \
220 {                                                                               \
221         long result;                                                            \
222                                                                                 \
223         __asm__ __volatile__(                                                   \
224         "am"#asm_op#mb".d " " %1, %2, %0                \n"                     \
225         : "+ZB" (v->counter), "=&r" (result)                                    \
226         : "r" (I)                                                               \
227         : "memory");                                                            \
228                                                                                 \
229         return result;                                                          \
230 }
231 
232 #define ATOMIC64_OPS(op, I, asm_op, c_op)                                     \
233         ATOMIC64_OP(op, I, asm_op)                                            \
234         ATOMIC64_OP_RETURN(op, I, asm_op, c_op, _db,         )                \
235         ATOMIC64_OP_RETURN(op, I, asm_op, c_op,    , _relaxed)                \
236         ATOMIC64_FETCH_OP(op, I, asm_op, _db,         )                       \
237         ATOMIC64_FETCH_OP(op, I, asm_op,    , _relaxed)
238 
239 ATOMIC64_OPS(add, i, add, +)
240 ATOMIC64_OPS(sub, -i, add, +)
241 
242 #define arch_atomic64_add_return                arch_atomic64_add_return
243 #define arch_atomic64_add_return_acquire        arch_atomic64_add_return
244 #define arch_atomic64_add_return_release        arch_atomic64_add_return
245 #define arch_atomic64_add_return_relaxed        arch_atomic64_add_return_relaxed
246 #define arch_atomic64_sub_return                arch_atomic64_sub_return
247 #define arch_atomic64_sub_return_acquire        arch_atomic64_sub_return
248 #define arch_atomic64_sub_return_release        arch_atomic64_sub_return
249 #define arch_atomic64_sub_return_relaxed        arch_atomic64_sub_return_relaxed
250 #define arch_atomic64_fetch_add                 arch_atomic64_fetch_add
251 #define arch_atomic64_fetch_add_acquire         arch_atomic64_fetch_add
252 #define arch_atomic64_fetch_add_release         arch_atomic64_fetch_add
253 #define arch_atomic64_fetch_add_relaxed         arch_atomic64_fetch_add_relaxed
254 #define arch_atomic64_fetch_sub                 arch_atomic64_fetch_sub
255 #define arch_atomic64_fetch_sub_acquire         arch_atomic64_fetch_sub
256 #define arch_atomic64_fetch_sub_release         arch_atomic64_fetch_sub
257 #define arch_atomic64_fetch_sub_relaxed         arch_atomic64_fetch_sub_relaxed
258 
259 #undef ATOMIC64_OPS
260 
261 #define ATOMIC64_OPS(op, I, asm_op)                                           \
262         ATOMIC64_OP(op, I, asm_op)                                            \
263         ATOMIC64_FETCH_OP(op, I, asm_op, _db,         )                       \
264         ATOMIC64_FETCH_OP(op, I, asm_op,    , _relaxed)
265 
266 ATOMIC64_OPS(and, i, and)
267 ATOMIC64_OPS(or, i, or)
268 ATOMIC64_OPS(xor, i, xor)
269 
270 #define arch_atomic64_fetch_and         arch_atomic64_fetch_and
271 #define arch_atomic64_fetch_and_acquire arch_atomic64_fetch_and
272 #define arch_atomic64_fetch_and_release arch_atomic64_fetch_and
273 #define arch_atomic64_fetch_and_relaxed arch_atomic64_fetch_and_relaxed
274 #define arch_atomic64_fetch_or          arch_atomic64_fetch_or
275 #define arch_atomic64_fetch_or_acquire  arch_atomic64_fetch_or
276 #define arch_atomic64_fetch_or_release  arch_atomic64_fetch_or
277 #define arch_atomic64_fetch_or_relaxed  arch_atomic64_fetch_or_relaxed
278 #define arch_atomic64_fetch_xor         arch_atomic64_fetch_xor
279 #define arch_atomic64_fetch_xor_acquire arch_atomic64_fetch_xor
280 #define arch_atomic64_fetch_xor_release arch_atomic64_fetch_xor
281 #define arch_atomic64_fetch_xor_relaxed arch_atomic64_fetch_xor_relaxed
282 
283 #undef ATOMIC64_OPS
284 #undef ATOMIC64_FETCH_OP
285 #undef ATOMIC64_OP_RETURN
286 #undef ATOMIC64_OP
287 
288 static inline long arch_atomic64_fetch_add_unless(atomic64_t *v, long a, long u)
289 {
290        long prev, rc;
291 
292         __asm__ __volatile__ (
293                 "0:     ll.d    %[p],  %[c]\n"
294                 "       beq     %[p],  %[u], 1f\n"
295                 "       add.d   %[rc], %[p], %[a]\n"
296                 "       sc.d    %[rc], %[c]\n"
297                 "       beqz    %[rc], 0b\n"
298                 "       b       2f\n"
299                 "1:\n"
300                 __WEAK_LLSC_MB
301                 "2:\n"
302                 : [p]"=&r" (prev), [rc]"=&r" (rc),
303                   [c] "=ZB" (v->counter)
304                 : [a]"r" (a), [u]"r" (u)
305                 : "memory");
306 
307         return prev;
308 }
309 #define arch_atomic64_fetch_add_unless arch_atomic64_fetch_add_unless
310 
311 static inline long arch_atomic64_sub_if_positive(long i, atomic64_t *v)
312 {
313         long result;
314         long temp;
315 
316         if (__builtin_constant_p(i)) {
317                 __asm__ __volatile__(
318                 "1:     ll.d    %1, %2  # atomic64_sub_if_positive      \n"
319                 "       addi.d  %0, %1, %3                              \n"
320                 "       move    %1, %0                                  \n"
321                 "       bltz    %0, 2f                                  \n"
322                 "       sc.d    %1, %2                                  \n"
323                 "       beqz    %1, 1b                                  \n"
324                 "2:                                                     \n"
325                 __WEAK_LLSC_MB
326                 : "=&r" (result), "=&r" (temp), "+ZC" (v->counter)
327                 : "I" (-i));
328         } else {
329                 __asm__ __volatile__(
330                 "1:     ll.d    %1, %2  # atomic64_sub_if_positive      \n"
331                 "       sub.d   %0, %1, %3                              \n"
332                 "       move    %1, %0                                  \n"
333                 "       bltz    %0, 2f                                  \n"
334                 "       sc.d    %1, %2                                  \n"
335                 "       beqz    %1, 1b                                  \n"
336                 "2:                                                     \n"
337                 __WEAK_LLSC_MB
338                 : "=&r" (result), "=&r" (temp), "+ZC" (v->counter)
339                 : "r" (i));
340         }
341 
342         return result;
343 }
344 
345 #define arch_atomic64_dec_if_positive(v)        arch_atomic64_sub_if_positive(1, v)
346 
347 #endif /* CONFIG_64BIT */
348 
349 #endif /* _ASM_ATOMIC_H */
350 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php