Lockdep is not able to detect simple rw deadlocks because it is not tracking recursive read dependencies: read_lock(A) --> spin_lock(B) spin_lock(B) --> write_lock(A) /* should fail */ Furthermore, the following should not result in a deadlock for recursive read locks: read_lock(A) --> spin_lock(B) spin_lock(B) --> read_lock(A) /* success */ Add these checks so that we may improve lockdep to accurately track recursive read locks and report the correct answers. Signed-off-by: Peter Zijlstra --- lib/locking-selftest.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) Index: tip/lib/locking-selftest.c =================================================================== --- tip.orig/lib/locking-selftest.c +++ tip/lib/locking-selftest.c @@ -185,13 +185,16 @@ static void init_shared_classes(void) #define ML(x) mutex_lock(&mutex_##x) #define MU(x) mutex_unlock(&mutex_##x) +#define MLU(x) ML(x); MU(x) #define MI(x) mutex_init(&mutex_##x) #define WSL(x) down_write(&rwsem_##x) #define WSU(x) up_write(&rwsem_##x) +#define WSLU(x) WSL(x); WSU(x) #define RSL(x) down_read(&rwsem_##x) #define RSU(x) up_read(&rwsem_##x) +#define RSLU(x) RSL(x); RSU(x) #define RWSI(x) init_rwsem(&rwsem_##x) #define LOCK_UNLOCK_2(x,y) LOCK(x); LOCK(y); UNLOCK(y); UNLOCK(x) @@ -300,6 +303,50 @@ static void rsem_AA3(void) RSL(X2); // this one should fail } +static void rwlock_spinlock_ABBA(void) +{ + RL(A); + LU(B); + RU(A); + + L(B); + WLU(A); /* fail */ + U(B); +} + +static void rlock_spinlock_ABBA(void) +{ + RL(A); + LU(B); + RU(A); + + L(B); + RLU(A); /* not fail */ + U(B); +} + +static void rwsem_mutex_ABBA(void) +{ + RSL(A); + MLU(B); + RSU(A); + + ML(B); + WSLU(A); /* fail */ + MU(B); +} + +static void rsem_mutex_ABBA(void) +{ + RSL(A); + MLU(B); + RSU(A); + + ML(B); + RSLU(A); /* fail */ + MU(B); +} + /* * ABBA deadlock: */ @@ -1174,6 +1221,20 @@ void locking_selftest(void) dotest(rsem_AA3, FAILURE, LOCKTYPE_RWSEM); printk("\n"); + print_testname("mixed write-spin-read-lock"); + printk(" |"); + dotest(rwlock_spinlock_ABBA, FAILURE, LOCKTYPE_RWLOCK); + printk(" |"); + dotest(rwsem_mutex_ABBA, FAILURE, LOCKTYPE_RWSEM); + printk("\n"); + + print_testname("mixed read-spin-read-lock"); + printk(" |"); + dotest(rlock_spinlock_ABBA, SUCCESS, LOCKTYPE_RWLOCK); + printk(" |"); + dotest(rsem_mutex_ABBA, FAILURE, LOCKTYPE_RWSEM); + printk("\n"); + printk(" --------------------------------------------------------------------------\n"); /* -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/