Linux 2.6.13-rc4
[linux-2.6/next.git] / arch / sparc / lib / debuglocks.c
blobfb182352782c57fb344a1860a518bc72a2ca3e12
1 /* $Id: debuglocks.c,v 1.11 2001/09/20 00:35:31 davem Exp $
2 * debuglocks.c: Debugging versions of SMP locking primitives.
4 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au)
6 */
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 #include <linux/threads.h> /* For NR_CPUS */
11 #include <linux/spinlock.h>
12 #include <asm/psr.h>
13 #include <asm/system.h>
15 #ifdef CONFIG_SMP
17 /* Some notes on how these debugging routines work. When a lock is acquired
18 * an extra debugging member lock->owner_pc is set to the caller of the lock
19 * acquisition routine. Right before releasing a lock, the debugging program
20 * counter is cleared to zero.
22 * Furthermore, since PC's are 4 byte aligned on Sparc, we stuff the CPU
23 * number of the owner in the lowest two bits.
26 #define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A));
28 static inline void show(char *str, spinlock_t *lock, unsigned long caller)
30 int cpu = smp_processor_id();
32 printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str,
33 lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
36 static inline void show_read(char *str, rwlock_t *lock, unsigned long caller)
38 int cpu = smp_processor_id();
40 printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", str,
41 lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
44 static inline void show_write(char *str, rwlock_t *lock, unsigned long caller)
46 int cpu = smp_processor_id();
47 int i;
49 printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)", str,
50 lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
52 for(i = 0; i < NR_CPUS; i++)
53 printk(" reader[%d]=%08lx", i, lock->reader_pc[i]);
55 printk("\n");
58 #undef INIT_STUCK
59 #define INIT_STUCK 100000000
61 void _do_spin_lock(spinlock_t *lock, char *str)
63 unsigned long caller;
64 unsigned long val;
65 int cpu = smp_processor_id();
66 int stuck = INIT_STUCK;
68 STORE_CALLER(caller);
70 again:
71 __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
72 if(val) {
73 while(lock->lock) {
74 if (!--stuck) {
75 show(str, lock, caller);
76 stuck = INIT_STUCK;
78 barrier();
80 goto again;
82 lock->owner_pc = (cpu & 3) | (caller & ~3);
85 int _spin_trylock(spinlock_t *lock)
87 unsigned long val;
88 unsigned long caller;
89 int cpu = smp_processor_id();
91 STORE_CALLER(caller);
93 __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
94 if(!val) {
95 /* We got it, record our identity for debugging. */
96 lock->owner_pc = (cpu & 3) | (caller & ~3);
98 return val == 0;
101 void _do_spin_unlock(spinlock_t *lock)
103 lock->owner_pc = 0;
104 barrier();
105 lock->lock = 0;
108 void _do_read_lock(rwlock_t *rw, char *str)
110 unsigned long caller;
111 unsigned long val;
112 int cpu = smp_processor_id();
113 int stuck = INIT_STUCK;
115 STORE_CALLER(caller);
117 wlock_again:
118 __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
119 if(val) {
120 while(rw->lock & 0xff) {
121 if (!--stuck) {
122 show_read(str, rw, caller);
123 stuck = INIT_STUCK;
125 barrier();
127 goto wlock_again;
130 rw->reader_pc[cpu] = caller;
131 barrier();
132 rw->lock++;
135 void _do_read_unlock(rwlock_t *rw, char *str)
137 unsigned long caller;
138 unsigned long val;
139 int cpu = smp_processor_id();
140 int stuck = INIT_STUCK;
142 STORE_CALLER(caller);
144 wlock_again:
145 __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
146 if(val) {
147 while(rw->lock & 0xff) {
148 if (!--stuck) {
149 show_read(str, rw, caller);
150 stuck = INIT_STUCK;
152 barrier();
154 goto wlock_again;
157 rw->reader_pc[cpu] = 0;
158 barrier();
159 rw->lock -= 0x1ff;
162 void _do_write_lock(rwlock_t *rw, char *str)
164 unsigned long caller;
165 unsigned long val;
166 int cpu = smp_processor_id();
167 int stuck = INIT_STUCK;
169 STORE_CALLER(caller);
171 wlock_again:
172 __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
173 if(val) {
174 wlock_wait:
175 while(rw->lock) {
176 if (!--stuck) {
177 show_write(str, rw, caller);
178 stuck = INIT_STUCK;
180 barrier();
182 goto wlock_again;
185 if (rw->lock & ~0xff) {
186 *(((unsigned char *)&rw->lock)+3) = 0;
187 barrier();
188 goto wlock_wait;
191 barrier();
192 rw->owner_pc = (cpu & 3) | (caller & ~3);
195 void _do_write_unlock(rwlock_t *rw)
197 rw->owner_pc = 0;
198 barrier();
199 rw->lock = 0;
202 #endif /* SMP */