Commit 0c46d68d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'core-mutexes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull WW mutex support from Ingo Molnar:
 "This tree adds support for wound/wait style locks, which the graphics
  guys would like to make use of in the TTM graphics subsystem.

  Wound/wait mutexes are used when other multiple lock acquisitions of a
  similar type can be done in an arbitrary order.  The deadlock handling
  used here is called wait/wound in the RDBMS literature: The older
  tasks waits until it can acquire the contended lock.  The younger
  tasks needs to back off and drop all the locks it is currently
  holding, ie the younger task is wounded.

  See this LWN.net description of W/W mutexes:

     https://lwn.net/Articles/548909/

  The comments there outline specific usecases for this facility (which
  have already been implemented for the DRM tree).

  Also see Documentation/ww-mutex-design.txt for more details"

* 'core-mutexes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  locking-selftests: Handle unexpected failures more strictly
  mutex: Add more w/w tests to test EDEADLK path handling
  mutex: Add more tests to lib/locking-selftest.c
  mutex: Add w/w tests to lib/locking-selftest.c
  mutex: Add w/w mutex slowpath debugging
  mutex: Add support for wound/wait style locks
  arch: Make __mutex_fastpath_lock_retval return whether fastpath succeeded or not
parents 3e42dee6 166989e3
This diff is collapsed.
......@@ -29,17 +29,15 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
* from 1 to a 0 value
* @count: pointer of type atomic_t
* @fail_fn: function to call if the original value was not 1
*
* Change the count from 1 to a value lower than 1, and call <fail_fn> if
* it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
* or anything the slow path function returns.
* Change the count from 1 to a value lower than 1. This function returns 0
* if the fastpath succeeds, or -1 otherwise.
*/
static inline int
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
__mutex_fastpath_lock_retval(atomic_t *count)
{
if (unlikely(ia64_fetchadd4_acq(count, -1) != 1))
return fail_fn(count);
return -1;
return 0;
}
......
......@@ -82,17 +82,15 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
* from 1 to a 0 value
* @count: pointer of type atomic_t
* @fail_fn: function to call if the original value was not 1
*
* Change the count from 1 to a value lower than 1, and call <fail_fn> if
* it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
* or anything the slow path function returns.
* Change the count from 1 to a value lower than 1. This function returns 0
* if the fastpath succeeds, or -1 otherwise.
*/
static inline int
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
__mutex_fastpath_lock_retval(atomic_t *count)
{
if (unlikely(__mutex_dec_return_lock(count) < 0))
return fail_fn(count);
return -1;
return 0;
}
......
......@@ -37,7 +37,7 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
}
static inline int
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
__mutex_fastpath_lock_retval(atomic_t *count)
{
int __done, __res;
......@@ -51,7 +51,7 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
: "t");
if (unlikely(!__done || __res != 0))
__res = fail_fn(count);
__res = -1;
return __res;
}
......
......@@ -42,17 +42,14 @@ do { \
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
* from 1 to a 0 value
* @count: pointer of type atomic_t
* @fail_fn: function to call if the original value was not 1
*
* Change the count from 1 to a value lower than 1, and call <fail_fn> if it
* wasn't 1 originally. This function returns 0 if the fastpath succeeds,
* or anything the slow path function returns
* Change the count from 1 to a value lower than 1. This function returns 0
* if the fastpath succeeds, or -1 otherwise.
*/
static inline int __mutex_fastpath_lock_retval(atomic_t *count,
int (*fail_fn)(atomic_t *))
static inline int __mutex_fastpath_lock_retval(atomic_t *count)
{
if (unlikely(atomic_dec_return(count) < 0))
return fail_fn(count);
return -1;
else
return 0;
}
......
......@@ -37,17 +37,14 @@ do { \
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
* from 1 to a 0 value
* @count: pointer of type atomic_t
* @fail_fn: function to call if the original value was not 1
*
* Change the count from 1 to a value lower than 1, and call <fail_fn> if
* it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
* or anything the slow path function returns
* Change the count from 1 to a value lower than 1. This function returns 0
* if the fastpath succeeds, or -1 otherwise.
*/
static inline int __mutex_fastpath_lock_retval(atomic_t *count,
int (*fail_fn)(atomic_t *))
static inline int __mutex_fastpath_lock_retval(atomic_t *count)
{
if (unlikely(atomic_dec_return(count) < 0))
return fail_fn(count);
return -1;
else
return 0;
}
......
......@@ -28,17 +28,15 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
* from 1 to a 0 value
* @count: pointer of type atomic_t
* @fail_fn: function to call if the original value was not 1
*
* Change the count from 1 to a value lower than 1, and call <fail_fn> if
* it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
* or anything the slow path function returns.
* Change the count from 1 to a value lower than 1. This function returns 0
* if the fastpath succeeds, or -1 otherwise.
*/
static inline int
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
__mutex_fastpath_lock_retval(atomic_t *count)
{
if (unlikely(atomic_dec_return(count) < 0))
return fail_fn(count);
return -1;
return 0;
}
......
......@@ -11,7 +11,7 @@
#define _ASM_GENERIC_MUTEX_NULL_H
#define __mutex_fastpath_lock(count, fail_fn) fail_fn(count)
#define __mutex_fastpath_lock_retval(count, fail_fn) fail_fn(count)
#define __mutex_fastpath_lock_retval(count) (-1)
#define __mutex_fastpath_unlock(count, fail_fn) fail_fn(count)
#define __mutex_fastpath_trylock(count, fail_fn) fail_fn(count)
#define __mutex_slowpath_needs_to_unlock() 1
......
......@@ -39,18 +39,16 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
* from 1 to a 0 value
* @count: pointer of type atomic_t
* @fail_fn: function to call if the original value was not 1
*
* Change the count from 1 to a value lower than 1, and call <fail_fn> if it
* wasn't 1 originally. This function returns 0 if the fastpath succeeds,
* or anything the slow path function returns
* Change the count from 1 to a value lower than 1. This function returns 0
* if the fastpath succeeds, or -1 otherwise.
*/
static inline int
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
__mutex_fastpath_lock_retval(atomic_t *count)
{
if (unlikely(atomic_xchg(count, 0) != 1))
if (likely(atomic_xchg(count, -1) != 1))
return fail_fn(count);
return -1;
return 0;
}
......
......@@ -3,6 +3,7 @@
#include <linux/linkage.h>
#include <linux/lockdep.h>
#include <linux/debug_locks.h>
/*
* Mutexes - debugging helpers:
......
This diff is collapsed.
This diff is collapsed.
......@@ -547,6 +547,19 @@ config DEBUG_MUTEXES
This feature allows mutex semantics violations to be detected and
reported.
config DEBUG_WW_MUTEX_SLOWPATH
bool "Wait/wound mutex debugging: Slowpath testing"
depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
select DEBUG_LOCK_ALLOC
select DEBUG_SPINLOCK
select DEBUG_MUTEXES
help
This feature enables slowpath testing for w/w mutex users by
injecting additional -EDEADLK wound/backoff cases. Together with
the full mutex checks enabled with (CONFIG_PROVE_LOCKING) this
will test all possible w/w mutex interface abuse with the
exception of simply not acquiring all the required locks.
config DEBUG_LOCK_ALLOC
bool "Lock debugging: detect incorrect freeing of live locks"
depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
......
......@@ -30,6 +30,7 @@ EXPORT_SYMBOL_GPL(debug_locks);
* a locking bug is detected.
*/
int debug_locks_silent;
EXPORT_SYMBOL_GPL(debug_locks_silent);
/*
* Generic 'turn off all lock debugging' function:
......@@ -44,3 +45,4 @@ int debug_locks_off(void)
}
return 0;
}
EXPORT_SYMBOL_GPL(debug_locks_off);
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment