debuglocks.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 228 行

C
228
字号
/*  *    Debugging versions of SMP locking primitives. * *    Copyright (C) 2004 Thibaut VARENE <varenet@esiee.fr> * *    Some code stollen from alpha & sparc64 ;) * *    This program is free software; you can redistribute it and/or modify *    it under the terms of the GNU General Public License as published by *    the Free Software Foundation; either version 2 of the License, or *    (at your option) any later version. * *    This program is distributed in the hope that it will be useful, *    but WITHOUT ANY WARRANTY; without even the implied warranty of *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *    GNU General Public License for more details. * *    You should have received a copy of the GNU General Public License *    along with this program; if not, write to the Free Software *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <linux/config.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/spinlock.h>#include <linux/hardirq.h>	/* in_interrupt() */#include <asm/system.h>#undef INIT_STUCK#define INIT_STUCK 1L << 30#ifdef CONFIG_DEBUG_SPINLOCKvoid _dbg_spin_lock(spinlock_t * lock, const char *base_file, int line_no){	volatile unsigned int *a;	long stuck = INIT_STUCK;	void *inline_pc = __builtin_return_address(0);	unsigned long started = jiffies;	int printed = 0;	int cpu = smp_processor_id();try_again:	/* Do the actual locking */	/* <T-Bone> ggg: we can't get stuck on the outter loop?	 * <ggg> T-Bone: We can hit the outer loop	 *	alot if multiple CPUs are constantly racing for a lock	 *	and the backplane is NOT fair about which CPU sees	 *	the update first. But it won't hang since every failed	 *	attempt will drop us back into the inner loop and	 *	decrement `stuck'.	 * <ggg> K-class and some of the others are NOT fair in the HW	 * 	implementation so we could see false positives.	 * 	But fixing the lock contention is easier than	 * 	fixing the HW to be fair.	 * <tausq> __ldcw() returns 1 if we get the lock; otherwise we	 * 	spin until the value of the lock changes, or we time out.	 */	a = __ldcw_align(lock);	while (stuck && (__ldcw(a) == 0))		while ((*a == 0) && --stuck);	if (unlikely(stuck <= 0)) {		printk(KERN_WARNING			"%s:%d: spin_lock(%s/%p) stuck in %s at %p(%d)"			" owned by %s:%d in %s at %p(%d)\n",			base_file, line_no, lock->module, lock,			current->comm, inline_pc, cpu,			lock->bfile, lock->bline, lock->task->comm,			lock->previous, lock->oncpu);		stuck = INIT_STUCK;		printed = 1;		goto try_again;	}	/* Exiting.  Got the lock.  */	lock->oncpu = cpu;	lock->previous = inline_pc;	lock->task = current;	lock->bfile = (char *)base_file;	lock->bline = line_no;	if (unlikely(printed)) {		printk(KERN_WARNING			"%s:%d: spin_lock grabbed in %s at %p(%d) %ld ticks\n",			base_file, line_no, current->comm, inline_pc,			cpu, jiffies - started);	}}void _dbg_spin_unlock(spinlock_t * lock, const char *base_file, int line_no){	CHECK_LOCK(lock);	volatile unsigned int *a = __ldcw_align(lock);	if (unlikely((*a != 0) && lock->babble)) {		lock->babble--;		printk(KERN_WARNING			"%s:%d: spin_unlock(%s:%p) not locked\n",			base_file, line_no, lock->module, lock);	}	*a = 1;	}int _dbg_spin_trylock(spinlock_t * lock, const char *base_file, int line_no){	int ret;	volatile unsigned int *a = __ldcw_align(lock);	if ((ret = (__ldcw(a) != 0))) {		lock->oncpu = smp_processor_id();		lock->previous = __builtin_return_address(0);		lock->task = current;	} else {		lock->bfile = (char *)base_file;		lock->bline = line_no;	}	return ret;}#endif /* CONFIG_DEBUG_SPINLOCK */#ifdef CONFIG_DEBUG_RWLOCK/* Interrupts trouble detailed explanation, thx Grant: * * o writer (wants to modify data) attempts to acquire the rwlock * o He gets the write lock. * o Interupts are still enabled, we take an interrupt with the *   write still holding the lock. * o interrupt handler tries to acquire the rwlock for read. * o deadlock since the writer can't release it at this point. *  * In general, any use of spinlocks that competes between "base" * level and interrupt level code will risk deadlock. Interrupts * need to be disabled in the base level routines to avoid it. * Or more precisely, only the IRQ the base level routine * is competing with for the lock.  But it's more efficient/faster * to just disable all interrupts on that CPU to guarantee * once it gets the lock it can release it quickly too. */ void _dbg_write_lock(rwlock_t *rw, const char *bfile, int bline){	void *inline_pc = __builtin_return_address(0);	unsigned long started = jiffies;	long stuck = INIT_STUCK;	int printed = 0;	int cpu = smp_processor_id();		if(unlikely(in_interrupt())) {	/* acquiring write lock in interrupt context, bad idea */		printk(KERN_WARNING "write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline);		BUG();	}	/* Note: if interrupts are disabled (which is most likely), the printk	will never show on the console. We might need a polling method to flush	the dmesg buffer anyhow. */	retry:	_raw_spin_lock(&rw->lock);	if(rw->counter != 0) {		/* this basically never happens */		_raw_spin_unlock(&rw->lock);				stuck--;		if ((unlikely(stuck <= 0)) && (rw->counter < 0)) {			printk(KERN_WARNING				"%s:%d: write_lock stuck on writer"				" in %s at %p(%d) %ld ticks\n",				bfile, bline, current->comm, inline_pc,				cpu, jiffies - started);			stuck = INIT_STUCK;			printed = 1;		}		else if (unlikely(stuck <= 0)) {			printk(KERN_WARNING				"%s:%d: write_lock stuck on reader"				" in %s at %p(%d) %ld ticks\n",				bfile, bline, current->comm, inline_pc,				cpu, jiffies - started);			stuck = INIT_STUCK;			printed = 1;		}				while(rw->counter != 0);		goto retry;	}	/* got it.  now leave without unlocking */	rw->counter = -1; /* remember we are locked */	if (unlikely(printed)) {		printk(KERN_WARNING			"%s:%d: write_lock grabbed in %s at %p(%d) %ld ticks\n",			bfile, bline, current->comm, inline_pc,			cpu, jiffies - started);	}}void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline){#if 0	void *inline_pc = __builtin_return_address(0);	unsigned long started = jiffies;	int cpu = smp_processor_id();#endif	unsigned long flags;	local_irq_save(flags);	_raw_spin_lock(&rw->lock); 	rw->counter++;#if 0	printk(KERN_WARNING		"%s:%d: read_lock grabbed in %s at %p(%d) %ld ticks\n",		bfile, bline, current->comm, inline_pc,		cpu, jiffies - started);#endif	_raw_spin_unlock(&rw->lock);	local_irq_restore(flags);}#endif /* CONFIG_DEBUG_RWLOCK */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?