Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef __ASM_CSKY_ATOMIC_H
4#define __ASM_CSKY_ATOMIC_H
5
6#ifdef CONFIG_SMP
7#include <asm-generic/atomic64.h>
8
9#include <asm/cmpxchg.h>
10#include <asm/barrier.h>
11
12#define __atomic_acquire_fence() __bar_brarw()
13
14#define __atomic_release_fence() __bar_brwaw()
15
16static __always_inline int arch_atomic_read(const atomic_t *v)
17{
18 return READ_ONCE(v->counter);
19}
20static __always_inline void arch_atomic_set(atomic_t *v, int i)
21{
22 WRITE_ONCE(v->counter, i);
23}
24
25#define ATOMIC_OP(op) \
26static __always_inline \
27void arch_atomic_##op(int i, atomic_t *v) \
28{ \
29 unsigned long tmp; \
30 __asm__ __volatile__ ( \
31 "1: ldex.w %0, (%2) \n" \
32 " " #op " %0, %1 \n" \
33 " stex.w %0, (%2) \n" \
34 " bez %0, 1b \n" \
35 : "=&r" (tmp) \
36 : "r" (i), "r" (&v->counter) \
37 : "memory"); \
38}
39
40ATOMIC_OP(add)
41ATOMIC_OP(sub)
42ATOMIC_OP(and)
43ATOMIC_OP( or)
44ATOMIC_OP(xor)
45
46#undef ATOMIC_OP
47
48#define ATOMIC_FETCH_OP(op) \
49static __always_inline \
50int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v) \
51{ \
52 register int ret, tmp; \
53 __asm__ __volatile__ ( \
54 "1: ldex.w %0, (%3) \n" \
55 " mov %1, %0 \n" \
56 " " #op " %0, %2 \n" \
57 " stex.w %0, (%3) \n" \
58 " bez %0, 1b \n" \
59 : "=&r" (tmp), "=&r" (ret) \
60 : "r" (i), "r"(&v->counter) \
61 : "memory"); \
62 return ret; \
63}
64
65#define ATOMIC_OP_RETURN(op, c_op) \
66static __always_inline \
67int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \
68{ \
69 return arch_atomic_fetch_##op##_relaxed(i, v) c_op i; \
70}
71
72#define ATOMIC_OPS(op, c_op) \
73 ATOMIC_FETCH_OP(op) \
74 ATOMIC_OP_RETURN(op, c_op)
75
76ATOMIC_OPS(add, +)
77ATOMIC_OPS(sub, -)
78
79#define arch_atomic_fetch_add_relaxed arch_atomic_fetch_add_relaxed
80#define arch_atomic_fetch_sub_relaxed arch_atomic_fetch_sub_relaxed
81
82#define arch_atomic_add_return_relaxed arch_atomic_add_return_relaxed
83#define arch_atomic_sub_return_relaxed arch_atomic_sub_return_relaxed
84
85#undef ATOMIC_OPS
86#undef ATOMIC_OP_RETURN
87
88#define ATOMIC_OPS(op) \
89 ATOMIC_FETCH_OP(op)
90
91ATOMIC_OPS(and)
92ATOMIC_OPS( or)
93ATOMIC_OPS(xor)
94
95#define arch_atomic_fetch_and_relaxed arch_atomic_fetch_and_relaxed
96#define arch_atomic_fetch_or_relaxed arch_atomic_fetch_or_relaxed
97#define arch_atomic_fetch_xor_relaxed arch_atomic_fetch_xor_relaxed
98
99#undef ATOMIC_OPS
100
101#undef ATOMIC_FETCH_OP
102
103static __always_inline int
104arch_atomic_fetch_add_unless(atomic_t *v, int a, int u)
105{
106 int prev, tmp;
107
108 __asm__ __volatile__ (
109 RELEASE_FENCE
110 "1: ldex.w %0, (%3) \n"
111 " cmpne %0, %4 \n"
112 " bf 2f \n"
113 " mov %1, %0 \n"
114 " add %1, %2 \n"
115 " stex.w %1, (%3) \n"
116 " bez %1, 1b \n"
117 FULL_FENCE
118 "2:\n"
119 : "=&r" (prev), "=&r" (tmp)
120 : "r" (a), "r" (&v->counter), "r" (u)
121 : "memory");
122
123 return prev;
124}
125#define arch_atomic_fetch_add_unless arch_atomic_fetch_add_unless
126
127static __always_inline bool
128arch_atomic_inc_unless_negative(atomic_t *v)
129{
130 int rc, tmp;
131
132 __asm__ __volatile__ (
133 RELEASE_FENCE
134 "1: ldex.w %0, (%2) \n"
135 " movi %1, 0 \n"
136 " blz %0, 2f \n"
137 " movi %1, 1 \n"
138 " addi %0, 1 \n"
139 " stex.w %0, (%2) \n"
140 " bez %0, 1b \n"
141 FULL_FENCE
142 "2:\n"
143 : "=&r" (tmp), "=&r" (rc)
144 : "r" (&v->counter)
145 : "memory");
146
147 return tmp ? true : false;
148
149}
150#define arch_atomic_inc_unless_negative arch_atomic_inc_unless_negative
151
152static __always_inline bool
153arch_atomic_dec_unless_positive(atomic_t *v)
154{
155 int rc, tmp;
156
157 __asm__ __volatile__ (
158 RELEASE_FENCE
159 "1: ldex.w %0, (%2) \n"
160 " movi %1, 0 \n"
161 " bhz %0, 2f \n"
162 " movi %1, 1 \n"
163 " subi %0, 1 \n"
164 " stex.w %0, (%2) \n"
165 " bez %0, 1b \n"
166 FULL_FENCE
167 "2:\n"
168 : "=&r" (tmp), "=&r" (rc)
169 : "r" (&v->counter)
170 : "memory");
171
172 return tmp ? true : false;
173}
174#define arch_atomic_dec_unless_positive arch_atomic_dec_unless_positive
175
176static __always_inline int
177arch_atomic_dec_if_positive(atomic_t *v)
178{
179 int dec, tmp;
180
181 __asm__ __volatile__ (
182 RELEASE_FENCE
183 "1: ldex.w %0, (%2) \n"
184 " subi %1, %0, 1 \n"
185 " blz %1, 2f \n"
186 " stex.w %1, (%2) \n"
187 " bez %1, 1b \n"
188 FULL_FENCE
189 "2:\n"
190 : "=&r" (dec), "=&r" (tmp)
191 : "r" (&v->counter)
192 : "memory");
193
194 return dec - 1;
195}
196#define arch_atomic_dec_if_positive arch_atomic_dec_if_positive
197
198#else
199#include <asm-generic/atomic.h>
200#endif
201
202#endif /* __ASM_CSKY_ATOMIC_H */