Import 2.3.18pre1
[davej-history.git] / arch / sparc / lib / debuglocks.c
blobb362895ee5ea4941ddf498bd016d5024caf86867
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)
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 /* 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();
50 int i;
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]);
58 printk("\n");
61 #undef INIT_STUCK
62 #define INIT_STUCK 100000000
64 void _do_spin_lock(spinlock_t *lock, char *str)
66 unsigned long caller;
67 unsigned long val;
68 int cpu = smp_processor_id();
69 int stuck = INIT_STUCK;
71 STORE_CALLER(caller);
73 again:
74 __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
75 if(val) {
76 while(lock->lock) {
77 if (!--stuck) {
78 show(str, lock, caller);
79 stuck = INIT_STUCK;
81 barrier();
83 goto again;
85 lock->owner_pc = (cpu & 3) | (caller & ~3);
88 int _spin_trylock(spinlock_t *lock)
90 unsigned long val;
91 unsigned long caller;
92 int cpu = smp_processor_id();
94 STORE_CALLER(caller);
96 __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
97 if(!val) {
98 /* We got it, record our identity for debugging. */
99 lock->owner_pc = (cpu & 3) | (caller & ~3);
101 return val == 0;
104 void _do_spin_unlock(spinlock_t *lock)
106 lock->owner_pc = 0;
107 barrier();
108 lock->lock = 0;
111 void _do_read_lock(rwlock_t *rw, char *str)
113 unsigned long caller;
114 unsigned long val;
115 int cpu = smp_processor_id();
116 int stuck = INIT_STUCK;
118 STORE_CALLER(caller);
120 wlock_again:
121 __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
122 if(val) {
123 while(rw->lock & 0xff) {
124 if (!--stuck) {
125 show_read(str, rw, caller);
126 stuck = INIT_STUCK;
128 barrier();
130 goto wlock_again;
133 rw->reader_pc[cpu] = caller;
134 barrier();
135 rw->lock++;
138 void _do_read_unlock(rwlock_t *rw, char *str)
140 unsigned long caller;
141 unsigned long val;
142 int cpu = smp_processor_id();
143 int stuck = INIT_STUCK;
145 STORE_CALLER(caller);
147 wlock_again:
148 __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
149 if(val) {
150 while(rw->lock & 0xff) {
151 if (!--stuck) {
152 show_read(str, rw, caller);
153 stuck = INIT_STUCK;
155 barrier();
157 goto wlock_again;
160 rw->reader_pc[cpu] = 0;
161 barrier();
162 rw->lock -= 0x1ff;
165 void _do_write_lock(rwlock_t *rw, char *str)
167 unsigned long caller;
168 unsigned long val;
169 int cpu = smp_processor_id();
170 int stuck = INIT_STUCK;
172 STORE_CALLER(caller);
174 wlock_again:
175 __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
176 if(val) {
177 wlock_wait:
178 while(rw->lock) {
179 if (!--stuck) {
180 show_write(str, rw, caller);
181 stuck = INIT_STUCK;
183 barrier();
185 goto wlock_again;
188 if (rw->lock & ~0xff) {
189 *(((unsigned char *)&rw->lock)+3) = 0;
190 barrier();
191 goto wlock_wait;
194 barrier();
195 rw->owner_pc = (cpu & 3) | (caller & ~3);
198 void _do_write_unlock(rwlock_t *rw)
200 rw->owner_pc = 0;
201 barrier();
202 rw->lock = 0;
205 #endif /* SPIN_LOCK_DEBUG */