Skip to content

Commit

Permalink
locking/lockdep/selftests: Add mixed read-write ABBA tests
Browse files Browse the repository at this point in the history
Currently lockdep has limited support for recursive readers, add a few
mixed read-write ABBA selftests to show the extend of these
limitations.

  [    0.000000] ----------------------------------------------------------------------------
  [    0.000000]                                  | spin |wlock |rlock |mutex | wsem | rsem |
  [    0.000000]   --------------------------------------------------------------------------

  [    0.000000]   mixed read-lock/lock-write ABBA:             |FAILED|             |  ok  |
  [    0.000000]    mixed read-lock/lock-read ABBA:             |  ok  |             |  ok  |
  [    0.000000]  mixed write-lock/lock-write ABBA:             |  ok  |             |  ok  |

This clearly illustrates the case where lockdep fails to find a
deadlock.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: boqun.feng@gmail.com
Cc: byungchul.park@lge.com
Cc: david@fromorbit.com
Cc: johannes@sipsolutions.net
Cc: oleg@redhat.com
Cc: tj@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Peter Zijlstra authored and Ingo Molnar committed Aug 25, 2017
1 parent 0e70970 commit e914985
Showing 1 changed file with 115 additions and 2 deletions.
117 changes: 115 additions & 2 deletions lib/locking-selftest.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,103 @@ static void rsem_AA3(void)
RSL(X2); // this one should fail
}

/*
* read_lock(A)
* spin_lock(B)
* spin_lock(B)
* write_lock(A)
*/
static void rlock_ABBA1(void)
{
RL(X1);
L(Y1);
U(Y1);
RU(X1);

L(Y1);
WL(X1);
WU(X1);
U(Y1); // should fail
}

static void rwsem_ABBA1(void)
{
RSL(X1);
ML(Y1);
MU(Y1);
RSU(X1);

ML(Y1);
WSL(X1);
WSU(X1);
MU(Y1); // should fail
}

/*
* read_lock(A)
* spin_lock(B)
* spin_lock(B)
* read_lock(A)
*/
static void rlock_ABBA2(void)
{
RL(X1);
L(Y1);
U(Y1);
RU(X1);

L(Y1);
RL(X1);
RU(X1);
U(Y1); // should NOT fail
}

static void rwsem_ABBA2(void)
{
RSL(X1);
ML(Y1);
MU(Y1);
RSU(X1);

ML(Y1);
RSL(X1);
RSU(X1);
MU(Y1); // should fail
}


/*
* write_lock(A)
* spin_lock(B)
* spin_lock(B)
* write_lock(A)
*/
static void rlock_ABBA3(void)
{
WL(X1);
L(Y1);
U(Y1);
WU(X1);

L(Y1);
WL(X1);
WU(X1);
U(Y1); // should fail
}

static void rwsem_ABBA3(void)
{
WSL(X1);
ML(Y1);
MU(Y1);
WSU(X1);

ML(Y1);
WSL(X1);
WSU(X1);
MU(Y1); // should fail
}

/*
* ABBA deadlock:
*/
Expand Down Expand Up @@ -1056,8 +1153,6 @@ static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask)
if (debug_locks != expected) {
unexpected_testcase_failures++;
pr_cont("FAILED|");

dump_stack();
} else {
testcase_successes++;
pr_cont(" ok |");
Expand Down Expand Up @@ -1933,6 +2028,24 @@ void locking_selftest(void)
dotest(rsem_AA3, FAILURE, LOCKTYPE_RWSEM);
pr_cont("\n");

print_testname("mixed read-lock/lock-write ABBA");
pr_cont(" |");
dotest(rlock_ABBA1, FAILURE, LOCKTYPE_RWLOCK);
pr_cont(" |");
dotest(rwsem_ABBA1, FAILURE, LOCKTYPE_RWSEM);

print_testname("mixed read-lock/lock-read ABBA");
pr_cont(" |");
dotest(rlock_ABBA2, SUCCESS, LOCKTYPE_RWLOCK);
pr_cont(" |");
dotest(rwsem_ABBA2, FAILURE, LOCKTYPE_RWSEM);

print_testname("mixed write-lock/lock-write ABBA");
pr_cont(" |");
dotest(rlock_ABBA3, FAILURE, LOCKTYPE_RWLOCK);
pr_cont(" |");
dotest(rwsem_ABBA3, FAILURE, LOCKTYPE_RWSEM);

printk(" --------------------------------------------------------------------------\n");

/*
Expand Down

0 comments on commit e914985

Please sign in to comment.