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)
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 #include <linux/threads.h> /* For NR_CPUS */
11 #include <linux/spinlock.h>
13 #include <asm/system.h>
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();
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
]);
59 #define INIT_STUCK 100000000
61 void _do_spin_lock(spinlock_t
*lock
, char *str
)
65 int cpu
= smp_processor_id();
66 int stuck
= INIT_STUCK
;
71 __asm__
__volatile__("ldstub [%1], %0" : "=r" (val
) : "r" (&(lock
->lock
)));
75 show(str
, lock
, caller
);
82 lock
->owner_pc
= (cpu
& 3) | (caller
& ~3);
85 int _spin_trylock(spinlock_t
*lock
)
89 int cpu
= smp_processor_id();
93 __asm__
__volatile__("ldstub [%1], %0" : "=r" (val
) : "r" (&(lock
->lock
)));
95 /* We got it, record our identity for debugging. */
96 lock
->owner_pc
= (cpu
& 3) | (caller
& ~3);
101 void _do_spin_unlock(spinlock_t
*lock
)
108 void _do_read_lock(rwlock_t
*rw
, char *str
)
110 unsigned long caller
;
112 int cpu
= smp_processor_id();
113 int stuck
= INIT_STUCK
;
115 STORE_CALLER(caller
);
118 __asm__
__volatile__("ldstub [%1 + 3], %0" : "=r" (val
) : "r" (&(rw
->lock
)));
120 while(rw
->lock
& 0xff) {
122 show_read(str
, rw
, caller
);
130 rw
->reader_pc
[cpu
] = caller
;
135 void _do_read_unlock(rwlock_t
*rw
, char *str
)
137 unsigned long caller
;
139 int cpu
= smp_processor_id();
140 int stuck
= INIT_STUCK
;
142 STORE_CALLER(caller
);
145 __asm__
__volatile__("ldstub [%1 + 3], %0" : "=r" (val
) : "r" (&(rw
->lock
)));
147 while(rw
->lock
& 0xff) {
149 show_read(str
, rw
, caller
);
157 rw
->reader_pc
[cpu
] = 0;
162 void _do_write_lock(rwlock_t
*rw
, char *str
)
164 unsigned long caller
;
166 int cpu
= smp_processor_id();
167 int stuck
= INIT_STUCK
;
169 STORE_CALLER(caller
);
172 __asm__
__volatile__("ldstub [%1 + 3], %0" : "=r" (val
) : "r" (&(rw
->lock
)));
177 show_write(str
, rw
, caller
);
185 if (rw
->lock
& ~0xff) {
186 *(((unsigned char *)&rw
->lock
)+3) = 0;
192 rw
->owner_pc
= (cpu
& 3) | (caller
& ~3);
195 void _do_write_unlock(rwlock_t
*rw
)