forked from Minki/linux
locking/ww_mutex: Add ww_mutex to locktorture test
Although ww_mutexes degenerate into mutexes, it would be useful to torture the deadlock handling between multiple ww_mutexes in addition to torturing the regular mutexes. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Maarten Lankhorst <dev@mblankhorst.nl> Cc: Nicolai Hähnle <nhaehnle@gmail.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20161201114711.28697-3-chris@chris-wilson.co.uk Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
af2e859edd
commit
0186a6cbdc
@ -372,6 +372,78 @@ static struct lock_torture_ops mutex_lock_ops = {
|
||||
.name = "mutex_lock"
|
||||
};
|
||||
|
||||
#include <linux/ww_mutex.h>
|
||||
static DEFINE_WW_CLASS(torture_ww_class);
|
||||
static DEFINE_WW_MUTEX(torture_ww_mutex_0, &torture_ww_class);
|
||||
static DEFINE_WW_MUTEX(torture_ww_mutex_1, &torture_ww_class);
|
||||
static DEFINE_WW_MUTEX(torture_ww_mutex_2, &torture_ww_class);
|
||||
|
||||
static int torture_ww_mutex_lock(void)
|
||||
__acquires(torture_ww_mutex_0)
|
||||
__acquires(torture_ww_mutex_1)
|
||||
__acquires(torture_ww_mutex_2)
|
||||
{
|
||||
LIST_HEAD(list);
|
||||
struct reorder_lock {
|
||||
struct list_head link;
|
||||
struct ww_mutex *lock;
|
||||
} locks[3], *ll, *ln;
|
||||
struct ww_acquire_ctx ctx;
|
||||
|
||||
locks[0].lock = &torture_ww_mutex_0;
|
||||
list_add(&locks[0].link, &list);
|
||||
|
||||
locks[1].lock = &torture_ww_mutex_1;
|
||||
list_add(&locks[1].link, &list);
|
||||
|
||||
locks[2].lock = &torture_ww_mutex_2;
|
||||
list_add(&locks[2].link, &list);
|
||||
|
||||
ww_acquire_init(&ctx, &torture_ww_class);
|
||||
|
||||
list_for_each_entry(ll, &list, link) {
|
||||
int err;
|
||||
|
||||
err = ww_mutex_lock(ll->lock, &ctx);
|
||||
if (!err)
|
||||
continue;
|
||||
|
||||
ln = ll;
|
||||
list_for_each_entry_continue_reverse(ln, &list, link)
|
||||
ww_mutex_unlock(ln->lock);
|
||||
|
||||
if (err != -EDEADLK)
|
||||
return err;
|
||||
|
||||
ww_mutex_lock_slow(ll->lock, &ctx);
|
||||
list_move(&ll->link, &list);
|
||||
}
|
||||
|
||||
ww_acquire_fini(&ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void torture_ww_mutex_unlock(void)
|
||||
__releases(torture_ww_mutex_0)
|
||||
__releases(torture_ww_mutex_1)
|
||||
__releases(torture_ww_mutex_2)
|
||||
{
|
||||
ww_mutex_unlock(&torture_ww_mutex_0);
|
||||
ww_mutex_unlock(&torture_ww_mutex_1);
|
||||
ww_mutex_unlock(&torture_ww_mutex_2);
|
||||
}
|
||||
|
||||
static struct lock_torture_ops ww_mutex_lock_ops = {
|
||||
.writelock = torture_ww_mutex_lock,
|
||||
.write_delay = torture_mutex_delay,
|
||||
.task_boost = torture_boost_dummy,
|
||||
.writeunlock = torture_ww_mutex_unlock,
|
||||
.readlock = NULL,
|
||||
.read_delay = NULL,
|
||||
.readunlock = NULL,
|
||||
.name = "ww_mutex_lock"
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RT_MUTEXES
|
||||
static DEFINE_RT_MUTEX(torture_rtmutex);
|
||||
|
||||
@ -793,6 +865,7 @@ static int __init lock_torture_init(void)
|
||||
&spin_lock_ops, &spin_lock_irq_ops,
|
||||
&rw_lock_ops, &rw_lock_irq_ops,
|
||||
&mutex_lock_ops,
|
||||
&ww_mutex_lock_ops,
|
||||
#ifdef CONFIG_RT_MUTEXES
|
||||
&rtmutex_lock_ops,
|
||||
#endif
|
||||
|
@ -4,3 +4,4 @@ LOCK03
|
||||
LOCK04
|
||||
LOCK05
|
||||
LOCK06
|
||||
LOCK07
|
||||
|
6
tools/testing/selftests/rcutorture/configs/lock/LOCK07
Normal file
6
tools/testing/selftests/rcutorture/configs/lock/LOCK07
Normal file
@ -0,0 +1,6 @@
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_HOTPLUG_CPU=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=y
|
@ -0,0 +1 @@
|
||||
locktorture.torture_type=ww_mutex_lock
|
Loading…
Reference in New Issue
Block a user