diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2016-12-01 06:47:05 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-01-14 05:37:14 -0500 |
commit | 0186a6cbdc6287fde65858e5d9c714dc167b8ace (patch) | |
tree | 7f9d7eac00704e67959e5786c7d2b94cecf739a6 | |
parent | af2e859edd477fa1ea3d1d106f41a595cff3d162 (diff) |
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>
4 files changed, 81 insertions, 0 deletions
diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index f8c5af52a131..9bffedd82884 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c | |||
@@ -372,6 +372,78 @@ static struct lock_torture_ops mutex_lock_ops = { | |||
372 | .name = "mutex_lock" | 372 | .name = "mutex_lock" |
373 | }; | 373 | }; |
374 | 374 | ||
375 | #include <linux/ww_mutex.h> | ||
376 | static DEFINE_WW_CLASS(torture_ww_class); | ||
377 | static DEFINE_WW_MUTEX(torture_ww_mutex_0, &torture_ww_class); | ||
378 | static DEFINE_WW_MUTEX(torture_ww_mutex_1, &torture_ww_class); | ||
379 | static DEFINE_WW_MUTEX(torture_ww_mutex_2, &torture_ww_class); | ||
380 | |||
381 | static int torture_ww_mutex_lock(void) | ||
382 | __acquires(torture_ww_mutex_0) | ||
383 | __acquires(torture_ww_mutex_1) | ||
384 | __acquires(torture_ww_mutex_2) | ||
385 | { | ||
386 | LIST_HEAD(list); | ||
387 | struct reorder_lock { | ||
388 | struct list_head link; | ||
389 | struct ww_mutex *lock; | ||
390 | } locks[3], *ll, *ln; | ||
391 | struct ww_acquire_ctx ctx; | ||
392 | |||
393 | locks[0].lock = &torture_ww_mutex_0; | ||
394 | list_add(&locks[0].link, &list); | ||
395 | |||
396 | locks[1].lock = &torture_ww_mutex_1; | ||
397 | list_add(&locks[1].link, &list); | ||
398 | |||
399 | locks[2].lock = &torture_ww_mutex_2; | ||
400 | list_add(&locks[2].link, &list); | ||
401 | |||
402 | ww_acquire_init(&ctx, &torture_ww_class); | ||
403 | |||
404 | list_for_each_entry(ll, &list, link) { | ||
405 | int err; | ||
406 | |||
407 | err = ww_mutex_lock(ll->lock, &ctx); | ||
408 | if (!err) | ||
409 | continue; | ||
410 | |||
411 | ln = ll; | ||
412 | list_for_each_entry_continue_reverse(ln, &list, link) | ||
413 | ww_mutex_unlock(ln->lock); | ||
414 | |||
415 | if (err != -EDEADLK) | ||
416 | return err; | ||
417 | |||
418 | ww_mutex_lock_slow(ll->lock, &ctx); | ||
419 | list_move(&ll->link, &list); | ||
420 | } | ||
421 | |||
422 | ww_acquire_fini(&ctx); | ||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static void torture_ww_mutex_unlock(void) | ||
427 | __releases(torture_ww_mutex_0) | ||
428 | __releases(torture_ww_mutex_1) | ||
429 | __releases(torture_ww_mutex_2) | ||
430 | { | ||
431 | ww_mutex_unlock(&torture_ww_mutex_0); | ||
432 | ww_mutex_unlock(&torture_ww_mutex_1); | ||
433 | ww_mutex_unlock(&torture_ww_mutex_2); | ||
434 | } | ||
435 | |||
436 | static struct lock_torture_ops ww_mutex_lock_ops = { | ||
437 | .writelock = torture_ww_mutex_lock, | ||
438 | .write_delay = torture_mutex_delay, | ||
439 | .task_boost = torture_boost_dummy, | ||
440 | .writeunlock = torture_ww_mutex_unlock, | ||
441 | .readlock = NULL, | ||
442 | .read_delay = NULL, | ||
443 | .readunlock = NULL, | ||
444 | .name = "ww_mutex_lock" | ||
445 | }; | ||
446 | |||
375 | #ifdef CONFIG_RT_MUTEXES | 447 | #ifdef CONFIG_RT_MUTEXES |
376 | static DEFINE_RT_MUTEX(torture_rtmutex); | 448 | static DEFINE_RT_MUTEX(torture_rtmutex); |
377 | 449 | ||
@@ -793,6 +865,7 @@ static int __init lock_torture_init(void) | |||
793 | &spin_lock_ops, &spin_lock_irq_ops, | 865 | &spin_lock_ops, &spin_lock_irq_ops, |
794 | &rw_lock_ops, &rw_lock_irq_ops, | 866 | &rw_lock_ops, &rw_lock_irq_ops, |
795 | &mutex_lock_ops, | 867 | &mutex_lock_ops, |
868 | &ww_mutex_lock_ops, | ||
796 | #ifdef CONFIG_RT_MUTEXES | 869 | #ifdef CONFIG_RT_MUTEXES |
797 | &rtmutex_lock_ops, | 870 | &rtmutex_lock_ops, |
798 | #endif | 871 | #endif |
diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFLIST b/tools/testing/selftests/rcutorture/configs/lock/CFLIST index b9611c523723..41bae5824339 100644 --- a/tools/testing/selftests/rcutorture/configs/lock/CFLIST +++ b/tools/testing/selftests/rcutorture/configs/lock/CFLIST | |||
@@ -4,3 +4,4 @@ LOCK03 | |||
4 | LOCK04 | 4 | LOCK04 |
5 | LOCK05 | 5 | LOCK05 |
6 | LOCK06 | 6 | LOCK06 |
7 | LOCK07 | ||
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK07 b/tools/testing/selftests/rcutorture/configs/lock/LOCK07 new file mode 100644 index 000000000000..1d1da1477fc3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK07 | |||
@@ -0,0 +1,6 @@ | |||
1 | CONFIG_SMP=y | ||
2 | CONFIG_NR_CPUS=4 | ||
3 | CONFIG_HOTPLUG_CPU=y | ||
4 | CONFIG_PREEMPT_NONE=n | ||
5 | CONFIG_PREEMPT_VOLUNTARY=n | ||
6 | CONFIG_PREEMPT=y | ||
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK07.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK07.boot new file mode 100644 index 000000000000..97dadd1a9e45 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK07.boot | |||
@@ -0,0 +1 @@ | |||
locktorture.torture_type=ww_mutex_lock | |||