at v2.6.15 5.9 kB view raw
1/* 2 * Copyright 2005, Red Hat, Inc., Ingo Molnar 3 * Released under the General Public License (GPL). 4 * 5 * This file contains the spinlock/rwlock implementations for 6 * DEBUG_SPINLOCK. 7 */ 8 9#include <linux/config.h> 10#include <linux/spinlock.h> 11#include <linux/interrupt.h> 12#include <linux/delay.h> 13 14static void spin_bug(spinlock_t *lock, const char *msg) 15{ 16 static long print_once = 1; 17 struct task_struct *owner = NULL; 18 19 if (xchg(&print_once, 0)) { 20 if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT) 21 owner = lock->owner; 22 printk("BUG: spinlock %s on CPU#%d, %s/%d\n", 23 msg, raw_smp_processor_id(), 24 current->comm, current->pid); 25 printk(" lock: %p, .magic: %08x, .owner: %s/%d, .owner_cpu: %d\n", 26 lock, lock->magic, 27 owner ? owner->comm : "<none>", 28 owner ? owner->pid : -1, 29 lock->owner_cpu); 30 dump_stack(); 31#ifdef CONFIG_SMP 32 /* 33 * We cannot continue on SMP: 34 */ 35// panic("bad locking"); 36#endif 37 } 38} 39 40#define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg) 41 42static inline void debug_spin_lock_before(spinlock_t *lock) 43{ 44 SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); 45 SPIN_BUG_ON(lock->owner == current, lock, "recursion"); 46 SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), 47 lock, "cpu recursion"); 48} 49 50static inline void debug_spin_lock_after(spinlock_t *lock) 51{ 52 lock->owner_cpu = raw_smp_processor_id(); 53 lock->owner = current; 54} 55 56static inline void debug_spin_unlock(spinlock_t *lock) 57{ 58 SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); 59 SPIN_BUG_ON(!spin_is_locked(lock), lock, "already unlocked"); 60 SPIN_BUG_ON(lock->owner != current, lock, "wrong owner"); 61 SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), 62 lock, "wrong CPU"); 63 lock->owner = SPINLOCK_OWNER_INIT; 64 lock->owner_cpu = -1; 65} 66 67static void __spin_lock_debug(spinlock_t *lock) 68{ 69 int print_once = 1; 70 u64 i; 71 72 for (;;) { 73 for (i = 0; i < loops_per_jiffy * HZ; i++) { 74 cpu_relax(); 75 if (__raw_spin_trylock(&lock->raw_lock)) 76 return; 77 } 78 /* lockup suspected: */ 79 if (print_once) { 80 print_once = 0; 81 printk("BUG: spinlock lockup on CPU#%d, %s/%d, %p\n", 82 raw_smp_processor_id(), current->comm, 83 current->pid, lock); 84 dump_stack(); 85 } 86 } 87} 88 89void _raw_spin_lock(spinlock_t *lock) 90{ 91 debug_spin_lock_before(lock); 92 if (unlikely(!__raw_spin_trylock(&lock->raw_lock))) 93 __spin_lock_debug(lock); 94 debug_spin_lock_after(lock); 95} 96 97int _raw_spin_trylock(spinlock_t *lock) 98{ 99 int ret = __raw_spin_trylock(&lock->raw_lock); 100 101 if (ret) 102 debug_spin_lock_after(lock); 103#ifndef CONFIG_SMP 104 /* 105 * Must not happen on UP: 106 */ 107 SPIN_BUG_ON(!ret, lock, "trylock failure on UP"); 108#endif 109 return ret; 110} 111 112void _raw_spin_unlock(spinlock_t *lock) 113{ 114 debug_spin_unlock(lock); 115 __raw_spin_unlock(&lock->raw_lock); 116} 117 118static void rwlock_bug(rwlock_t *lock, const char *msg) 119{ 120 static long print_once = 1; 121 122 if (xchg(&print_once, 0)) { 123 printk("BUG: rwlock %s on CPU#%d, %s/%d, %p\n", msg, 124 raw_smp_processor_id(), current->comm, 125 current->pid, lock); 126 dump_stack(); 127#ifdef CONFIG_SMP 128 /* 129 * We cannot continue on SMP: 130 */ 131 panic("bad locking"); 132#endif 133 } 134} 135 136#define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg) 137 138static void __read_lock_debug(rwlock_t *lock) 139{ 140 int print_once = 1; 141 u64 i; 142 143 for (;;) { 144 for (i = 0; i < loops_per_jiffy * HZ; i++) { 145 cpu_relax(); 146 if (__raw_read_trylock(&lock->raw_lock)) 147 return; 148 } 149 /* lockup suspected: */ 150 if (print_once) { 151 print_once = 0; 152 printk("BUG: read-lock lockup on CPU#%d, %s/%d, %p\n", 153 raw_smp_processor_id(), current->comm, 154 current->pid, lock); 155 dump_stack(); 156 } 157 } 158} 159 160void _raw_read_lock(rwlock_t *lock) 161{ 162 RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); 163 if (unlikely(!__raw_read_trylock(&lock->raw_lock))) 164 __read_lock_debug(lock); 165} 166 167int _raw_read_trylock(rwlock_t *lock) 168{ 169 int ret = __raw_read_trylock(&lock->raw_lock); 170 171#ifndef CONFIG_SMP 172 /* 173 * Must not happen on UP: 174 */ 175 RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); 176#endif 177 return ret; 178} 179 180void _raw_read_unlock(rwlock_t *lock) 181{ 182 RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); 183 __raw_read_unlock(&lock->raw_lock); 184} 185 186static inline void debug_write_lock_before(rwlock_t *lock) 187{ 188 RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); 189 RWLOCK_BUG_ON(lock->owner == current, lock, "recursion"); 190 RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), 191 lock, "cpu recursion"); 192} 193 194static inline void debug_write_lock_after(rwlock_t *lock) 195{ 196 lock->owner_cpu = raw_smp_processor_id(); 197 lock->owner = current; 198} 199 200static inline void debug_write_unlock(rwlock_t *lock) 201{ 202 RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); 203 RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner"); 204 RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), 205 lock, "wrong CPU"); 206 lock->owner = SPINLOCK_OWNER_INIT; 207 lock->owner_cpu = -1; 208} 209 210static void __write_lock_debug(rwlock_t *lock) 211{ 212 int print_once = 1; 213 u64 i; 214 215 for (;;) { 216 for (i = 0; i < loops_per_jiffy * HZ; i++) { 217 cpu_relax(); 218 if (__raw_write_trylock(&lock->raw_lock)) 219 return; 220 } 221 /* lockup suspected: */ 222 if (print_once) { 223 print_once = 0; 224 printk("BUG: write-lock lockup on CPU#%d, %s/%d, %p\n", 225 raw_smp_processor_id(), current->comm, 226 current->pid, lock); 227 dump_stack(); 228 } 229 } 230} 231 232void _raw_write_lock(rwlock_t *lock) 233{ 234 debug_write_lock_before(lock); 235 if (unlikely(!__raw_write_trylock(&lock->raw_lock))) 236 __write_lock_debug(lock); 237 debug_write_lock_after(lock); 238} 239 240int _raw_write_trylock(rwlock_t *lock) 241{ 242 int ret = __raw_write_trylock(&lock->raw_lock); 243 244 if (ret) 245 debug_write_lock_after(lock); 246#ifndef CONFIG_SMP 247 /* 248 * Must not happen on UP: 249 */ 250 RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); 251#endif 252 return ret; 253} 254 255void _raw_write_unlock(rwlock_t *lock) 256{ 257 debug_write_unlock(lock); 258 __raw_write_unlock(&lock->raw_lock); 259}