[PATCH v3 3/3] mutex: Add ww tests to lib/locking-selftest.c. v3
This stresses the lockdep code in some ways specifically useful to ww_mutexes. It adds checks for most of the common locking errors. Changes since v1: - Add tests to verify reservation_id is untouched. - Use L() and U() macros where possible. Changes since v2: - Use the ww_mutex api directly. - Use macros for most of the code. Signed-off-by: Maarten Lankhorst --- lib/locking-selftest.c | 439 ++-- 1 file changed, 420 insertions(+), 19 deletions(-) diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c index c3eb261..9cef196 100644 --- a/lib/locking-selftest.c +++ b/lib/locking-selftest.c @@ -26,6 +26,8 @@ */ static unsigned int debug_locks_verbose; +static DEFINE_WW_CLASS(ww_lockdep); + static int __init setup_debug_locks_verbose(char *str) { get_option(, _locks_verbose); @@ -42,6 +44,10 @@ __setup("debug_locks_verbose=", setup_debug_locks_verbose); #define LOCKTYPE_RWLOCK0x2 #define LOCKTYPE_MUTEX 0x4 #define LOCKTYPE_RWSEM 0x8 +#define LOCKTYPE_WW0x10 + +static struct ww_acquire_ctx t, t2; +static struct ww_mutex o, o2; /* * Normal standalone locks, for the circular and irq-context @@ -193,6 +199,17 @@ static void init_shared_classes(void) #define RSU(x) up_read(_##x) #define RWSI(x)init_rwsem(_##x) +#define WWAI(x)ww_acquire_init(x, _lockdep) +#define WWAD(x)ww_acquire_done(x) +#define WWAF(x)ww_acquire_fini(x) + +#define WWL(x, c) ww_mutex_lock(x, c) +#define WWU(x) ww_mutex_unlock(x) + +#define WWL1(x)ww_mutex_lock_single(x) +#define WWT1(x)ww_mutex_trylock_single(x) +#define WWU1(x)ww_mutex_unlock_single(x) + #define LOCK_UNLOCK_2(x,y) LOCK(x); LOCK(y); UNLOCK(y); UNLOCK(x) /* @@ -894,11 +911,13 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft) # define I_RWLOCK(x) lockdep_reset_lock(_##x.dep_map) # define I_MUTEX(x)lockdep_reset_lock(_##x.dep_map) # define I_RWSEM(x)lockdep_reset_lock(_##x.dep_map) +# define I_WW(x) lockdep_reset_lock(_map) #else # define I_SPINLOCK(x) # define I_RWLOCK(x) # define I_MUTEX(x) # define I_RWSEM(x) +# define I_WW(x) #endif #define I1(x) \ @@ -920,11 +939,20 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft) static void reset_locks(void) { local_irq_disable(); + lockdep_free_key_range(_lockdep.acquire_key, 1); + lockdep_free_key_range(_lockdep.mutex_key, 1); + I1(A); I1(B); I1(C); I1(D); I1(X1); I1(X2); I1(Y1); I1(Y2); I1(Z1); I1(Z2); + I_WW(t); I_WW(t2); I_WW(o.base); I_WW(o2.base); lockdep_reset(); I2(A); I2(B); I2(C); I2(D); init_shared_classes(); + + ww_mutex_init(, _lockdep); ww_mutex_init(, _lockdep); + memset(, 0, sizeof(t)); memset(, 0, sizeof(t2)); + memset(_lockdep.acquire_key, 0, sizeof(ww_lockdep.acquire_key)); + memset(_lockdep.mutex_key, 0, sizeof(ww_lockdep.mutex_key)); local_irq_enable(); } @@ -938,7 +966,6 @@ static int unexpected_testcase_failures; static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask) { unsigned long saved_preempt_count = preempt_count(); - int expected_failure = 0; WARN_ON(irqs_disabled()); @@ -946,26 +973,16 @@ static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask) /* * Filter out expected failures: */ + if (debug_locks != expected) { #ifndef CONFIG_PROVE_LOCKING - if ((lockclass_mask & LOCKTYPE_SPIN) && debug_locks != expected) - expected_failure = 1; - if ((lockclass_mask & LOCKTYPE_RWLOCK) && debug_locks != expected) - expected_failure = 1; - if ((lockclass_mask & LOCKTYPE_MUTEX) && debug_locks != expected) - expected_failure = 1; - if ((lockclass_mask & LOCKTYPE_RWSEM) && debug_locks != expected) - expected_failure = 1; + expected_testcase_failures++; + printk("failed|"); +#else + unexpected_testcase_failures++; + printk("FAILED|"); + + dump_stack(); #endif - if (debug_locks != expected) { - if (expected_failure) { - expected_testcase_failures++; - printk("failed|"); - } else { - unexpected_testcase_failures++; - - printk("FAILED|"); - dump_stack(); - } } else { testcase_successes++; printk(" ok |"); @@ -1108,6 +1125,388 @@ static inline void print_testname(const char *testname) DO_TESTCASE_6IRW(desc, name, 312); \ DO_TESTCASE_6IRW(desc, name,
[PATCH v3 3/3] mutex: Add ww tests to lib/locking-selftest.c. v3
This stresses the lockdep code in some ways specifically useful to ww_mutexes. It adds checks for most of the common locking errors. Changes since v1: - Add tests to verify reservation_id is untouched. - Use L() and U() macros where possible. Changes since v2: - Use the ww_mutex api directly. - Use macros for most of the code. Signed-off-by: Maarten Lankhorst maarten.lankho...@canonical.com --- lib/locking-selftest.c | 439 ++-- 1 file changed, 420 insertions(+), 19 deletions(-) diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c index c3eb261..9cef196 100644 --- a/lib/locking-selftest.c +++ b/lib/locking-selftest.c @@ -26,6 +26,8 @@ */ static unsigned int debug_locks_verbose; +static DEFINE_WW_CLASS(ww_lockdep); + static int __init setup_debug_locks_verbose(char *str) { get_option(str, debug_locks_verbose); @@ -42,6 +44,10 @@ __setup(debug_locks_verbose=, setup_debug_locks_verbose); #define LOCKTYPE_RWLOCK0x2 #define LOCKTYPE_MUTEX 0x4 #define LOCKTYPE_RWSEM 0x8 +#define LOCKTYPE_WW0x10 + +static struct ww_acquire_ctx t, t2; +static struct ww_mutex o, o2; /* * Normal standalone locks, for the circular and irq-context @@ -193,6 +199,17 @@ static void init_shared_classes(void) #define RSU(x) up_read(rwsem_##x) #define RWSI(x)init_rwsem(rwsem_##x) +#define WWAI(x)ww_acquire_init(x, ww_lockdep) +#define WWAD(x)ww_acquire_done(x) +#define WWAF(x)ww_acquire_fini(x) + +#define WWL(x, c) ww_mutex_lock(x, c) +#define WWU(x) ww_mutex_unlock(x) + +#define WWL1(x)ww_mutex_lock_single(x) +#define WWT1(x)ww_mutex_trylock_single(x) +#define WWU1(x)ww_mutex_unlock_single(x) + #define LOCK_UNLOCK_2(x,y) LOCK(x); LOCK(y); UNLOCK(y); UNLOCK(x) /* @@ -894,11 +911,13 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft) # define I_RWLOCK(x) lockdep_reset_lock(rwlock_##x.dep_map) # define I_MUTEX(x)lockdep_reset_lock(mutex_##x.dep_map) # define I_RWSEM(x)lockdep_reset_lock(rwsem_##x.dep_map) +# define I_WW(x) lockdep_reset_lock(x.dep_map) #else # define I_SPINLOCK(x) # define I_RWLOCK(x) # define I_MUTEX(x) # define I_RWSEM(x) +# define I_WW(x) #endif #define I1(x) \ @@ -920,11 +939,20 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft) static void reset_locks(void) { local_irq_disable(); + lockdep_free_key_range(ww_lockdep.acquire_key, 1); + lockdep_free_key_range(ww_lockdep.mutex_key, 1); + I1(A); I1(B); I1(C); I1(D); I1(X1); I1(X2); I1(Y1); I1(Y2); I1(Z1); I1(Z2); + I_WW(t); I_WW(t2); I_WW(o.base); I_WW(o2.base); lockdep_reset(); I2(A); I2(B); I2(C); I2(D); init_shared_classes(); + + ww_mutex_init(o, ww_lockdep); ww_mutex_init(o2, ww_lockdep); + memset(t, 0, sizeof(t)); memset(t2, 0, sizeof(t2)); + memset(ww_lockdep.acquire_key, 0, sizeof(ww_lockdep.acquire_key)); + memset(ww_lockdep.mutex_key, 0, sizeof(ww_lockdep.mutex_key)); local_irq_enable(); } @@ -938,7 +966,6 @@ static int unexpected_testcase_failures; static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask) { unsigned long saved_preempt_count = preempt_count(); - int expected_failure = 0; WARN_ON(irqs_disabled()); @@ -946,26 +973,16 @@ static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask) /* * Filter out expected failures: */ + if (debug_locks != expected) { #ifndef CONFIG_PROVE_LOCKING - if ((lockclass_mask LOCKTYPE_SPIN) debug_locks != expected) - expected_failure = 1; - if ((lockclass_mask LOCKTYPE_RWLOCK) debug_locks != expected) - expected_failure = 1; - if ((lockclass_mask LOCKTYPE_MUTEX) debug_locks != expected) - expected_failure = 1; - if ((lockclass_mask LOCKTYPE_RWSEM) debug_locks != expected) - expected_failure = 1; + expected_testcase_failures++; + printk(failed|); +#else + unexpected_testcase_failures++; + printk(FAILED|); + + dump_stack(); #endif - if (debug_locks != expected) { - if (expected_failure) { - expected_testcase_failures++; - printk(failed|); - } else { - unexpected_testcase_failures++; - - printk(FAILED|); - dump_stack(); - } } else { testcase_successes++; printk( ok |); @@ -1108,6 +1125,388 @@ static inline void print_testname(const char *testname) DO_TESTCASE_6IRW(desc, name,