]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - arch/sparc64/lib/debuglocks.c
1 /* $Id: debuglocks.c,v 1.9 2001/11/17 00:10:48 davem Exp $
2 * debuglocks.c: Debugging versions of SMP locking primitives.
4 * Copyright (C) 1998 David S. Miller (davem@redhat.com)
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>
15 static inline void show (char *str
, spinlock_t
*lock
, unsigned long caller
)
17 int cpu
= smp_processor_id();
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
);
24 static inline void show_read (char *str
, rwlock_t
*lock
, unsigned long caller
)
26 int cpu
= smp_processor_id();
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
);
33 static inline void show_write (char *str
, rwlock_t
*lock
, unsigned long caller
)
35 int cpu
= smp_processor_id();
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
);
43 for (i
= 0; i
< NR_CPUS
; i
++)
44 if (lock
->reader_pc
[i
])
45 printk(" %d[%08x]", i
, lock
->reader_pc
[i
]);
50 #define INIT_STUCK 100000000
52 void _do_spin_lock(spinlock_t
*lock
, char *str
, unsigned long caller
)
55 int stuck
= INIT_STUCK
;
60 __asm__
__volatile__("ldstub [%1], %0"
64 membar_storeload_storestore();
69 show(str
, lock
, caller
);
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
);
84 int _do_spin_trylock(spinlock_t
*lock
, unsigned long caller
)
89 __asm__
__volatile__("ldstub [%1], %0"
93 membar_storeload_storestore();
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
);
106 void _do_spin_unlock(spinlock_t
*lock
)
109 lock
->owner_cpu
= NO_PROC_ID
;
110 membar_storestore_loadstore();
112 current
->thread
.smp_lock_count
--;
115 /* Keep INIT_STUCK the same... */
117 void _do_read_lock(rwlock_t
*rw
, char *str
, unsigned long caller
)
120 int stuck
= INIT_STUCK
;
125 /* Wait for any writer to go away. */
126 while (((long)(rw
->lock
)) < 0) {
129 show_read(str
, rw
, caller
);
134 /* Try once to increment the counter. */
135 __asm__
__volatile__(
137 " brlz,a,pn %%g1, 2f\n"
139 " add %%g1, 1, %%g7\n"
140 " casx [%0], %%g1, %%g7\n"
141 " sub %%g1, %%g7, %0\n"
144 : "g1", "g7", "memory");
145 membar_storeload_storestore();
148 rw
->reader_pc
[cpu
] = ((unsigned int)caller
);
149 current
->thread
.smp_lock_count
++;
150 current
->thread
.smp_lock_pc
= ((unsigned int)caller
);
155 void _do_read_unlock(rwlock_t
*rw
, char *str
, unsigned long caller
)
158 int stuck
= INIT_STUCK
;
162 /* Drop our identity _first_. */
163 rw
->reader_pc
[cpu
] = 0;
164 current
->thread
.smp_lock_count
--;
166 /* Spin trying to decrement the counter using casx. */
167 __asm__
__volatile__(
168 " membar #StoreLoad | #LoadLoad\n"
170 " sub %%g1, 1, %%g7\n"
171 " casx [%0], %%g1, %%g7\n"
172 " membar #StoreLoad | #StoreStore\n"
173 " sub %%g1, %%g7, %0\n"
176 : "g1", "g7", "memory");
180 show_read(str
, rw
, caller
);
189 void _do_write_lock(rwlock_t
*rw
, char *str
, unsigned long caller
)
192 int stuck
= INIT_STUCK
;
197 /* Spin while there is another writer. */
198 while (((long)rw
->lock
) < 0) {
201 show_write(str
, rw
, caller
);
207 /* Try to acuire the write bit. */
208 __asm__
__volatile__(
210 " sllx %%g3, 63, %%g3\n"
212 " brlz,pn %%g1, 1f\n"
213 " or %%g1, %%g3, %%g7\n"
214 " casx [%0], %%g1, %%g7\n"
215 " membar #StoreLoad | #StoreStore\n"
217 " sub %%g1, %%g7, %0\n"
221 : "g3", "g1", "g7", "memory");
223 /* We couldn't get the write bit. */
226 show_write(str
, rw
, caller
);
231 if ((rw
->lock
& ((1UL<<63)-1UL)) != 0UL) {
232 /* Readers still around, drop the write
233 * lock, spin, and try again.
237 show_write(str
, rw
, caller
);
240 __asm__
__volatile__(
242 " sllx %%g3, 63, %%g3\n"
243 "1: ldx [%0], %%g1\n"
244 " andn %%g1, %%g3, %%g7\n"
245 " casx [%0], %%g1, %%g7\n"
247 " membar #StoreLoad | #StoreStore\n"
248 " bne,pn %%xcc, 1b\n"
252 : "g3", "g1", "g7", "cc", "memory");
253 while(rw
->lock
!= 0) {
256 show_write(str
, rw
, caller
);
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
);
273 void _do_write_unlock(rwlock_t
*rw
, unsigned long caller
)
276 int stuck
= INIT_STUCK
;
279 /* Drop our identity _first_ */
281 rw
->writer_cpu
= NO_PROC_ID
;
282 current
->thread
.smp_lock_count
--;
284 __asm__
__volatile__(
285 " membar #StoreLoad | #LoadLoad\n"
287 " sllx %%g3, 63, %%g3\n"
289 " andn %%g1, %%g3, %%g7\n"
290 " casx [%0], %%g1, %%g7\n"
291 " membar #StoreLoad | #StoreStore\n"
292 " sub %%g1, %%g7, %0\n"
295 : "g3", "g1", "g7", "memory");
299 show_write("write_unlock", rw
, caller
);
306 int _do_write_trylock(rwlock_t
*rw
, char *str
, unsigned long caller
)
311 /* Try to acuire the write bit. */
312 __asm__
__volatile__(
314 " sllx %%g3, 63, %%g3\n"
316 " brlz,pn %%g1, 1f\n"
317 " or %%g1, %%g3, %%g7\n"
318 " casx [%0], %%g1, %%g7\n"
319 " membar #StoreLoad | #StoreStore\n"
321 " sub %%g1, %%g7, %0\n"
325 : "g3", "g1", "g7", "memory");
332 if ((rw
->lock
& ((1UL<<63)-1UL)) != 0UL) {
333 /* Readers still around, drop the write
334 * lock, return failure.
336 __asm__
__volatile__(
338 " sllx %%g3, 63, %%g3\n"
339 "1: ldx [%0], %%g1\n"
340 " andn %%g1, %%g3, %%g7\n"
341 " casx [%0], %%g1, %%g7\n"
343 " membar #StoreLoad | #StoreStore\n"
344 " bne,pn %%xcc, 1b\n"
348 : "g3", "g1", "g7", "cc", "memory");
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
);
366 #endif /* CONFIG_SMP */