diff options
Diffstat (limited to 'kernel/mutex-debug.h')
| -rw-r--r-- | kernel/mutex-debug.h | 134 | 
1 files changed, 134 insertions, 0 deletions
diff --git a/kernel/mutex-debug.h b/kernel/mutex-debug.h new file mode 100644 index 00000000000..fd384050acb --- /dev/null +++ b/kernel/mutex-debug.h @@ -0,0 +1,134 @@ +/* + * Mutexes: blocking mutual exclusion locks + * + * started by Ingo Molnar: + * + *  Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * + * This file contains mutex debugging related internal declarations, + * prototypes and inline functions, for the CONFIG_DEBUG_MUTEXES case. + * More details are in kernel/mutex-debug.c. + */ + +extern spinlock_t debug_mutex_lock; +extern struct list_head debug_mutex_held_locks; +extern int debug_mutex_on; + +/* + * In the debug case we carry the caller's instruction pointer into + * other functions, but we dont want the function argument overhead + * in the nondebug case - hence these macros: + */ +#define __IP_DECL__		, unsigned long ip +#define __IP__			, ip +#define __RET_IP__		, (unsigned long)__builtin_return_address(0) + +/* + * This must be called with lock->wait_lock held. + */ +extern void debug_mutex_set_owner(struct mutex *lock, +				  struct thread_info *new_owner __IP_DECL__); + +static inline void debug_mutex_clear_owner(struct mutex *lock) +{ +	lock->owner = NULL; +} + +extern void debug_mutex_init_waiter(struct mutex_waiter *waiter); +extern void debug_mutex_wake_waiter(struct mutex *lock, +				    struct mutex_waiter *waiter); +extern void debug_mutex_free_waiter(struct mutex_waiter *waiter); +extern void debug_mutex_add_waiter(struct mutex *lock, +				   struct mutex_waiter *waiter, +				   struct thread_info *ti __IP_DECL__); +extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, +				struct thread_info *ti); +extern void debug_mutex_unlock(struct mutex *lock); +extern void debug_mutex_init(struct mutex *lock, const char *name); + +#define debug_spin_lock(lock)				\ +	do {						\ +		local_irq_disable();			\ +		if (debug_mutex_on)			\ +			spin_lock(lock);		\ +	} while (0) + +#define debug_spin_unlock(lock)				\ +	do {						\ +		if (debug_mutex_on)			\ +			spin_unlock(lock);		\ +		local_irq_enable();			\ +		preempt_check_resched();		\ +	} while (0) + +#define debug_spin_lock_save(lock, flags)		\ +	do {						\ +		local_irq_save(flags);			\ +		if (debug_mutex_on)			\ +			spin_lock(lock);		\ +	} while (0) + +#define debug_spin_lock_restore(lock, flags)		\ +	do {						\ +		if (debug_mutex_on)			\ +			spin_unlock(lock);		\ +		local_irq_restore(flags);		\ +		preempt_check_resched();		\ +	} while (0) + +#define spin_lock_mutex(lock)				\ +	do {						\ +		struct mutex *l = container_of(lock, struct mutex, wait_lock); \ +							\ +		DEBUG_WARN_ON(in_interrupt());		\ +		debug_spin_lock(&debug_mutex_lock);	\ +		spin_lock(lock);			\ +		DEBUG_WARN_ON(l->magic != l);		\ +	} while (0) + +#define spin_unlock_mutex(lock)				\ +	do {						\ +		spin_unlock(lock);			\ +		debug_spin_unlock(&debug_mutex_lock);	\ +	} while (0) + +#define DEBUG_OFF()					\ +do {							\ +	if (debug_mutex_on) {				\ +		debug_mutex_on = 0;			\ +		console_verbose();			\ +		if (spin_is_locked(&debug_mutex_lock))	\ +			spin_unlock(&debug_mutex_lock);	\ +	}						\ +} while (0) + +#define DEBUG_BUG()					\ +do {							\ +	if (debug_mutex_on) {				\ +		DEBUG_OFF();				\ +		BUG();					\ +	}						\ +} while (0) + +#define DEBUG_WARN_ON(c)				\ +do {							\ +	if (unlikely(c && debug_mutex_on)) {		\ +		DEBUG_OFF();				\ +		WARN_ON(1);				\ +	}						\ +} while (0) + +# define DEBUG_BUG_ON(c)				\ +do {							\ +	if (unlikely(c))				\ +		DEBUG_BUG();				\ +} while (0) + +#ifdef CONFIG_SMP +# define SMP_DEBUG_WARN_ON(c)			DEBUG_WARN_ON(c) +# define SMP_DEBUG_BUG_ON(c)			DEBUG_BUG_ON(c) +#else +# define SMP_DEBUG_WARN_ON(c)			do { } while (0) +# define SMP_DEBUG_BUG_ON(c)			do { } while (0) +#endif +  |