diff options
| author | David S. Miller <davem@davemloft.net> | 2005-08-29 15:46:07 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2005-08-29 15:46:07 -0400 |
| commit | 442464a50077ff00454ff8d7628cbe1b8eacc034 (patch) | |
| tree | d076c18c8f9d860ee9f357a78b87d0ede8286585 | |
| parent | ca7c8d2c1e2a2f2445cb5e00f45b93af57f22c1b (diff) | |
[SPARC64]: Make debugging spinlocks usable again.
When the spinlock routines were moved out of line into
kernel/spinlock.c this made it so that the debugging
spinlocks record lock acquisition program counts in the
kernel/spinlock.c functions not in their callers.
This makes the debugging info kind of useless.
So record the correct caller's program counter and
now this feature is useful once more.
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | arch/sparc64/kernel/sparc64_ksyms.c | 23 | ||||
| -rw-r--r-- | arch/sparc64/lib/debuglocks.c | 40 | ||||
| -rw-r--r-- | include/asm-sparc64/spinlock.h | 40 |
3 files changed, 38 insertions, 65 deletions
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 9202d925a9ce..0764b9330784 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c | |||
| @@ -99,17 +99,6 @@ extern int __ashrdi3(int, int); | |||
| 99 | extern void dump_thread(struct pt_regs *, struct user *); | 99 | extern void dump_thread(struct pt_regs *, struct user *); |
| 100 | extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs); | 100 | extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs); |
| 101 | 101 | ||
| 102 | #if defined(CONFIG_SMP) && defined(CONFIG_DEBUG_SPINLOCK) | ||
| 103 | extern void _do_spin_lock (spinlock_t *lock, char *str); | ||
| 104 | extern void _do_spin_unlock (spinlock_t *lock); | ||
| 105 | extern int _spin_trylock (spinlock_t *lock); | ||
| 106 | extern void _do_read_lock(rwlock_t *rw, char *str); | ||
| 107 | extern void _do_read_unlock(rwlock_t *rw, char *str); | ||
| 108 | extern void _do_write_lock(rwlock_t *rw, char *str); | ||
| 109 | extern void _do_write_unlock(rwlock_t *rw); | ||
| 110 | extern int _do_write_trylock(rwlock_t *rw, char *str); | ||
| 111 | #endif | ||
| 112 | |||
| 113 | extern unsigned long phys_base; | 102 | extern unsigned long phys_base; |
| 114 | extern unsigned long pfn_base; | 103 | extern unsigned long pfn_base; |
| 115 | 104 | ||
| @@ -152,18 +141,6 @@ EXPORT_SYMBOL(_mcount); | |||
| 152 | EXPORT_SYMBOL(cpu_online_map); | 141 | EXPORT_SYMBOL(cpu_online_map); |
| 153 | EXPORT_SYMBOL(phys_cpu_present_map); | 142 | EXPORT_SYMBOL(phys_cpu_present_map); |
| 154 | 143 | ||
| 155 | /* Spinlock debugging library, optional. */ | ||
| 156 | #ifdef CONFIG_DEBUG_SPINLOCK | ||
| 157 | EXPORT_SYMBOL(_do_spin_lock); | ||
| 158 | EXPORT_SYMBOL(_do_spin_unlock); | ||
| 159 | EXPORT_SYMBOL(_spin_trylock); | ||
| 160 | EXPORT_SYMBOL(_do_read_lock); | ||
| 161 | EXPORT_SYMBOL(_do_read_unlock); | ||
| 162 | EXPORT_SYMBOL(_do_write_lock); | ||
| 163 | EXPORT_SYMBOL(_do_write_unlock); | ||
| 164 | EXPORT_SYMBOL(_do_write_trylock); | ||
| 165 | #endif | ||
| 166 | |||
| 167 | EXPORT_SYMBOL(smp_call_function); | 144 | EXPORT_SYMBOL(smp_call_function); |
| 168 | #endif /* CONFIG_SMP */ | 145 | #endif /* CONFIG_SMP */ |
| 169 | 146 | ||
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c index f03344cf784e..7f6ccc4114c5 100644 --- a/arch/sparc64/lib/debuglocks.c +++ b/arch/sparc64/lib/debuglocks.c | |||
| @@ -12,8 +12,6 @@ | |||
| 12 | 12 | ||
| 13 | #ifdef CONFIG_SMP | 13 | #ifdef CONFIG_SMP |
| 14 | 14 | ||
| 15 | #define GET_CALLER(PC) __asm__ __volatile__("mov %%i7, %0" : "=r" (PC)) | ||
| 16 | |||
| 17 | static inline void show (char *str, spinlock_t *lock, unsigned long caller) | 15 | static inline void show (char *str, spinlock_t *lock, unsigned long caller) |
| 18 | { | 16 | { |
| 19 | int cpu = smp_processor_id(); | 17 | int cpu = smp_processor_id(); |
| @@ -51,14 +49,13 @@ static inline void show_write (char *str, rwlock_t *lock, unsigned long caller) | |||
| 51 | #undef INIT_STUCK | 49 | #undef INIT_STUCK |
| 52 | #define INIT_STUCK 100000000 | 50 | #define INIT_STUCK 100000000 |
| 53 | 51 | ||
| 54 | void _do_spin_lock(spinlock_t *lock, char *str) | 52 | void _do_spin_lock(spinlock_t *lock, char *str, unsigned long caller) |
| 55 | { | 53 | { |
| 56 | unsigned long caller, val; | 54 | unsigned long val; |
| 57 | int stuck = INIT_STUCK; | 55 | int stuck = INIT_STUCK; |
| 58 | int cpu = get_cpu(); | 56 | int cpu = get_cpu(); |
| 59 | int shown = 0; | 57 | int shown = 0; |
| 60 | 58 | ||
| 61 | GET_CALLER(caller); | ||
| 62 | again: | 59 | again: |
| 63 | __asm__ __volatile__("ldstub [%1], %0" | 60 | __asm__ __volatile__("ldstub [%1], %0" |
| 64 | : "=r" (val) | 61 | : "=r" (val) |
| @@ -84,12 +81,11 @@ again: | |||
| 84 | put_cpu(); | 81 | put_cpu(); |
| 85 | } | 82 | } |
| 86 | 83 | ||
| 87 | int _do_spin_trylock(spinlock_t *lock) | 84 | int _do_spin_trylock(spinlock_t *lock, unsigned long caller) |
| 88 | { | 85 | { |
| 89 | unsigned long val, caller; | 86 | unsigned long val; |
| 90 | int cpu = get_cpu(); | 87 | int cpu = get_cpu(); |
| 91 | 88 | ||
| 92 | GET_CALLER(caller); | ||
| 93 | __asm__ __volatile__("ldstub [%1], %0" | 89 | __asm__ __volatile__("ldstub [%1], %0" |
| 94 | : "=r" (val) | 90 | : "=r" (val) |
| 95 | : "r" (&(lock->lock)) | 91 | : "r" (&(lock->lock)) |
| @@ -118,14 +114,13 @@ void _do_spin_unlock(spinlock_t *lock) | |||
| 118 | 114 | ||
| 119 | /* Keep INIT_STUCK the same... */ | 115 | /* Keep INIT_STUCK the same... */ |
| 120 | 116 | ||
| 121 | void _do_read_lock (rwlock_t *rw, char *str) | 117 | void _do_read_lock(rwlock_t *rw, char *str, unsigned long caller) |
| 122 | { | 118 | { |
| 123 | unsigned long caller, val; | 119 | unsigned long val; |
| 124 | int stuck = INIT_STUCK; | 120 | int stuck = INIT_STUCK; |
| 125 | int cpu = get_cpu(); | 121 | int cpu = get_cpu(); |
| 126 | int shown = 0; | 122 | int shown = 0; |
| 127 | 123 | ||
| 128 | GET_CALLER(caller); | ||
| 129 | wlock_again: | 124 | wlock_again: |
| 130 | /* Wait for any writer to go away. */ | 125 | /* Wait for any writer to go away. */ |
| 131 | while (((long)(rw->lock)) < 0) { | 126 | while (((long)(rw->lock)) < 0) { |
| @@ -157,15 +152,13 @@ wlock_again: | |||
| 157 | put_cpu(); | 152 | put_cpu(); |
| 158 | } | 153 | } |
| 159 | 154 | ||
| 160 | void _do_read_unlock (rwlock_t *rw, char *str) | 155 | void _do_read_unlock(rwlock_t *rw, char *str, unsigned long caller) |
| 161 | { | 156 | { |
| 162 | unsigned long caller, val; | 157 | unsigned long val; |
| 163 | int stuck = INIT_STUCK; | 158 | int stuck = INIT_STUCK; |
| 164 | int cpu = get_cpu(); | 159 | int cpu = get_cpu(); |
| 165 | int shown = 0; | 160 | int shown = 0; |
| 166 | 161 | ||
| 167 | GET_CALLER(caller); | ||
| 168 | |||
| 169 | /* Drop our identity _first_. */ | 162 | /* Drop our identity _first_. */ |
| 170 | rw->reader_pc[cpu] = 0; | 163 | rw->reader_pc[cpu] = 0; |
| 171 | current->thread.smp_lock_count--; | 164 | current->thread.smp_lock_count--; |
| @@ -193,14 +186,13 @@ runlock_again: | |||
| 193 | put_cpu(); | 186 | put_cpu(); |
| 194 | } | 187 | } |
| 195 | 188 | ||
| 196 | void _do_write_lock (rwlock_t *rw, char *str) | 189 | void _do_write_lock(rwlock_t *rw, char *str, unsigned long caller) |
| 197 | { | 190 | { |
| 198 | unsigned long caller, val; | 191 | unsigned long val; |
| 199 | int stuck = INIT_STUCK; | 192 | int stuck = INIT_STUCK; |
| 200 | int cpu = get_cpu(); | 193 | int cpu = get_cpu(); |
| 201 | int shown = 0; | 194 | int shown = 0; |
| 202 | 195 | ||
| 203 | GET_CALLER(caller); | ||
| 204 | wlock_again: | 196 | wlock_again: |
| 205 | /* Spin while there is another writer. */ | 197 | /* Spin while there is another writer. */ |
| 206 | while (((long)rw->lock) < 0) { | 198 | while (((long)rw->lock) < 0) { |
| @@ -278,14 +270,12 @@ wlock_again: | |||
| 278 | put_cpu(); | 270 | put_cpu(); |
| 279 | } | 271 | } |
| 280 | 272 | ||
| 281 | void _do_write_unlock(rwlock_t *rw) | 273 | void _do_write_unlock(rwlock_t *rw, unsigned long caller) |
| 282 | { | 274 | { |
| 283 | unsigned long caller, val; | 275 | unsigned long val; |
| 284 | int stuck = INIT_STUCK; | 276 | int stuck = INIT_STUCK; |
| 285 | int shown = 0; | 277 | int shown = 0; |
| 286 | 278 | ||
| 287 | GET_CALLER(caller); | ||
| 288 | |||
| 289 | /* Drop our identity _first_ */ | 279 | /* Drop our identity _first_ */ |
| 290 | rw->writer_pc = 0; | 280 | rw->writer_pc = 0; |
| 291 | rw->writer_cpu = NO_PROC_ID; | 281 | rw->writer_cpu = NO_PROC_ID; |
| @@ -313,13 +303,11 @@ wlock_again: | |||
| 313 | } | 303 | } |
| 314 | } | 304 | } |
| 315 | 305 | ||
| 316 | int _do_write_trylock (rwlock_t *rw, char *str) | 306 | int _do_write_trylock(rwlock_t *rw, char *str, unsigned long caller) |
| 317 | { | 307 | { |
| 318 | unsigned long caller, val; | 308 | unsigned long val; |
| 319 | int cpu = get_cpu(); | 309 | int cpu = get_cpu(); |
| 320 | 310 | ||
| 321 | GET_CALLER(caller); | ||
| 322 | |||
| 323 | /* Try to acuire the write bit. */ | 311 | /* Try to acuire the write bit. */ |
| 324 | __asm__ __volatile__( | 312 | __asm__ __volatile__( |
| 325 | " mov 1, %%g3\n" | 313 | " mov 1, %%g3\n" |
diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h index 9cb93a5c2b4f..d265bf6570fe 100644 --- a/include/asm-sparc64/spinlock.h +++ b/include/asm-sparc64/spinlock.h | |||
| @@ -132,12 +132,15 @@ do { \ | |||
| 132 | membar("#LoadLoad"); \ | 132 | membar("#LoadLoad"); \ |
| 133 | } while((__lock)->lock) | 133 | } while((__lock)->lock) |
| 134 | 134 | ||
| 135 | extern void _do_spin_lock (spinlock_t *lock, char *str); | 135 | extern void _do_spin_lock(spinlock_t *lock, char *str, unsigned long caller); |
| 136 | extern void _do_spin_unlock (spinlock_t *lock); | 136 | extern void _do_spin_unlock(spinlock_t *lock); |
| 137 | extern int _do_spin_trylock (spinlock_t *lock); | 137 | extern int _do_spin_trylock(spinlock_t *lock, unsigned long caller); |
| 138 | 138 | ||
| 139 | #define _raw_spin_trylock(lp) _do_spin_trylock(lp) | 139 | #define _raw_spin_trylock(lp) \ |
| 140 | #define _raw_spin_lock(lock) _do_spin_lock(lock, "spin_lock") | 140 | _do_spin_trylock(lp, (unsigned long) __builtin_return_address(0)) |
| 141 | #define _raw_spin_lock(lock) \ | ||
| 142 | _do_spin_lock(lock, "spin_lock", \ | ||
| 143 | (unsigned long) __builtin_return_address(0)) | ||
| 141 | #define _raw_spin_unlock(lock) _do_spin_unlock(lock) | 144 | #define _raw_spin_unlock(lock) _do_spin_unlock(lock) |
| 142 | #define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock) | 145 | #define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock) |
| 143 | 146 | ||
| @@ -279,37 +282,41 @@ typedef struct { | |||
| 279 | #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, 0xff, { } } | 282 | #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, 0xff, { } } |
| 280 | #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0) | 283 | #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0) |
| 281 | 284 | ||
| 282 | extern void _do_read_lock(rwlock_t *rw, char *str); | 285 | extern void _do_read_lock(rwlock_t *rw, char *str, unsigned long caller); |
| 283 | extern void _do_read_unlock(rwlock_t *rw, char *str); | 286 | extern void _do_read_unlock(rwlock_t *rw, char *str, unsigned long caller); |
| 284 | extern void _do_write_lock(rwlock_t *rw, char *str); | 287 | extern void _do_write_lock(rwlock_t *rw, char *str, unsigned long caller); |
| 285 | extern void _do_write_unlock(rwlock_t *rw); | 288 | extern void _do_write_unlock(rwlock_t *rw, unsigned long caller); |
| 286 | extern int _do_write_trylock(rwlock_t *rw, char *str); | 289 | extern int _do_write_trylock(rwlock_t *rw, char *str, unsigned long caller); |
| 287 | 290 | ||
| 288 | #define _raw_read_lock(lock) \ | 291 | #define _raw_read_lock(lock) \ |
| 289 | do { unsigned long flags; \ | 292 | do { unsigned long flags; \ |
| 290 | local_irq_save(flags); \ | 293 | local_irq_save(flags); \ |
| 291 | _do_read_lock(lock, "read_lock"); \ | 294 | _do_read_lock(lock, "read_lock", \ |
| 295 | (unsigned long) __builtin_return_address(0)); \ | ||
| 292 | local_irq_restore(flags); \ | 296 | local_irq_restore(flags); \ |
| 293 | } while(0) | 297 | } while(0) |
| 294 | 298 | ||
| 295 | #define _raw_read_unlock(lock) \ | 299 | #define _raw_read_unlock(lock) \ |
| 296 | do { unsigned long flags; \ | 300 | do { unsigned long flags; \ |
| 297 | local_irq_save(flags); \ | 301 | local_irq_save(flags); \ |
| 298 | _do_read_unlock(lock, "read_unlock"); \ | 302 | _do_read_unlock(lock, "read_unlock", \ |
| 303 | (unsigned long) __builtin_return_address(0)); \ | ||
| 299 | local_irq_restore(flags); \ | 304 | local_irq_restore(flags); \ |
| 300 | } while(0) | 305 | } while(0) |
| 301 | 306 | ||
| 302 | #define _raw_write_lock(lock) \ | 307 | #define _raw_write_lock(lock) \ |
| 303 | do { unsigned long flags; \ | 308 | do { unsigned long flags; \ |
| 304 | local_irq_save(flags); \ | 309 | local_irq_save(flags); \ |
| 305 | _do_write_lock(lock, "write_lock"); \ | 310 | _do_write_lock(lock, "write_lock", \ |
| 311 | (unsigned long) __builtin_return_address(0)); \ | ||
| 306 | local_irq_restore(flags); \ | 312 | local_irq_restore(flags); \ |
| 307 | } while(0) | 313 | } while(0) |
| 308 | 314 | ||
| 309 | #define _raw_write_unlock(lock) \ | 315 | #define _raw_write_unlock(lock) \ |
| 310 | do { unsigned long flags; \ | 316 | do { unsigned long flags; \ |
| 311 | local_irq_save(flags); \ | 317 | local_irq_save(flags); \ |
| 312 | _do_write_unlock(lock); \ | 318 | _do_write_unlock(lock, \ |
| 319 | (unsigned long) __builtin_return_address(0)); \ | ||
| 313 | local_irq_restore(flags); \ | 320 | local_irq_restore(flags); \ |
| 314 | } while(0) | 321 | } while(0) |
| 315 | 322 | ||
| @@ -317,7 +324,8 @@ do { unsigned long flags; \ | |||
| 317 | ({ unsigned long flags; \ | 324 | ({ unsigned long flags; \ |
| 318 | int val; \ | 325 | int val; \ |
| 319 | local_irq_save(flags); \ | 326 | local_irq_save(flags); \ |
| 320 | val = _do_write_trylock(lock, "write_trylock"); \ | 327 | val = _do_write_trylock(lock, "write_trylock", \ |
| 328 | (unsigned long) __builtin_return_address(0)); \ | ||
| 321 | local_irq_restore(flags); \ | 329 | local_irq_restore(flags); \ |
| 322 | val; \ | 330 | val; \ |
| 323 | }) | 331 | }) |
