summaryrefslogtreecommitdiffstats
path: root/arch/sparc/lib/debuglocks.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-06-01 03:16:17 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-06-01 03:16:17 +0000
commitd8d9b8f76f22b7a16a83e261e64f89ee611f49df (patch)
tree3067bc130b80d52808e6390c9fc7fc087ec1e33c /arch/sparc/lib/debuglocks.c
parent19c9bba94152148523ba0f7ef7cffe3d45656b11 (diff)
Initial revision
Diffstat (limited to 'arch/sparc/lib/debuglocks.c')
-rw-r--r--arch/sparc/lib/debuglocks.c463
1 files changed, 463 insertions, 0 deletions
diff --git a/arch/sparc/lib/debuglocks.c b/arch/sparc/lib/debuglocks.c
new file mode 100644
index 000000000..006cba5a8
--- /dev/null
+++ b/arch/sparc/lib/debuglocks.c
@@ -0,0 +1,463 @@
+/* $Id: debuglocks.c,v 1.1 1997/05/08 18:13:34 davem Exp $
+ * debuglocks.c: Debugging versions of SMP locking primitives.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/psr.h>
+#include <asm/system.h>
+#include <asm/spinlock.h>
+
+/* To enable this code, just define SPIN_LOCK_DEBUG in asm/spinlock.h */
+#ifdef SPIN_LOCK_DEBUG
+
+/* Some notes on how these debugging routines work. When a lock is acquired
+ * an extra debugging member lock->owner_pc is set to the caller of the lock
+ * acquisition routine. Right before releasing a lock, the debugging program
+ * counter is cleared to zero.
+ *
+ * Furthermore, since PC's are 4 byte aligned on Sparc, we stuff the CPU
+ * number of the owner in the lowest two bits.
+ */
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("spin_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; }
+
+void _spin_lock(spinlock_t *lock)
+{
+ unsigned long caller;
+ unsigned long val;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+again:
+ __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
+ if(val) {
+ while(lock->lock) {
+ STUCK;
+ barrier();
+ }
+ goto again;
+ }
+ lock->owner_pc = (cpu & 3) | (caller & ~3);
+}
+
+int _spin_trylock(spinlock_t *lock)
+{
+ unsigned long val;
+ unsigned long caller;
+ int cpu = smp_processor_id();
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+ __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
+ if(!val) {
+ /* We got it, record our identity for debugging. */
+ lock->owner_pc = (cpu & 3) | (caller & ~3);
+ }
+ return val == 0;
+}
+
+void _spin_unlock(spinlock_t *lock)
+{
+ lock->owner_pc = 0;
+ __asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory");
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("spin_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; }
+
+void _spin_lock_irq(spinlock_t *lock)
+{
+ unsigned long caller;
+ unsigned long val;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __cli();
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+again:
+ __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
+ if(val) {
+ while(lock->lock) {
+ STUCK;
+ barrier();
+ }
+ goto again;
+ }
+ lock->owner_pc = (cpu & 3) | (caller & ~3);
+}
+
+void _spin_unlock_irq(spinlock_t *lock)
+{
+ lock->owner_pc = 0;
+ __asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory");
+ __sti();
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("spin_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; }
+
+/* Caller macro does __save_and_cli(flags) for us. */
+void _spin_lock_irqsave(spinlock_t *lock)
+{
+ unsigned long caller;
+ unsigned long val;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+again:
+ __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
+ if(val) {
+ while(lock->lock) {
+ STUCK;
+ barrier();
+ }
+ goto again;
+ }
+ lock->owner_pc = (cpu & 3) | (caller & ~3);
+}
+
+void _spin_unlock_irqrestore(spinlock_t *lock)
+{
+ lock->owner_pc = 0;
+ __asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory");
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("read_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
+
+void _read_lock(rwlock_t *rw)
+{
+ unsigned long flags;
+ unsigned long caller;
+ unsigned long val;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+ __save_and_cli(flags);
+wlock_again:
+ __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff) {
+ STUCK;
+ barrier();
+ }
+ goto wlock_again;
+ }
+clock_again:
+ __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff00) {
+ STUCK;
+ barrier();
+ }
+ goto clock_again;
+ }
+ (*((unsigned short *)&rw->lock))++;
+ barrier();
+ (*(((unsigned short *)&rw->lock)+1)) = 0;
+ __restore_flags(flags);
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("read_unlock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
+
+void _read_unlock(rwlock_t *rw)
+{
+ unsigned long flags, val, caller;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+ __save_and_cli(flags);
+clock_again:
+ __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff00) {
+ STUCK;
+ barrier();
+ }
+ goto clock_again;
+ }
+ (*((unsigned short *)&rw->lock))--;
+ barrier();
+ (*(((unsigned char *)&rw->lock)+2))=0;
+ __restore_flags(flags);
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("write_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
+
+void _write_lock(rwlock_t *rw)
+{
+ unsigned long flags, val, caller;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+ __save_and_cli(flags);
+wlock_again:
+ __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff) {
+ STUCK;
+ barrier();
+ }
+ goto wlock_again;
+ }
+ rw->owner_pc = (cpu & 3) | (caller & ~3);
+ while(rw->lock & ~0xff) {
+ STUCK;
+ barrier();
+ }
+}
+
+void _write_unlock(rwlock_t *rw)
+{
+ rw->owner_pc = 0;
+ barrier();
+ rw->lock = 0;
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("read_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
+
+void _read_lock_irq(rwlock_t *rw)
+{
+ unsigned long caller;
+ unsigned long val;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+ __cli();
+wlock_again:
+ __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff) {
+ STUCK;
+ barrier();
+ }
+ goto wlock_again;
+ }
+clock_again:
+ __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff00) {
+ STUCK;
+ barrier();
+ }
+ goto clock_again;
+ }
+ (*((unsigned short *)&rw->lock))++;
+ barrier();
+ (*(((unsigned short *)&rw->lock)+1)) = 0;
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("read_unlock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
+
+void _read_unlock_irq(rwlock_t *rw)
+{
+ unsigned long val, caller;
+ int stuck = INIT_STUCK;
+ int cpu = smp_processor_id();
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+clock_again:
+ __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff00) {
+ STUCK;
+ barrier();
+ }
+ goto clock_again;
+ }
+ (*((unsigned short *)&rw->lock))--;
+ barrier();
+ (*(((unsigned char *)&rw->lock)+2))=0;
+ __sti();
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("write_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
+
+void _write_lock_irq(rwlock_t *rw)
+{
+ unsigned long val, caller;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+ __cli();
+wlock_again:
+ __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff) {
+ STUCK;
+ barrier();
+ }
+ goto wlock_again;
+ }
+ rw->owner_pc = (cpu & 3) | (caller & ~3);
+ while(rw->lock & ~0xff) {
+ STUCK;
+ barrier();
+ }
+}
+
+void _write_unlock_irq(rwlock_t *rw)
+{
+ rw->owner_pc = 0;
+ barrier();
+ rw->lock = 0;
+ __sti();
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("read_lock_irqsave(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
+
+/* Caller does __save_and_cli(flags) for us. */
+void _read_lock_irqsave(rwlock_t *rw)
+{
+ unsigned long caller;
+ unsigned long val;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+wlock_again:
+ __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff) {
+ STUCK;
+ barrier();
+ }
+ goto wlock_again;
+ }
+clock_again:
+ __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff00) {
+ STUCK;
+ barrier();
+ }
+ goto clock_again;
+ }
+ (*((unsigned short *)&rw->lock))++;
+ barrier();
+ (*(((unsigned short *)&rw->lock)+1)) = 0;
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("read_unlock_irqrestore(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
+
+void _read_unlock_irqrestore(rwlock_t *rw)
+{
+ unsigned long val, caller;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+clock_again:
+ __asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff00) {
+ STUCK;
+ barrier();
+ }
+ goto clock_again;
+ }
+ (*((unsigned short *)&rw->lock))--;
+ barrier();
+ (*(((unsigned char *)&rw->lock)+2))=0;
+}
+
+#undef INIT_STUCK
+#define INIT_STUCK 100000000
+
+#undef STUCK
+#define STUCK \
+if(!--stuck) { printk("write_lock_irqsave(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
+
+/* Caller does __save_and_cli(flags) for us. */
+void _write_lock_irqsave(rwlock_t *rw)
+{
+ unsigned long val, caller;
+ int cpu = smp_processor_id();
+ int stuck = INIT_STUCK;
+
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+wlock_again:
+ __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
+ if(val) {
+ while(rw->lock & 0xff) {
+ STUCK;
+ barrier();
+ }
+ goto wlock_again;
+ }
+ rw->owner_pc = (cpu & 3) | (caller & ~3);
+ while(rw->lock & ~0xff) {
+ STUCK;
+ barrier();
+ }
+}
+
+void _write_unlock_irqrestore(rwlock_t *rw)
+{
+ rw->owner_pc = 0;
+ barrier();
+ rw->lock = 0;
+}
+
+#endif /* SPIN_LOCK_DEBUG */