1/* 2 * kernel/mutex-debug.c 3 * 4 * Debugging code for mutexes 5 * 6 * Started by Ingo Molnar: 7 * 8 * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> 9 * 10 * lock debugging, locking tree, deadlock detection started by: 11 * 12 * Copyright (C) 2004, LynuxWorks, Inc., Igor Manyilov, Bill Huey 13 * Released under the General Public License (GPL). 14 */ 15#include <linux/mutex.h> 16#include <linux/delay.h> 17#include <linux/module.h> 18#include <linux/poison.h> 19#include <linux/spinlock.h> 20#include <linux/kallsyms.h> 21#include <linux/interrupt.h> 22#include <linux/debug_locks.h> 23 24#include "mutex-debug.h" 25 26/* 27 * Must be called with lock->wait_lock held. 28 */ 29void debug_mutex_set_owner(struct mutex *lock, struct thread_info *new_owner) 30{ 31 lock->owner = new_owner; 32} 33 34void debug_mutex_lock_common(struct mutex *lock, struct mutex_waiter *waiter) 35{ 36 memset(waiter, MUTEX_DEBUG_INIT, sizeof(*waiter)); 37 waiter->magic = waiter; 38 INIT_LIST_HEAD(&waiter->list); 39} 40 41void debug_mutex_wake_waiter(struct mutex *lock, struct mutex_waiter *waiter) 42{ 43 SMP_DEBUG_LOCKS_WARN_ON(!spin_is_locked(&lock->wait_lock)); 44 DEBUG_LOCKS_WARN_ON(list_empty(&lock->wait_list)); 45 DEBUG_LOCKS_WARN_ON(waiter->magic != waiter); 46 DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list)); 47} 48 49void debug_mutex_free_waiter(struct mutex_waiter *waiter) 50{ 51 DEBUG_LOCKS_WARN_ON(!list_empty(&waiter->list)); 52 memset(waiter, MUTEX_DEBUG_FREE, sizeof(*waiter)); 53} 54 55void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter, 56 struct thread_info *ti) 57{ 58 SMP_DEBUG_LOCKS_WARN_ON(!spin_is_locked(&lock->wait_lock)); 59 60 /* Mark the current thread as blocked on the lock: */ 61 ti->task->blocked_on = waiter; 62 waiter->lock = lock; 63} 64 65void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, 66 struct thread_info *ti) 67{ 68 DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list)); 69 DEBUG_LOCKS_WARN_ON(waiter->task != ti->task); 70 DEBUG_LOCKS_WARN_ON(ti->task->blocked_on != waiter); 71 ti->task->blocked_on = NULL; 72 73 list_del_init(&waiter->list); 74 waiter->task = NULL; 75} 76 77void debug_mutex_unlock(struct mutex *lock) 78{ 79 if (unlikely(!debug_locks)) 80 return; 81 82 DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info()); 83 DEBUG_LOCKS_WARN_ON(lock->magic != lock); 84 DEBUG_LOCKS_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next); 85 DEBUG_LOCKS_WARN_ON(lock->owner != current_thread_info()); 86} 87 88void debug_mutex_init(struct mutex *lock, const char *name, 89 struct lock_class_key *key) 90{ 91#ifdef CONFIG_DEBUG_LOCK_ALLOC 92 /* 93 * Make sure we are not reinitializing a held lock: 94 */ 95 debug_check_no_locks_freed((void *)lock, sizeof(*lock)); 96 lockdep_init_map(&lock->dep_map, name, key, 0); 97#endif 98 lock->owner = NULL; 99 lock->magic = lock; 100} 101 102/*** 103 * mutex_destroy - mark a mutex unusable 104 * @lock: the mutex to be destroyed 105 * 106 * This function marks the mutex uninitialized, and any subsequent 107 * use of the mutex is forbidden. The mutex must not be locked when 108 * this function is called. 109 */ 110void fastcall mutex_destroy(struct mutex *lock) 111{ 112 DEBUG_LOCKS_WARN_ON(mutex_is_locked(lock)); 113 lock->magic = NULL; 114} 115 116EXPORT_SYMBOL_GPL(mutex_destroy); 117