2006-01-10 02:59:20 +03:00
/*
* kernel / mutex - debug . c
*
* Debugging code for mutexes
*
* Started by Ingo Molnar :
*
* Copyright ( C ) 2004 , 2005 , 2006 Red Hat , Inc . , Ingo Molnar < mingo @ redhat . com >
*
* lock debugging , locking tree , deadlock detection started by :
*
* Copyright ( C ) 2004 , LynuxWorks , Inc . , Igor Manyilov , Bill Huey
* Released under the General Public License ( GPL ) .
*/
# include <linux/mutex.h>
# include <linux/delay.h>
# include <linux/module.h>
2006-06-27 13:53:54 +04:00
# include <linux/poison.h>
2006-01-10 02:59:20 +03:00
# include <linux/spinlock.h>
# include <linux/kallsyms.h>
# include <linux/interrupt.h>
2006-07-03 11:24:33 +04:00
# include <linux/debug_locks.h>
2006-01-10 02:59:20 +03:00
# include "mutex-debug.h"
/*
* Must be called with lock - > wait_lock held .
*/
2006-07-03 11:24:33 +04:00
void debug_mutex_set_owner ( struct mutex * lock , struct thread_info * new_owner )
2006-01-10 02:59:20 +03:00
{
lock - > owner = new_owner ;
}
2006-07-03 11:24:33 +04:00
void debug_mutex_lock_common ( struct mutex * lock , struct mutex_waiter * waiter )
2006-01-10 02:59:20 +03:00
{
2006-06-27 13:53:54 +04:00
memset ( waiter , MUTEX_DEBUG_INIT , sizeof ( * waiter ) ) ;
2006-01-10 02:59:20 +03:00
waiter - > magic = waiter ;
INIT_LIST_HEAD ( & waiter - > list ) ;
}
void debug_mutex_wake_waiter ( struct mutex * lock , struct mutex_waiter * waiter )
{
2006-07-03 11:24:30 +04:00
SMP_DEBUG_LOCKS_WARN_ON ( ! spin_is_locked ( & lock - > wait_lock ) ) ;
DEBUG_LOCKS_WARN_ON ( list_empty ( & lock - > wait_list ) ) ;
DEBUG_LOCKS_WARN_ON ( waiter - > magic ! = waiter ) ;
DEBUG_LOCKS_WARN_ON ( list_empty ( & waiter - > list ) ) ;
2006-01-10 02:59:20 +03:00
}
void debug_mutex_free_waiter ( struct mutex_waiter * waiter )
{
2006-07-03 11:24:30 +04:00
DEBUG_LOCKS_WARN_ON ( ! list_empty ( & waiter - > list ) ) ;
2006-06-27 13:53:54 +04:00
memset ( waiter , MUTEX_DEBUG_FREE , sizeof ( * waiter ) ) ;
2006-01-10 02:59:20 +03:00
}
void debug_mutex_add_waiter ( struct mutex * lock , struct mutex_waiter * waiter ,
2006-07-03 11:24:33 +04:00
struct thread_info * ti )
2006-01-10 02:59:20 +03:00
{
2006-07-03 11:24:30 +04:00
SMP_DEBUG_LOCKS_WARN_ON ( ! spin_is_locked ( & lock - > wait_lock ) ) ;
2006-07-03 11:24:33 +04:00
2006-01-10 02:59:20 +03:00
/* Mark the current thread as blocked on the lock: */
ti - > task - > blocked_on = waiter ;
waiter - > lock = lock ;
}
void mutex_remove_waiter ( struct mutex * lock , struct mutex_waiter * waiter ,
struct thread_info * ti )
{
2006-07-03 11:24:30 +04:00
DEBUG_LOCKS_WARN_ON ( list_empty ( & waiter - > list ) ) ;
DEBUG_LOCKS_WARN_ON ( waiter - > task ! = ti - > task ) ;
DEBUG_LOCKS_WARN_ON ( ti - > task - > blocked_on ! = waiter ) ;
2006-01-10 02:59:20 +03:00
ti - > task - > blocked_on = NULL ;
list_del_init ( & waiter - > list ) ;
waiter - > task = NULL ;
}
void debug_mutex_unlock ( struct mutex * lock )
{
2006-12-07 07:39:32 +03:00
if ( unlikely ( ! debug_locks ) )
return ;
2006-07-03 11:24:33 +04:00
DEBUG_LOCKS_WARN_ON ( lock - > owner ! = current_thread_info ( ) ) ;
2006-07-03 11:24:30 +04:00
DEBUG_LOCKS_WARN_ON ( lock - > magic ! = lock ) ;
DEBUG_LOCKS_WARN_ON ( ! lock - > wait_list . prev & & ! lock - > wait_list . next ) ;
DEBUG_LOCKS_WARN_ON ( lock - > owner ! = current_thread_info ( ) ) ;
2006-01-10 02:59:20 +03:00
}
2006-07-03 11:24:55 +04:00
void debug_mutex_init ( struct mutex * lock , const char * name ,
struct lock_class_key * key )
2006-01-10 02:59:20 +03:00
{
2006-07-03 11:24:55 +04:00
# ifdef CONFIG_DEBUG_LOCK_ALLOC
2006-01-10 02:59:20 +03:00
/*
* Make sure we are not reinitializing a held lock :
*/
2006-07-03 11:24:33 +04:00
debug_check_no_locks_freed ( ( void * ) lock , sizeof ( * lock ) ) ;
2006-10-11 09:45:14 +04:00
lockdep_init_map ( & lock - > dep_map , name , key , 0 ) ;
2006-07-03 11:24:55 +04:00
# endif
2006-01-10 02:59:20 +03:00
lock - > owner = NULL ;
lock - > magic = lock ;
}
/***
* mutex_destroy - mark a mutex unusable
* @ lock : the mutex to be destroyed
*
* This function marks the mutex uninitialized , and any subsequent
* use of the mutex is forbidden . The mutex must not be locked when
* this function is called .
*/
void fastcall mutex_destroy ( struct mutex * lock )
{
2006-07-03 11:24:30 +04:00
DEBUG_LOCKS_WARN_ON ( mutex_is_locked ( lock ) ) ;
2006-01-10 02:59:20 +03:00
lock - > magic = NULL ;
}
EXPORT_SYMBOL_GPL ( mutex_destroy ) ;