[SPARC64]: More fully work around Spitfire Errata 51.
[deliverable/linux.git] / arch / sparc64 / lib / debuglocks.c
CommitLineData
1da177e4
LT
1/* $Id: debuglocks.c,v 1.9 2001/11/17 00:10:48 davem Exp $
2 * debuglocks.c: Debugging versions of SMP locking primitives.
3 *
4 * Copyright (C) 1998 David S. Miller (davem@redhat.com)
5 */
6
7#include <linux/config.h>
8#include <linux/kernel.h>
9#include <linux/sched.h>
10#include <linux/spinlock.h>
11#include <asm/system.h>
12
13#ifdef CONFIG_SMP
14
1da177e4
LT
15static inline void show (char *str, spinlock_t *lock, unsigned long caller)
16{
17 int cpu = smp_processor_id();
18
19 printk("%s(%p) CPU#%d stuck at %08x, owner PC(%08x):CPU(%x)\n",
20 str, lock, cpu, (unsigned int) caller,
21 lock->owner_pc, lock->owner_cpu);
22}
23
24static inline void show_read (char *str, rwlock_t *lock, unsigned long caller)
25{
26 int cpu = smp_processor_id();
27
28 printk("%s(%p) CPU#%d stuck at %08x, writer PC(%08x):CPU(%x)\n",
29 str, lock, cpu, (unsigned int) caller,
30 lock->writer_pc, lock->writer_cpu);
31}
32
33static inline void show_write (char *str, rwlock_t *lock, unsigned long caller)
34{
35 int cpu = smp_processor_id();
36 int i;
37
38 printk("%s(%p) CPU#%d stuck at %08x\n",
39 str, lock, cpu, (unsigned int) caller);
40 printk("Writer: PC(%08x):CPU(%x)\n",
41 lock->writer_pc, lock->writer_cpu);
42 printk("Readers:");
43 for (i = 0; i < NR_CPUS; i++)
44 if (lock->reader_pc[i])
45 printk(" %d[%08x]", i, lock->reader_pc[i]);
46 printk("\n");
47}
48
49#undef INIT_STUCK
50#define INIT_STUCK 100000000
51
442464a5 52void _do_spin_lock(spinlock_t *lock, char *str, unsigned long caller)
1da177e4 53{
442464a5 54 unsigned long val;
1da177e4
LT
55 int stuck = INIT_STUCK;
56 int cpu = get_cpu();
57 int shown = 0;
58
1da177e4
LT
59again:
60 __asm__ __volatile__("ldstub [%1], %0"
61 : "=r" (val)
62 : "r" (&(lock->lock))
63 : "memory");
4f07118f 64 membar_storeload_storestore();
1da177e4
LT
65 if (val) {
66 while (lock->lock) {
67 if (!--stuck) {
68 if (shown++ <= 2)
69 show(str, lock, caller);
70 stuck = INIT_STUCK;
71 }
4f07118f 72 rmb();
1da177e4
LT
73 }
74 goto again;
75 }
76 lock->owner_pc = ((unsigned int)caller);
77 lock->owner_cpu = cpu;
78 current->thread.smp_lock_count++;
79 current->thread.smp_lock_pc = ((unsigned int)caller);
80
81 put_cpu();
82}
83
442464a5 84int _do_spin_trylock(spinlock_t *lock, unsigned long caller)
1da177e4 85{
442464a5 86 unsigned long val;
1da177e4
LT
87 int cpu = get_cpu();
88
1da177e4
LT
89 __asm__ __volatile__("ldstub [%1], %0"
90 : "=r" (val)
91 : "r" (&(lock->lock))
92 : "memory");
4f07118f 93 membar_storeload_storestore();
1da177e4
LT
94 if (!val) {
95 lock->owner_pc = ((unsigned int)caller);
96 lock->owner_cpu = cpu;
97 current->thread.smp_lock_count++;
98 current->thread.smp_lock_pc = ((unsigned int)caller);
99 }
100
101 put_cpu();
102
103 return val == 0;
104}
105
106void _do_spin_unlock(spinlock_t *lock)
107{
108 lock->owner_pc = 0;
109 lock->owner_cpu = NO_PROC_ID;
4f07118f 110 membar_storestore_loadstore();
1da177e4
LT
111 lock->lock = 0;
112 current->thread.smp_lock_count--;
113}
114
115/* Keep INIT_STUCK the same... */
116
442464a5 117void _do_read_lock(rwlock_t *rw, char *str, unsigned long caller)
1da177e4 118{
442464a5 119 unsigned long val;
1da177e4
LT
120 int stuck = INIT_STUCK;
121 int cpu = get_cpu();
122 int shown = 0;
123
1da177e4
LT
124wlock_again:
125 /* Wait for any writer to go away. */
126 while (((long)(rw->lock)) < 0) {
127 if (!--stuck) {
128 if (shown++ <= 2)
129 show_read(str, rw, caller);
130 stuck = INIT_STUCK;
131 }
4f07118f 132 rmb();
1da177e4
LT
133 }
134 /* Try once to increment the counter. */
135 __asm__ __volatile__(
136" ldx [%0], %%g1\n"
137" brlz,a,pn %%g1, 2f\n"
138" mov 1, %0\n"
139" add %%g1, 1, %%g7\n"
140" casx [%0], %%g1, %%g7\n"
141" sub %%g1, %%g7, %0\n"
142"2:" : "=r" (val)
143 : "0" (&(rw->lock))
144 : "g1", "g7", "memory");
4f07118f 145 membar_storeload_storestore();
1da177e4
LT
146 if (val)
147 goto wlock_again;
148 rw->reader_pc[cpu] = ((unsigned int)caller);
149 current->thread.smp_lock_count++;
150 current->thread.smp_lock_pc = ((unsigned int)caller);
151
152 put_cpu();
153}
154
442464a5 155void _do_read_unlock(rwlock_t *rw, char *str, unsigned long caller)
1da177e4 156{
442464a5 157 unsigned long val;
1da177e4
LT
158 int stuck = INIT_STUCK;
159 int cpu = get_cpu();
160 int shown = 0;
161
1da177e4
LT
162 /* Drop our identity _first_. */
163 rw->reader_pc[cpu] = 0;
164 current->thread.smp_lock_count--;
165runlock_again:
166 /* Spin trying to decrement the counter using casx. */
167 __asm__ __volatile__(
168" membar #StoreLoad | #LoadLoad\n"
169" ldx [%0], %%g1\n"
170" sub %%g1, 1, %%g7\n"
171" casx [%0], %%g1, %%g7\n"
172" membar #StoreLoad | #StoreStore\n"
173" sub %%g1, %%g7, %0\n"
174 : "=r" (val)
175 : "0" (&(rw->lock))
176 : "g1", "g7", "memory");
177 if (val) {
178 if (!--stuck) {
179 if (shown++ <= 2)
180 show_read(str, rw, caller);
181 stuck = INIT_STUCK;
182 }
183 goto runlock_again;
184 }
185
186 put_cpu();
187}
188
442464a5 189void _do_write_lock(rwlock_t *rw, char *str, unsigned long caller)
1da177e4 190{
442464a5 191 unsigned long val;
1da177e4
LT
192 int stuck = INIT_STUCK;
193 int cpu = get_cpu();
194 int shown = 0;
195
1da177e4
LT
196wlock_again:
197 /* Spin while there is another writer. */
198 while (((long)rw->lock) < 0) {
199 if (!--stuck) {
200 if (shown++ <= 2)
201 show_write(str, rw, caller);
202 stuck = INIT_STUCK;
203 }
4f07118f 204 rmb();
1da177e4
LT
205 }
206
207 /* Try to acuire the write bit. */
208 __asm__ __volatile__(
209" mov 1, %%g3\n"
210" sllx %%g3, 63, %%g3\n"
211" ldx [%0], %%g1\n"
212" brlz,pn %%g1, 1f\n"
213" or %%g1, %%g3, %%g7\n"
214" casx [%0], %%g1, %%g7\n"
215" membar #StoreLoad | #StoreStore\n"
216" ba,pt %%xcc, 2f\n"
217" sub %%g1, %%g7, %0\n"
218"1: mov 1, %0\n"
219"2:" : "=r" (val)
220 : "0" (&(rw->lock))
221 : "g3", "g1", "g7", "memory");
222 if (val) {
223 /* We couldn't get the write bit. */
224 if (!--stuck) {
225 if (shown++ <= 2)
226 show_write(str, rw, caller);
227 stuck = INIT_STUCK;
228 }
229 goto wlock_again;
230 }
231 if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
232 /* Readers still around, drop the write
233 * lock, spin, and try again.
234 */
235 if (!--stuck) {
236 if (shown++ <= 2)
237 show_write(str, rw, caller);
238 stuck = INIT_STUCK;
239 }
240 __asm__ __volatile__(
241" mov 1, %%g3\n"
242" sllx %%g3, 63, %%g3\n"
243"1: ldx [%0], %%g1\n"
244" andn %%g1, %%g3, %%g7\n"
245" casx [%0], %%g1, %%g7\n"
246" cmp %%g1, %%g7\n"
b445e26c 247" membar #StoreLoad | #StoreStore\n"
1da177e4 248" bne,pn %%xcc, 1b\n"
b445e26c 249" nop"
1da177e4
LT
250 : /* no outputs */
251 : "r" (&(rw->lock))
252 : "g3", "g1", "g7", "cc", "memory");
253 while(rw->lock != 0) {
254 if (!--stuck) {
255 if (shown++ <= 2)
256 show_write(str, rw, caller);
257 stuck = INIT_STUCK;
258 }
4f07118f 259 rmb();
1da177e4
LT
260 }
261 goto wlock_again;
262 }
263
264 /* We have it, say who we are. */
265 rw->writer_pc = ((unsigned int)caller);
266 rw->writer_cpu = cpu;
267 current->thread.smp_lock_count++;
268 current->thread.smp_lock_pc = ((unsigned int)caller);
269
270 put_cpu();
271}
272
442464a5 273void _do_write_unlock(rwlock_t *rw, unsigned long caller)
1da177e4 274{
442464a5 275 unsigned long val;
1da177e4
LT
276 int stuck = INIT_STUCK;
277 int shown = 0;
278
1da177e4
LT
279 /* Drop our identity _first_ */
280 rw->writer_pc = 0;
281 rw->writer_cpu = NO_PROC_ID;
282 current->thread.smp_lock_count--;
283wlock_again:
284 __asm__ __volatile__(
285" membar #StoreLoad | #LoadLoad\n"
286" mov 1, %%g3\n"
287" sllx %%g3, 63, %%g3\n"
288" ldx [%0], %%g1\n"
289" andn %%g1, %%g3, %%g7\n"
290" casx [%0], %%g1, %%g7\n"
291" membar #StoreLoad | #StoreStore\n"
292" sub %%g1, %%g7, %0\n"
293 : "=r" (val)
294 : "0" (&(rw->lock))
295 : "g3", "g1", "g7", "memory");
296 if (val) {
297 if (!--stuck) {
298 if (shown++ <= 2)
299 show_write("write_unlock", rw, caller);
300 stuck = INIT_STUCK;
301 }
302 goto wlock_again;
303 }
304}
305
442464a5 306int _do_write_trylock(rwlock_t *rw, char *str, unsigned long caller)
1da177e4 307{
442464a5 308 unsigned long val;
1da177e4
LT
309 int cpu = get_cpu();
310
1da177e4
LT
311 /* Try to acuire the write bit. */
312 __asm__ __volatile__(
313" mov 1, %%g3\n"
314" sllx %%g3, 63, %%g3\n"
315" ldx [%0], %%g1\n"
316" brlz,pn %%g1, 1f\n"
317" or %%g1, %%g3, %%g7\n"
318" casx [%0], %%g1, %%g7\n"
319" membar #StoreLoad | #StoreStore\n"
320" ba,pt %%xcc, 2f\n"
321" sub %%g1, %%g7, %0\n"
322"1: mov 1, %0\n"
323"2:" : "=r" (val)
324 : "0" (&(rw->lock))
325 : "g3", "g1", "g7", "memory");
326
327 if (val) {
328 put_cpu();
329 return 0;
330 }
331
332 if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
333 /* Readers still around, drop the write
334 * lock, return failure.
335 */
336 __asm__ __volatile__(
337" mov 1, %%g3\n"
338" sllx %%g3, 63, %%g3\n"
339"1: ldx [%0], %%g1\n"
340" andn %%g1, %%g3, %%g7\n"
341" casx [%0], %%g1, %%g7\n"
342" cmp %%g1, %%g7\n"
b445e26c 343" membar #StoreLoad | #StoreStore\n"
1da177e4 344" bne,pn %%xcc, 1b\n"
b445e26c 345" nop"
1da177e4
LT
346 : /* no outputs */
347 : "r" (&(rw->lock))
348 : "g3", "g1", "g7", "cc", "memory");
349
350 put_cpu();
351
352 return 0;
353 }
354
355 /* We have it, say who we are. */
356 rw->writer_pc = ((unsigned int)caller);
357 rw->writer_cpu = cpu;
358 current->thread.smp_lock_count++;
359 current->thread.smp_lock_pc = ((unsigned int)caller);
360
361 put_cpu();
362
363 return 1;
364}
365
366#endif /* CONFIG_SMP */
This page took 0.061383 seconds and 5 git commands to generate.