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