diff options
Diffstat (limited to 'include/linux/mutex.h')
| -rw-r--r-- | include/linux/mutex.h | 77 | 
1 files changed, 61 insertions, 16 deletions
diff --git a/include/linux/mutex.h b/include/linux/mutex.h index 2cb7531e7d7a..b97870f2debd 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -18,6 +18,7 @@  #include <linux/atomic.h>  #include <asm/processor.h>  #include <linux/osq_lock.h> +#include <linux/debug_locks.h>  /*   * Simple, straightforward mutexes with strict semantics: @@ -48,16 +49,12 @@   *   locks and tasks (and only those tasks)   */  struct mutex { -	/* 1: unlocked, 0: locked, negative: locked, possible waiters */ -	atomic_t		count; +	atomic_long_t		owner;  	spinlock_t		wait_lock; -	struct list_head	wait_list; -#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER) -	struct task_struct	*owner; -#endif  #ifdef CONFIG_MUTEX_SPIN_ON_OWNER  	struct optimistic_spin_queue osq; /* Spinner MCS lock */  #endif +	struct list_head	wait_list;  #ifdef CONFIG_DEBUG_MUTEXES  	void			*magic;  #endif @@ -66,6 +63,11 @@ struct mutex {  #endif  }; +static inline struct task_struct *__mutex_owner(struct mutex *lock) +{ +	return (struct task_struct *)(atomic_long_read(&lock->owner) & ~0x03); +} +  /*   * This is the control structure for tasks blocked on mutex,   * which resides on the blocked task's kernel stack: @@ -79,9 +81,20 @@ struct mutex_waiter {  };  #ifdef CONFIG_DEBUG_MUTEXES -# include <linux/mutex-debug.h> + +#define __DEBUG_MUTEX_INITIALIZER(lockname)				\ +	, .magic = &lockname + +extern void mutex_destroy(struct mutex *lock); +  #else +  # define __DEBUG_MUTEX_INITIALIZER(lockname) + +static inline void mutex_destroy(struct mutex *lock) {} + +#endif +  /**   * mutex_init - initialize the mutex   * @mutex: the mutex to be initialized @@ -90,14 +103,12 @@ struct mutex_waiter {   *   * It is not allowed to initialize an already locked mutex.   */ -# define mutex_init(mutex) \ -do {							\ -	static struct lock_class_key __key;		\ -							\ -	__mutex_init((mutex), #mutex, &__key);		\ +#define mutex_init(mutex)						\ +do {									\ +	static struct lock_class_key __key;				\ +									\ +	__mutex_init((mutex), #mutex, &__key);				\  } while (0) -static inline void mutex_destroy(struct mutex *lock) {} -#endif  #ifdef CONFIG_DEBUG_LOCK_ALLOC  # define __DEP_MAP_MUTEX_INITIALIZER(lockname) \ @@ -107,7 +118,7 @@ static inline void mutex_destroy(struct mutex *lock) {}  #endif  #define __MUTEX_INITIALIZER(lockname) \ -		{ .count = ATOMIC_INIT(1) \ +		{ .owner = ATOMIC_LONG_INIT(0) \  		, .wait_lock = __SPIN_LOCK_UNLOCKED(lockname.wait_lock) \  		, .wait_list = LIST_HEAD_INIT(lockname.wait_list) \  		__DEBUG_MUTEX_INITIALIZER(lockname) \ @@ -127,7 +138,10 @@ extern void __mutex_init(struct mutex *lock, const char *name,   */  static inline int mutex_is_locked(struct mutex *lock)  { -	return atomic_read(&lock->count) != 1; +	/* +	 * XXX think about spin_is_locked +	 */ +	return __mutex_owner(lock) != NULL;  }  /* @@ -175,4 +189,35 @@ extern void mutex_unlock(struct mutex *lock);  extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock); +/* + * These values are chosen such that FAIL and SUCCESS match the + * values of the regular mutex_trylock(). + */ +enum mutex_trylock_recursive_enum { +	MUTEX_TRYLOCK_FAILED    = 0, +	MUTEX_TRYLOCK_SUCCESS   = 1, +	MUTEX_TRYLOCK_RECURSIVE, +}; + +/** + * mutex_trylock_recursive - trylock variant that allows recursive locking + * @lock: mutex to be locked + * + * This function should not be used, _ever_. It is purely for hysterical GEM + * raisins, and once those are gone this will be removed. + * + * Returns: + *  MUTEX_TRYLOCK_FAILED    - trylock failed, + *  MUTEX_TRYLOCK_SUCCESS   - lock acquired, + *  MUTEX_TRYLOCK_RECURSIVE - we already owned the lock. + */ +static inline /* __deprecated */ __must_check enum mutex_trylock_recursive_enum +mutex_trylock_recursive(struct mutex *lock) +{ +	if (unlikely(__mutex_owner(lock) == current)) +		return MUTEX_TRYLOCK_RECURSIVE; + +	return mutex_trylock(lock); +} +  #endif /* __LINUX_MUTEX_H */  | 
