1 /* $Id: debuglocks.c,v 1.9 1999/08/14 03:51:39 anton 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>
15 /* To enable this code, just define SPIN_LOCK_DEBUG in asm/spinlock.h */
16 #ifdef SPIN_LOCK_DEBUG
18 /* Some notes on how these debugging routines work. When a lock is acquired
19 * an extra debugging member lock->owner_pc is set to the caller of the lock
20 * acquisition routine. Right before releasing a lock, the debugging program
21 * counter is cleared to zero.
23 * Furthermore, since PC's are 4 byte aligned on Sparc, we stuff the CPU
24 * number of the owner in the lowest two bits.
27 #define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A));
29 static inline void show(char *str
, spinlock_t
*lock
, unsigned long caller
)
31 int cpu
= smp_processor_id();
32 extern spinlock_t console_lock
;
34 if (lock
!= &console_lock
)
35 printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str
,
36 lock
, cpu
, caller
, lock
->owner_pc
& ~3, lock
->owner_pc
& 3);
39 static inline void show_read(char *str
, rwlock_t
*lock
, unsigned long caller
)
41 int cpu
= smp_processor_id();
43 printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", str
,
44 lock
, cpu
, caller
, lock
->owner_pc
& ~3, lock
->owner_pc
& 3);
47 static inline void show_write(char *str
, rwlock_t
*lock
, unsigned long caller
)
49 int cpu
= smp_processor_id();
52 printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)", str
,
53 lock
, cpu
, caller
, lock
->owner_pc
& ~3, lock
->owner_pc
& 3);
55 for(i
= 0; i
< NR_CPUS
; i
++)
56 printk(" reader[%d]=%08lx", i
, lock
->reader_pc
[i
]);
62 #define INIT_STUCK 100000000
64 void _do_spin_lock(spinlock_t
*lock
, char *str
)
68 int cpu
= smp_processor_id();
69 int stuck
= INIT_STUCK
;
74 __asm__
__volatile__("ldstub [%1], %0" : "=r" (val
) : "r" (&(lock
->lock
)));
78 show(str
, lock
, caller
);
85 lock
->owner_pc
= (cpu
& 3) | (caller
& ~3);
88 int _spin_trylock(spinlock_t
*lock
)
92 int cpu
= smp_processor_id();
96 __asm__
__volatile__("ldstub [%1], %0" : "=r" (val
) : "r" (&(lock
->lock
)));
98 /* We got it, record our identity for debugging. */
99 lock
->owner_pc
= (cpu
& 3) | (caller
& ~3);
104 void _do_spin_unlock(spinlock_t
*lock
)
111 void _do_read_lock(rwlock_t
*rw
, char *str
)
113 unsigned long caller
;
115 int cpu
= smp_processor_id();
116 int stuck
= INIT_STUCK
;
118 STORE_CALLER(caller
);
121 __asm__
__volatile__("ldstub [%1 + 3], %0" : "=r" (val
) : "r" (&(rw
->lock
)));
123 while(rw
->lock
& 0xff) {
125 show_read(str
, rw
, caller
);
133 rw
->reader_pc
[cpu
] = caller
;
138 void _do_read_unlock(rwlock_t
*rw
, char *str
)
140 unsigned long caller
;
142 int cpu
= smp_processor_id();
143 int stuck
= INIT_STUCK
;
145 STORE_CALLER(caller
);
148 __asm__
__volatile__("ldstub [%1 + 3], %0" : "=r" (val
) : "r" (&(rw
->lock
)));
150 while(rw
->lock
& 0xff) {
152 show_read(str
, rw
, caller
);
160 rw
->reader_pc
[cpu
] = 0;
165 void _do_write_lock(rwlock_t
*rw
, char *str
)
167 unsigned long caller
;
169 int cpu
= smp_processor_id();
170 int stuck
= INIT_STUCK
;
172 STORE_CALLER(caller
);
175 __asm__
__volatile__("ldstub [%1 + 3], %0" : "=r" (val
) : "r" (&(rw
->lock
)));
180 show_write(str
, rw
, caller
);
188 if (rw
->lock
& ~0xff) {
189 *(((unsigned char *)&rw
->lock
)+3) = 0;
195 rw
->owner_pc
= (cpu
& 3) | (caller
& ~3);
198 void _do_write_unlock(rwlock_t
*rw
)
205 #endif /* SPIN_LOCK_DEBUG */