Linus TorvaldsLinux-2.6.12-rc21da177e21 years agoHistory
202 lines · 4.3 KB · C
RawDownload
/* $Id: debuglocks.c,v 1.11 2001/09/20 00:35:31 davem Exp $ * debuglocks.c: Debugging versions of SMP locking primitives. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au) */ #include <linux/kernel.h>#include <linux/sched.h>#include <linux/threads.h>	/* For NR_CPUS */#include <linux/spinlock.h>#include <asm/psr.h>#include <asm/system.h> #ifdef CONFIG_SMP /* 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. */ #define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A)); static inline void show(char *str, spinlock_t *lock, unsigned long caller){	int cpu = smp_processor_id(); 	printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str,		lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);} static inline void show_read(char *str, rwlock_t *lock, unsigned long caller){	int cpu = smp_processor_id(); 	printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", str,		lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);} static inline void show_write(char *str, rwlock_t *lock, unsigned long caller){	int cpu = smp_processor_id();	int i; 	printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)", str,		lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); 	for(i = 0; i < NR_CPUS; i++)		printk(" reader[%d]=%08lx", i, lock->reader_pc[i]); 	printk("\n");} #undef INIT_STUCK#define INIT_STUCK 100000000 void _do_spin_lock(spinlock_t *lock, char *str){	unsigned long caller;	unsigned long val;	int cpu = smp_processor_id();	int stuck = INIT_STUCK; 	STORE_CALLER(caller); again:	__asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));	if(val) {		while(lock->lock) {			if (!--stuck) {				show(str, lock, caller);				stuck = INIT_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(); 	STORE_CALLER(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 _do_spin_unlock(spinlock_t *lock){	lock->owner_pc = 0;	barrier();	lock->lock = 0;} void _do_read_lock(rwlock_t *rw, char *str){	unsigned long caller;	unsigned long val;	int cpu = smp_processor_id();	int stuck = INIT_STUCK; 	STORE_CALLER(caller); wlock_again:	__asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));	if(val) {		while(rw->lock & 0xff) {			if (!--stuck) {				show_read(str, rw, caller);				stuck = INIT_STUCK;			}			barrier();		}		goto wlock_again;	} 	rw->reader_pc[cpu] = caller;	barrier();	rw->lock++;} void _do_read_unlock(rwlock_t *rw, char *str){	unsigned long caller;	unsigned long val;	int cpu = smp_processor_id();	int stuck = INIT_STUCK; 	STORE_CALLER(caller); wlock_again:	__asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));	if(val) {		while(rw->lock & 0xff) {			if (!--stuck) {				show_read(str, rw, caller);				stuck = INIT_STUCK;			}			barrier();		}		goto wlock_again;	} 	rw->reader_pc[cpu] = 0;	barrier();	rw->lock -= 0x1ff;} void _do_write_lock(rwlock_t *rw, char *str){	unsigned long caller;	unsigned long val;	int cpu = smp_processor_id();	int stuck = INIT_STUCK; 	STORE_CALLER(caller); wlock_again:	__asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));	if(val) {wlock_wait:		while(rw->lock) {			if (!--stuck) {				show_write(str, rw, caller);				stuck = INIT_STUCK;			}			barrier();		}		goto wlock_again;	} 	if (rw->lock & ~0xff) {		*(((unsigned char *)&rw->lock)+3) = 0;		barrier();		goto wlock_wait;	} 	barrier();	rw->owner_pc = (cpu & 3) | (caller & ~3);} void _do_write_unlock(rwlock_t *rw){	rw->owner_pc = 0;	barrier();	rw->lock = 0;} #endif /* SMP */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t