This source file includes following definitions.
- arch_spin_lock
- arch_spin_trylock
- arch_spin_unlock
- arch_spin_value_unlocked
- arch_spin_is_locked
- arch_spin_is_contended
- arch_spin_lock
- arch_spin_unlock
- arch_spin_trylock
- arch_read_lock
- arch_read_unlock
- arch_read_trylock
- arch_write_lock
- arch_write_unlock
- arch_write_trylock
1
2
3 #ifndef __ASM_CSKY_SPINLOCK_H
4 #define __ASM_CSKY_SPINLOCK_H
5
6 #include <linux/spinlock_types.h>
7 #include <asm/barrier.h>
8
9 #ifdef CONFIG_QUEUED_RWLOCKS
10
11
12
13
14 static inline void arch_spin_lock(arch_spinlock_t *lock)
15 {
16 arch_spinlock_t lockval;
17 u32 ticket_next = 1 << TICKET_NEXT;
18 u32 *p = &lock->lock;
19 u32 tmp;
20
21 asm volatile (
22 "1: ldex.w %0, (%2) \n"
23 " mov %1, %0 \n"
24 " add %0, %3 \n"
25 " stex.w %0, (%2) \n"
26 " bez %0, 1b \n"
27 : "=&r" (tmp), "=&r" (lockval)
28 : "r"(p), "r"(ticket_next)
29 : "cc");
30
31 while (lockval.tickets.next != lockval.tickets.owner)
32 lockval.tickets.owner = READ_ONCE(lock->tickets.owner);
33
34 smp_mb();
35 }
36
37 static inline int arch_spin_trylock(arch_spinlock_t *lock)
38 {
39 u32 tmp, contended, res;
40 u32 ticket_next = 1 << TICKET_NEXT;
41 u32 *p = &lock->lock;
42
43 do {
44 asm volatile (
45 " ldex.w %0, (%3) \n"
46 " movi %2, 1 \n"
47 " rotli %1, %0, 16 \n"
48 " cmpne %1, %0 \n"
49 " bt 1f \n"
50 " movi %2, 0 \n"
51 " add %0, %0, %4 \n"
52 " stex.w %0, (%3) \n"
53 "1: \n"
54 : "=&r" (res), "=&r" (tmp), "=&r" (contended)
55 : "r"(p), "r"(ticket_next)
56 : "cc");
57 } while (!res);
58
59 if (!contended)
60 smp_mb();
61
62 return !contended;
63 }
64
65 static inline void arch_spin_unlock(arch_spinlock_t *lock)
66 {
67 smp_mb();
68 WRITE_ONCE(lock->tickets.owner, lock->tickets.owner + 1);
69 }
70
71 static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
72 {
73 return lock.tickets.owner == lock.tickets.next;
74 }
75
76 static inline int arch_spin_is_locked(arch_spinlock_t *lock)
77 {
78 return !arch_spin_value_unlocked(READ_ONCE(*lock));
79 }
80
81 static inline int arch_spin_is_contended(arch_spinlock_t *lock)
82 {
83 struct __raw_tickets tickets = READ_ONCE(lock->tickets);
84
85 return (tickets.next - tickets.owner) > 1;
86 }
87 #define arch_spin_is_contended arch_spin_is_contended
88
89 #include <asm/qrwlock.h>
90
91
92 #define smp_mb__after_spinlock() smp_mb()
93
94 #else
95
96
97
98
99 static inline void arch_spin_lock(arch_spinlock_t *lock)
100 {
101 u32 *p = &lock->lock;
102 u32 tmp;
103
104 asm volatile (
105 "1: ldex.w %0, (%1) \n"
106 " bnez %0, 1b \n"
107 " movi %0, 1 \n"
108 " stex.w %0, (%1) \n"
109 " bez %0, 1b \n"
110 : "=&r" (tmp)
111 : "r"(p)
112 : "cc");
113 smp_mb();
114 }
115
116 static inline void arch_spin_unlock(arch_spinlock_t *lock)
117 {
118 smp_mb();
119 WRITE_ONCE(lock->lock, 0);
120 }
121
122 static inline int arch_spin_trylock(arch_spinlock_t *lock)
123 {
124 u32 *p = &lock->lock;
125 u32 tmp;
126
127 asm volatile (
128 "1: ldex.w %0, (%1) \n"
129 " bnez %0, 2f \n"
130 " movi %0, 1 \n"
131 " stex.w %0, (%1) \n"
132 " bez %0, 1b \n"
133 " movi %0, 0 \n"
134 "2: \n"
135 : "=&r" (tmp)
136 : "r"(p)
137 : "cc");
138
139 if (!tmp)
140 smp_mb();
141
142 return !tmp;
143 }
144
145 #define arch_spin_is_locked(x) (READ_ONCE((x)->lock) != 0)
146
147
148
149
150 static inline void arch_read_lock(arch_rwlock_t *lock)
151 {
152 u32 *p = &lock->lock;
153 u32 tmp;
154
155 asm volatile (
156 "1: ldex.w %0, (%1) \n"
157 " blz %0, 1b \n"
158 " addi %0, 1 \n"
159 " stex.w %0, (%1) \n"
160 " bez %0, 1b \n"
161 : "=&r" (tmp)
162 : "r"(p)
163 : "cc");
164 smp_mb();
165 }
166
167 static inline void arch_read_unlock(arch_rwlock_t *lock)
168 {
169 u32 *p = &lock->lock;
170 u32 tmp;
171
172 smp_mb();
173 asm volatile (
174 "1: ldex.w %0, (%1) \n"
175 " subi %0, 1 \n"
176 " stex.w %0, (%1) \n"
177 " bez %0, 1b \n"
178 : "=&r" (tmp)
179 : "r"(p)
180 : "cc");
181 }
182
183 static inline int arch_read_trylock(arch_rwlock_t *lock)
184 {
185 u32 *p = &lock->lock;
186 u32 tmp;
187
188 asm volatile (
189 "1: ldex.w %0, (%1) \n"
190 " blz %0, 2f \n"
191 " addi %0, 1 \n"
192 " stex.w %0, (%1) \n"
193 " bez %0, 1b \n"
194 " movi %0, 0 \n"
195 "2: \n"
196 : "=&r" (tmp)
197 : "r"(p)
198 : "cc");
199
200 if (!tmp)
201 smp_mb();
202
203 return !tmp;
204 }
205
206
207
208
209 static inline void arch_write_lock(arch_rwlock_t *lock)
210 {
211 u32 *p = &lock->lock;
212 u32 tmp;
213
214 asm volatile (
215 "1: ldex.w %0, (%1) \n"
216 " bnez %0, 1b \n"
217 " subi %0, 1 \n"
218 " stex.w %0, (%1) \n"
219 " bez %0, 1b \n"
220 : "=&r" (tmp)
221 : "r"(p)
222 : "cc");
223 smp_mb();
224 }
225
226 static inline void arch_write_unlock(arch_rwlock_t *lock)
227 {
228 smp_mb();
229 WRITE_ONCE(lock->lock, 0);
230 }
231
232 static inline int arch_write_trylock(arch_rwlock_t *lock)
233 {
234 u32 *p = &lock->lock;
235 u32 tmp;
236
237 asm volatile (
238 "1: ldex.w %0, (%1) \n"
239 " bnez %0, 2f \n"
240 " subi %0, 1 \n"
241 " stex.w %0, (%1) \n"
242 " bez %0, 1b \n"
243 " movi %0, 0 \n"
244 "2: \n"
245 : "=&r" (tmp)
246 : "r"(p)
247 : "cc");
248
249 if (!tmp)
250 smp_mb();
251
252 return !tmp;
253 }
254
255 #endif
256 #endif