diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 | 
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 | 
| commit | 5e66dd6d66ffe758b39b6dcadf2330753ee1159b (patch) | |
| tree | a72cdcff4448e4af9425cc213ddf56ab23e697fe /kernel/rtmutex-debug.c | |
| parent | 026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (diff) | |
| parent | ca78f6baca863afe2e6a244a0fe94b3a70211d46 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'kernel/rtmutex-debug.c')
| -rw-r--r-- | kernel/rtmutex-debug.c | 307 | 
1 files changed, 18 insertions, 289 deletions
| diff --git a/kernel/rtmutex-debug.c b/kernel/rtmutex-debug.c index 4aa8a2c9f453..0c1faa950af7 100644 --- a/kernel/rtmutex-debug.c +++ b/kernel/rtmutex-debug.c @@ -26,6 +26,7 @@  #include <linux/interrupt.h>  #include <linux/plist.h>  #include <linux/fs.h> +#include <linux/debug_locks.h>  #include "rtmutex_common.h" @@ -45,8 +46,6 @@ do {								\  		console_verbose();				\  		if (spin_is_locked(¤t->pi_lock))		\  			spin_unlock(¤t->pi_lock);		\ -		if (spin_is_locked(¤t->held_list_lock))	\ -			spin_unlock(¤t->held_list_lock);	\  	}							\  } while (0) @@ -97,7 +96,7 @@ void deadlock_trace_off(void)  	rt_trace_on = 0;  } -static void printk_task(task_t *p) +static void printk_task(struct task_struct *p)  {  	if (p)  		printk("%16s:%5d [%p, %3d]", p->comm, p->pid, p, p->prio); @@ -105,14 +104,6 @@ static void printk_task(task_t *p)  		printk("<none>");  } -static void printk_task_short(task_t *p) -{ -	if (p) -		printk("%s/%d [%p, %3d]", p->comm, p->pid, p, p->prio); -	else -		printk("<none>"); -} -  static void printk_lock(struct rt_mutex *lock, int print_owner)  {  	if (lock->name) @@ -128,222 +119,6 @@ static void printk_lock(struct rt_mutex *lock, int print_owner)  		printk_task(rt_mutex_owner(lock));  		printk("\n");  	} -	if (rt_mutex_owner(lock)) { -		printk("... acquired at:               "); -		print_symbol("%s\n", lock->acquire_ip); -	} -} - -static void printk_waiter(struct rt_mutex_waiter *w) -{ -	printk("-------------------------\n"); -	printk("| waiter struct %p:\n", w); -	printk("| w->list_entry: [DP:%p/%p|SP:%p/%p|PRI:%d]\n", -	       w->list_entry.plist.prio_list.prev, w->list_entry.plist.prio_list.next, -	       w->list_entry.plist.node_list.prev, w->list_entry.plist.node_list.next, -	       w->list_entry.prio); -	printk("| w->pi_list_entry: [DP:%p/%p|SP:%p/%p|PRI:%d]\n", -	       w->pi_list_entry.plist.prio_list.prev, w->pi_list_entry.plist.prio_list.next, -	       w->pi_list_entry.plist.node_list.prev, w->pi_list_entry.plist.node_list.next, -	       w->pi_list_entry.prio); -	printk("\n| lock:\n"); -	printk_lock(w->lock, 1); -	printk("| w->ti->task:\n"); -	printk_task(w->task); -	printk("| blocked at:  "); -	print_symbol("%s\n", w->ip); -	printk("-------------------------\n"); -} - -static void show_task_locks(task_t *p) -{ -	switch (p->state) { -	case TASK_RUNNING:		printk("R"); break; -	case TASK_INTERRUPTIBLE:	printk("S"); break; -	case TASK_UNINTERRUPTIBLE:	printk("D"); break; -	case TASK_STOPPED:		printk("T"); break; -	case EXIT_ZOMBIE:		printk("Z"); break; -	case EXIT_DEAD:			printk("X"); break; -	default:			printk("?"); break; -	} -	printk_task(p); -	if (p->pi_blocked_on) { -		struct rt_mutex *lock = p->pi_blocked_on->lock; - -		printk(" blocked on:"); -		printk_lock(lock, 1); -	} else -		printk(" (not blocked)\n"); -} - -void rt_mutex_show_held_locks(task_t *task, int verbose) -{ -	struct list_head *curr, *cursor = NULL; -	struct rt_mutex *lock; -	task_t *t; -	unsigned long flags; -	int count = 0; - -	if (!rt_trace_on) -		return; - -	if (verbose) { -		printk("------------------------------\n"); -		printk("| showing all locks held by: |  ("); -		printk_task_short(task); -		printk("):\n"); -		printk("------------------------------\n"); -	} - -next: -	spin_lock_irqsave(&task->held_list_lock, flags); -	list_for_each(curr, &task->held_list_head) { -		if (cursor && curr != cursor) -			continue; -		lock = list_entry(curr, struct rt_mutex, held_list_entry); -		t = rt_mutex_owner(lock); -		WARN_ON(t != task); -		count++; -		cursor = curr->next; -		spin_unlock_irqrestore(&task->held_list_lock, flags); - -		printk("\n#%03d:            ", count); -		printk_lock(lock, 0); -		goto next; -	} -	spin_unlock_irqrestore(&task->held_list_lock, flags); - -	printk("\n"); -} - -void rt_mutex_show_all_locks(void) -{ -	task_t *g, *p; -	int count = 10; -	int unlock = 1; - -	printk("\n"); -	printk("----------------------\n"); -	printk("| showing all tasks: |\n"); -	printk("----------------------\n"); - -	/* -	 * Here we try to get the tasklist_lock as hard as possible, -	 * if not successful after 2 seconds we ignore it (but keep -	 * trying). This is to enable a debug printout even if a -	 * tasklist_lock-holding task deadlocks or crashes. -	 */ -retry: -	if (!read_trylock(&tasklist_lock)) { -		if (count == 10) -			printk("hm, tasklist_lock locked, retrying... "); -		if (count) { -			count--; -			printk(" #%d", 10-count); -			mdelay(200); -			goto retry; -		} -		printk(" ignoring it.\n"); -		unlock = 0; -	} -	if (count != 10) -		printk(" locked it.\n"); - -	do_each_thread(g, p) { -		show_task_locks(p); -		if (!unlock) -			if (read_trylock(&tasklist_lock)) -				unlock = 1; -	} while_each_thread(g, p); - -	printk("\n"); - -	printk("-----------------------------------------\n"); -	printk("| showing all locks held in the system: |\n"); -	printk("-----------------------------------------\n"); - -	do_each_thread(g, p) { -		rt_mutex_show_held_locks(p, 0); -		if (!unlock) -			if (read_trylock(&tasklist_lock)) -				unlock = 1; -	} while_each_thread(g, p); - - -	printk("=============================================\n\n"); - -	if (unlock) -		read_unlock(&tasklist_lock); -} - -void rt_mutex_debug_check_no_locks_held(task_t *task) -{ -	struct rt_mutex_waiter *w; -	struct list_head *curr; -	struct rt_mutex *lock; - -	if (!rt_trace_on) -		return; -	if (!rt_prio(task->normal_prio) && rt_prio(task->prio)) { -		printk("BUG: PI priority boost leaked!\n"); -		printk_task(task); -		printk("\n"); -	} -	if (list_empty(&task->held_list_head)) -		return; - -	spin_lock(&task->pi_lock); -	plist_for_each_entry(w, &task->pi_waiters, pi_list_entry) { -		TRACE_OFF(); - -		printk("hm, PI interest held at exit time? Task:\n"); -		printk_task(task); -		printk_waiter(w); -		return; -	} -	spin_unlock(&task->pi_lock); - -	list_for_each(curr, &task->held_list_head) { -		lock = list_entry(curr, struct rt_mutex, held_list_entry); - -		printk("BUG: %s/%d, lock held at task exit time!\n", -		       task->comm, task->pid); -		printk_lock(lock, 1); -		if (rt_mutex_owner(lock) != task) -			printk("exiting task is not even the owner??\n"); -	} -} - -int rt_mutex_debug_check_no_locks_freed(const void *from, unsigned long len) -{ -	const void *to = from + len; -	struct list_head *curr; -	struct rt_mutex *lock; -	unsigned long flags; -	void *lock_addr; - -	if (!rt_trace_on) -		return 0; - -	spin_lock_irqsave(¤t->held_list_lock, flags); -	list_for_each(curr, ¤t->held_list_head) { -		lock = list_entry(curr, struct rt_mutex, held_list_entry); -		lock_addr = lock; -		if (lock_addr < from || lock_addr >= to) -			continue; -		TRACE_OFF(); - -		printk("BUG: %s/%d, active lock [%p(%p-%p)] freed!\n", -			current->comm, current->pid, lock, from, to); -		dump_stack(); -		printk_lock(lock, 1); -		if (rt_mutex_owner(lock) != current) -			printk("freeing task is not even the owner??\n"); -		return 1; -	} -	spin_unlock_irqrestore(¤t->held_list_lock, flags); - -	return 0;  }  void rt_mutex_debug_task_free(struct task_struct *task) @@ -395,85 +170,41 @@ void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter)  	       current->comm, current->pid);  	printk_lock(waiter->lock, 1); -	printk("... trying at:                 "); -	print_symbol("%s\n", waiter->ip); -  	printk("\n2) %s/%d is blocked on this lock:\n", task->comm, task->pid);  	printk_lock(waiter->deadlock_lock, 1); -	rt_mutex_show_held_locks(current, 1); -	rt_mutex_show_held_locks(task, 1); +	debug_show_held_locks(current); +	debug_show_held_locks(task);  	printk("\n%s/%d's [blocked] stackdump:\n\n", task->comm, task->pid);  	show_stack(task, NULL);  	printk("\n%s/%d's [current] stackdump:\n\n",  	       current->comm, current->pid);  	dump_stack(); -	rt_mutex_show_all_locks(); +	debug_show_all_locks(); +  	printk("[ turning off deadlock detection."  	       "Please report this trace. ]\n\n");  	local_irq_disable();  } -void debug_rt_mutex_lock(struct rt_mutex *lock __IP_DECL__) +void debug_rt_mutex_lock(struct rt_mutex *lock)  { -	unsigned long flags; - -	if (rt_trace_on) { -		TRACE_WARN_ON_LOCKED(!list_empty(&lock->held_list_entry)); - -		spin_lock_irqsave(¤t->held_list_lock, flags); -		list_add_tail(&lock->held_list_entry, ¤t->held_list_head); -		spin_unlock_irqrestore(¤t->held_list_lock, flags); - -		lock->acquire_ip = ip; -	}  }  void debug_rt_mutex_unlock(struct rt_mutex *lock)  { -	unsigned long flags; - -	if (rt_trace_on) { -		TRACE_WARN_ON_LOCKED(rt_mutex_owner(lock) != current); -		TRACE_WARN_ON_LOCKED(list_empty(&lock->held_list_entry)); - -		spin_lock_irqsave(¤t->held_list_lock, flags); -		list_del_init(&lock->held_list_entry); -		spin_unlock_irqrestore(¤t->held_list_lock, flags); -	} +	TRACE_WARN_ON_LOCKED(rt_mutex_owner(lock) != current);  } -void debug_rt_mutex_proxy_lock(struct rt_mutex *lock, -			       struct task_struct *powner __IP_DECL__) +void +debug_rt_mutex_proxy_lock(struct rt_mutex *lock, struct task_struct *powner)  { -	unsigned long flags; - -	if (rt_trace_on) { -		TRACE_WARN_ON_LOCKED(!list_empty(&lock->held_list_entry)); - -		spin_lock_irqsave(&powner->held_list_lock, flags); -		list_add_tail(&lock->held_list_entry, &powner->held_list_head); -		spin_unlock_irqrestore(&powner->held_list_lock, flags); - -		lock->acquire_ip = ip; -	}  }  void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock)  { -	unsigned long flags; - -	if (rt_trace_on) { -		struct task_struct *owner = rt_mutex_owner(lock); - -		TRACE_WARN_ON_LOCKED(!owner); -		TRACE_WARN_ON_LOCKED(list_empty(&lock->held_list_entry)); - -		spin_lock_irqsave(&owner->held_list_lock, flags); -		list_del_init(&lock->held_list_entry); -		spin_unlock_irqrestore(&owner->held_list_lock, flags); -	} +	TRACE_WARN_ON_LOCKED(!rt_mutex_owner(lock));  }  void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter) @@ -493,17 +224,15 @@ void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)  void debug_rt_mutex_init(struct rt_mutex *lock, const char *name)  { -	void *addr = lock; - -	if (rt_trace_on) { -		rt_mutex_debug_check_no_locks_freed(addr, -						    sizeof(struct rt_mutex)); -		INIT_LIST_HEAD(&lock->held_list_entry); -		lock->name = name; -	} +	/* +	 * Make sure we are not reinitializing a held lock: +	 */ +	debug_check_no_locks_freed((void *)lock, sizeof(*lock)); +	lock->name = name;  } -void rt_mutex_deadlock_account_lock(struct rt_mutex *lock, task_t *task) +void +rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task)  {  } | 
