at v2.6.13 202 lines 4.4 kB view raw
1/* $Id: debuglocks.c,v 1.11 2001/09/20 00:35:31 davem Exp $ 2 * debuglocks.c: Debugging versions of SMP locking primitives. 3 * 4 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) 5 * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au) 6 */ 7 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> 14 15#ifdef CONFIG_SMP 16 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. 21 * 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. 24 */ 25 26#define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A)); 27 28static inline void show(char *str, spinlock_t *lock, unsigned long caller) 29{ 30 int cpu = smp_processor_id(); 31 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); 34} 35 36static inline void show_read(char *str, rwlock_t *lock, unsigned long caller) 37{ 38 int cpu = smp_processor_id(); 39 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); 42} 43 44static inline void show_write(char *str, rwlock_t *lock, unsigned long caller) 45{ 46 int cpu = smp_processor_id(); 47 int i; 48 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); 51 52 for(i = 0; i < NR_CPUS; i++) 53 printk(" reader[%d]=%08lx", i, lock->reader_pc[i]); 54 55 printk("\n"); 56} 57 58#undef INIT_STUCK 59#define INIT_STUCK 100000000 60 61void _do_spin_lock(spinlock_t *lock, char *str) 62{ 63 unsigned long caller; 64 unsigned long val; 65 int cpu = smp_processor_id(); 66 int stuck = INIT_STUCK; 67 68 STORE_CALLER(caller); 69 70again: 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; 77 } 78 barrier(); 79 } 80 goto again; 81 } 82 lock->owner_pc = (cpu & 3) | (caller & ~3); 83} 84 85int _spin_trylock(spinlock_t *lock) 86{ 87 unsigned long val; 88 unsigned long caller; 89 int cpu = smp_processor_id(); 90 91 STORE_CALLER(caller); 92 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); 97 } 98 return val == 0; 99} 100 101void _do_spin_unlock(spinlock_t *lock) 102{ 103 lock->owner_pc = 0; 104 barrier(); 105 lock->lock = 0; 106} 107 108void _do_read_lock(rwlock_t *rw, char *str) 109{ 110 unsigned long caller; 111 unsigned long val; 112 int cpu = smp_processor_id(); 113 int stuck = INIT_STUCK; 114 115 STORE_CALLER(caller); 116 117wlock_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; 124 } 125 barrier(); 126 } 127 goto wlock_again; 128 } 129 130 rw->reader_pc[cpu] = caller; 131 barrier(); 132 rw->lock++; 133} 134 135void _do_read_unlock(rwlock_t *rw, char *str) 136{ 137 unsigned long caller; 138 unsigned long val; 139 int cpu = smp_processor_id(); 140 int stuck = INIT_STUCK; 141 142 STORE_CALLER(caller); 143 144wlock_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; 151 } 152 barrier(); 153 } 154 goto wlock_again; 155 } 156 157 rw->reader_pc[cpu] = 0; 158 barrier(); 159 rw->lock -= 0x1ff; 160} 161 162void _do_write_lock(rwlock_t *rw, char *str) 163{ 164 unsigned long caller; 165 unsigned long val; 166 int cpu = smp_processor_id(); 167 int stuck = INIT_STUCK; 168 169 STORE_CALLER(caller); 170 171wlock_again: 172 __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock))); 173 if(val) { 174wlock_wait: 175 while(rw->lock) { 176 if (!--stuck) { 177 show_write(str, rw, caller); 178 stuck = INIT_STUCK; 179 } 180 barrier(); 181 } 182 goto wlock_again; 183 } 184 185 if (rw->lock & ~0xff) { 186 *(((unsigned char *)&rw->lock)+3) = 0; 187 barrier(); 188 goto wlock_wait; 189 } 190 191 barrier(); 192 rw->owner_pc = (cpu & 3) | (caller & ~3); 193} 194 195void _do_write_unlock(rwlock_t *rw) 196{ 197 rw->owner_pc = 0; 198 barrier(); 199 rw->lock = 0; 200} 201 202#endif /* SMP */