aboutsummaryrefslogtreecommitdiffstats
path: root/lib/locking-selftest.c
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>2013-06-20 07:31:24 -0400
committerIngo Molnar <mingo@kernel.org>2013-06-26 06:10:57 -0400
commit1de994452f44005e4b1f5c6c77eae4a26f86d484 (patch)
treee8de47c719892694c3586d52c421be285639f888 /lib/locking-selftest.c
parent230100276955529d5a7c69207421756b9a61a8e5 (diff)
mutex: Add w/w tests to lib/locking-selftest.c
This stresses the lockdep code in some ways specifically useful to ww_mutexes. It adds checks for most of the common locking errors. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-sig@lists.linaro.org Cc: robclark@gmail.com Cc: rostedt@goodmis.org Cc: daniel@ffwll.ch Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20130620113124.4001.23186.stgit@patser Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'lib/locking-selftest.c')
-rw-r--r--lib/locking-selftest.c400
1 files changed, 381 insertions, 19 deletions
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index c3eb261a7df3..996226224bcf 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -26,6 +26,8 @@
26 */ 26 */
27static unsigned int debug_locks_verbose; 27static unsigned int debug_locks_verbose;
28 28
29static DEFINE_WW_CLASS(ww_lockdep);
30
29static int __init setup_debug_locks_verbose(char *str) 31static int __init setup_debug_locks_verbose(char *str)
30{ 32{
31 get_option(&str, &debug_locks_verbose); 33 get_option(&str, &debug_locks_verbose);
@@ -42,6 +44,10 @@ __setup("debug_locks_verbose=", setup_debug_locks_verbose);
42#define LOCKTYPE_RWLOCK 0x2 44#define LOCKTYPE_RWLOCK 0x2
43#define LOCKTYPE_MUTEX 0x4 45#define LOCKTYPE_MUTEX 0x4
44#define LOCKTYPE_RWSEM 0x8 46#define LOCKTYPE_RWSEM 0x8
47#define LOCKTYPE_WW 0x10
48
49static struct ww_acquire_ctx t, t2;
50static struct ww_mutex o, o2;
45 51
46/* 52/*
47 * Normal standalone locks, for the circular and irq-context 53 * Normal standalone locks, for the circular and irq-context
@@ -193,6 +199,20 @@ static void init_shared_classes(void)
193#define RSU(x) up_read(&rwsem_##x) 199#define RSU(x) up_read(&rwsem_##x)
194#define RWSI(x) init_rwsem(&rwsem_##x) 200#define RWSI(x) init_rwsem(&rwsem_##x)
195 201
202#ifndef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
203#define WWAI(x) ww_acquire_init(x, &ww_lockdep)
204#else
205#define WWAI(x) do { ww_acquire_init(x, &ww_lockdep); (x)->deadlock_inject_countdown = ~0U; } while (0)
206#endif
207#define WWAD(x) ww_acquire_done(x)
208#define WWAF(x) ww_acquire_fini(x)
209
210#define WWL(x, c) ww_mutex_lock(x, c)
211#define WWT(x) ww_mutex_trylock(x)
212#define WWL1(x) ww_mutex_lock(x, NULL)
213#define WWU(x) ww_mutex_unlock(x)
214
215
196#define LOCK_UNLOCK_2(x,y) LOCK(x); LOCK(y); UNLOCK(y); UNLOCK(x) 216#define LOCK_UNLOCK_2(x,y) LOCK(x); LOCK(y); UNLOCK(y); UNLOCK(x)
197 217
198/* 218/*
@@ -894,11 +914,13 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft)
894# define I_RWLOCK(x) lockdep_reset_lock(&rwlock_##x.dep_map) 914# define I_RWLOCK(x) lockdep_reset_lock(&rwlock_##x.dep_map)
895# define I_MUTEX(x) lockdep_reset_lock(&mutex_##x.dep_map) 915# define I_MUTEX(x) lockdep_reset_lock(&mutex_##x.dep_map)
896# define I_RWSEM(x) lockdep_reset_lock(&rwsem_##x.dep_map) 916# define I_RWSEM(x) lockdep_reset_lock(&rwsem_##x.dep_map)
917# define I_WW(x) lockdep_reset_lock(&x.dep_map)
897#else 918#else
898# define I_SPINLOCK(x) 919# define I_SPINLOCK(x)
899# define I_RWLOCK(x) 920# define I_RWLOCK(x)
900# define I_MUTEX(x) 921# define I_MUTEX(x)
901# define I_RWSEM(x) 922# define I_RWSEM(x)
923# define I_WW(x)
902#endif 924#endif
903 925
904#define I1(x) \ 926#define I1(x) \
@@ -920,11 +942,20 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft)
920static void reset_locks(void) 942static void reset_locks(void)
921{ 943{
922 local_irq_disable(); 944 local_irq_disable();
945 lockdep_free_key_range(&ww_lockdep.acquire_key, 1);
946 lockdep_free_key_range(&ww_lockdep.mutex_key, 1);
947
923 I1(A); I1(B); I1(C); I1(D); 948 I1(A); I1(B); I1(C); I1(D);
924 I1(X1); I1(X2); I1(Y1); I1(Y2); I1(Z1); I1(Z2); 949 I1(X1); I1(X2); I1(Y1); I1(Y2); I1(Z1); I1(Z2);
950 I_WW(t); I_WW(t2); I_WW(o.base); I_WW(o2.base);
925 lockdep_reset(); 951 lockdep_reset();
926 I2(A); I2(B); I2(C); I2(D); 952 I2(A); I2(B); I2(C); I2(D);
927 init_shared_classes(); 953 init_shared_classes();
954
955 ww_mutex_init(&o, &ww_lockdep); ww_mutex_init(&o2, &ww_lockdep);
956 memset(&t, 0, sizeof(t)); memset(&t2, 0, sizeof(t2));
957 memset(&ww_lockdep.acquire_key, 0, sizeof(ww_lockdep.acquire_key));
958 memset(&ww_lockdep.mutex_key, 0, sizeof(ww_lockdep.mutex_key));
928 local_irq_enable(); 959 local_irq_enable();
929} 960}
930 961
@@ -938,7 +969,6 @@ static int unexpected_testcase_failures;
938static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask) 969static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask)
939{ 970{
940 unsigned long saved_preempt_count = preempt_count(); 971 unsigned long saved_preempt_count = preempt_count();
941 int expected_failure = 0;
942 972
943 WARN_ON(irqs_disabled()); 973 WARN_ON(irqs_disabled());
944 974
@@ -946,26 +976,16 @@ static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask)
946 /* 976 /*
947 * Filter out expected failures: 977 * Filter out expected failures:
948 */ 978 */
979 if (debug_locks != expected) {
949#ifndef CONFIG_PROVE_LOCKING 980#ifndef CONFIG_PROVE_LOCKING
950 if ((lockclass_mask & LOCKTYPE_SPIN) && debug_locks != expected) 981 expected_testcase_failures++;
951 expected_failure = 1; 982 printk("failed|");
952 if ((lockclass_mask & LOCKTYPE_RWLOCK) && debug_locks != expected) 983#else
953 expected_failure = 1; 984 unexpected_testcase_failures++;
954 if ((lockclass_mask & LOCKTYPE_MUTEX) && debug_locks != expected) 985 printk("FAILED|");
955 expected_failure = 1; 986
956 if ((lockclass_mask & LOCKTYPE_RWSEM) && debug_locks != expected) 987 dump_stack();
957 expected_failure = 1;
958#endif 988#endif
959 if (debug_locks != expected) {
960 if (expected_failure) {
961 expected_testcase_failures++;
962 printk("failed|");
963 } else {
964 unexpected_testcase_failures++;
965
966 printk("FAILED|");
967 dump_stack();
968 }
969 } else { 989 } else {
970 testcase_successes++; 990 testcase_successes++;
971 printk(" ok |"); 991 printk(" ok |");
@@ -1108,6 +1128,346 @@ static inline void print_testname(const char *testname)
1108 DO_TESTCASE_6IRW(desc, name, 312); \ 1128 DO_TESTCASE_6IRW(desc, name, 312); \
1109 DO_TESTCASE_6IRW(desc, name, 321); 1129 DO_TESTCASE_6IRW(desc, name, 321);
1110 1130
1131static void ww_test_fail_acquire(void)
1132{
1133 int ret;
1134
1135 WWAI(&t);
1136 t.stamp++;
1137
1138 ret = WWL(&o, &t);
1139
1140 if (WARN_ON(!o.ctx) ||
1141 WARN_ON(ret))
1142 return;
1143
1144 /* No lockdep test, pure API */
1145 ret = WWL(&o, &t);
1146 WARN_ON(ret != -EALREADY);
1147
1148 ret = WWT(&o);
1149 WARN_ON(ret);
1150
1151 t2 = t;
1152 t2.stamp++;
1153 ret = WWL(&o, &t2);
1154 WARN_ON(ret != -EDEADLK);
1155 WWU(&o);
1156
1157 if (WWT(&o))
1158 WWU(&o);
1159#ifdef CONFIG_DEBUG_LOCK_ALLOC
1160 else
1161 DEBUG_LOCKS_WARN_ON(1);
1162#endif
1163}
1164
1165static void ww_test_two_contexts(void)
1166{
1167 WWAI(&t);
1168 WWAI(&t2);
1169}
1170
1171static void ww_test_diff_class(void)
1172{
1173 WWAI(&t);
1174#ifdef CONFIG_DEBUG_MUTEXES
1175 t.ww_class = NULL;
1176#endif
1177 WWL(&o, &t);
1178}
1179
1180static void ww_test_context_done_twice(void)
1181{
1182 WWAI(&t);
1183 WWAD(&t);
1184 WWAD(&t);
1185 WWAF(&t);
1186}
1187
1188static void ww_test_context_unlock_twice(void)
1189{
1190 WWAI(&t);
1191 WWAD(&t);
1192 WWAF(&t);
1193 WWAF(&t);
1194}
1195
1196static void ww_test_context_fini_early(void)
1197{
1198 WWAI(&t);
1199 WWL(&o, &t);
1200 WWAD(&t);
1201 WWAF(&t);
1202}
1203
1204static void ww_test_context_lock_after_done(void)
1205{
1206 WWAI(&t);
1207 WWAD(&t);
1208 WWL(&o, &t);
1209}
1210
1211static void ww_test_object_unlock_twice(void)
1212{
1213 WWL1(&o);
1214 WWU(&o);
1215 WWU(&o);
1216}
1217
1218static void ww_test_object_lock_unbalanced(void)
1219{
1220 WWAI(&t);
1221 WWL(&o, &t);
1222 t.acquired = 0;
1223 WWU(&o);
1224 WWAF(&t);
1225}
1226
1227static void ww_test_object_lock_stale_context(void)
1228{
1229 WWAI(&t);
1230 o.ctx = &t2;
1231 WWL(&o, &t);
1232}
1233
1234static void ww_test_spin_nest_unlocked(void)
1235{
1236 raw_spin_lock_nest_lock(&lock_A, &o.base);
1237 U(A);
1238}
1239
1240static void ww_test_unneeded_slow(void)
1241{
1242 WWAI(&t);
1243
1244 ww_mutex_lock_slow(&o, &t);
1245}
1246
1247static void ww_test_context_block(void)
1248{
1249 int ret;
1250
1251 WWAI(&t);
1252
1253 ret = WWL(&o, &t);
1254 WARN_ON(ret);
1255 WWL1(&o2);
1256}
1257
1258static void ww_test_context_try(void)
1259{
1260 int ret;
1261
1262 WWAI(&t);
1263
1264 ret = WWL(&o, &t);
1265 WARN_ON(ret);
1266
1267 ret = WWT(&o2);
1268 WARN_ON(!ret);
1269 WWU(&o2);
1270 WWU(&o);
1271}
1272
1273static void ww_test_context_context(void)
1274{
1275 int ret;
1276
1277 WWAI(&t);
1278
1279 ret = WWL(&o, &t);
1280 WARN_ON(ret);
1281
1282 ret = WWL(&o2, &t);
1283 WARN_ON(ret);
1284
1285 WWU(&o2);
1286 WWU(&o);
1287}
1288
1289static void ww_test_try_block(void)
1290{
1291 bool ret;
1292
1293 ret = WWT(&o);
1294 WARN_ON(!ret);
1295
1296 WWL1(&o2);
1297 WWU(&o2);
1298 WWU(&o);
1299}
1300
1301static void ww_test_try_try(void)
1302{
1303 bool ret;
1304
1305 ret = WWT(&o);
1306 WARN_ON(!ret);
1307 ret = WWT(&o2);
1308 WARN_ON(!ret);
1309 WWU(&o2);
1310 WWU(&o);
1311}
1312
1313static void ww_test_try_context(void)
1314{
1315 int ret;
1316
1317 ret = WWT(&o);
1318 WARN_ON(!ret);
1319
1320 WWAI(&t);
1321
1322 ret = WWL(&o2, &t);
1323 WARN_ON(ret);
1324}
1325
1326static void ww_test_block_block(void)
1327{
1328 WWL1(&o);
1329 WWL1(&o2);
1330}
1331
1332static void ww_test_block_try(void)
1333{
1334 bool ret;
1335
1336 WWL1(&o);
1337 ret = WWT(&o2);
1338 WARN_ON(!ret);
1339}
1340
1341static void ww_test_block_context(void)
1342{
1343 int ret;
1344
1345 WWL1(&o);
1346 WWAI(&t);
1347
1348 ret = WWL(&o2, &t);
1349 WARN_ON(ret);
1350}
1351
1352static void ww_test_spin_block(void)
1353{
1354 L(A);
1355 U(A);
1356
1357 WWL1(&o);
1358 L(A);
1359 U(A);
1360 WWU(&o);
1361
1362 L(A);
1363 WWL1(&o);
1364 WWU(&o);
1365 U(A);
1366}
1367
1368static void ww_test_spin_try(void)
1369{
1370 bool ret;
1371
1372 L(A);
1373 U(A);
1374
1375 ret = WWT(&o);
1376 WARN_ON(!ret);
1377 L(A);
1378 U(A);
1379 WWU(&o);
1380
1381 L(A);
1382 ret = WWT(&o);
1383 WARN_ON(!ret);
1384 WWU(&o);
1385 U(A);
1386}
1387
1388static void ww_test_spin_context(void)
1389{
1390 int ret;
1391
1392 L(A);
1393 U(A);
1394
1395 WWAI(&t);
1396
1397 ret = WWL(&o, &t);
1398 WARN_ON(ret);
1399 L(A);
1400 U(A);
1401 WWU(&o);
1402
1403 L(A);
1404 ret = WWL(&o, &t);
1405 WARN_ON(ret);
1406 WWU(&o);
1407 U(A);
1408}
1409
1410static void ww_tests(void)
1411{
1412 printk(" --------------------------------------------------------------------------\n");
1413 printk(" | Wound/wait tests |\n");
1414 printk(" ---------------------\n");
1415
1416 print_testname("ww api failures");
1417 dotest(ww_test_fail_acquire, SUCCESS, LOCKTYPE_WW);
1418 dotest(ww_test_unneeded_slow, FAILURE, LOCKTYPE_WW);
1419 printk("\n");
1420
1421 print_testname("ww contexts mixing");
1422 dotest(ww_test_two_contexts, FAILURE, LOCKTYPE_WW);
1423 dotest(ww_test_diff_class, FAILURE, LOCKTYPE_WW);
1424 printk("\n");
1425
1426 print_testname("finishing ww context");
1427 dotest(ww_test_context_done_twice, FAILURE, LOCKTYPE_WW);
1428 dotest(ww_test_context_unlock_twice, FAILURE, LOCKTYPE_WW);
1429 dotest(ww_test_context_fini_early, FAILURE, LOCKTYPE_WW);
1430 dotest(ww_test_context_lock_after_done, FAILURE, LOCKTYPE_WW);
1431 printk("\n");
1432
1433 print_testname("locking mismatches");
1434 dotest(ww_test_object_unlock_twice, FAILURE, LOCKTYPE_WW);
1435 dotest(ww_test_object_lock_unbalanced, FAILURE, LOCKTYPE_WW);
1436 dotest(ww_test_object_lock_stale_context, FAILURE, LOCKTYPE_WW);
1437 printk("\n");
1438
1439 print_testname("spinlock nest unlocked");
1440 dotest(ww_test_spin_nest_unlocked, FAILURE, LOCKTYPE_WW);
1441 printk("\n");
1442
1443 printk(" -----------------------------------------------------\n");
1444 printk(" |block | try |context|\n");
1445 printk(" -----------------------------------------------------\n");
1446
1447 print_testname("context");
1448 dotest(ww_test_context_block, FAILURE, LOCKTYPE_WW);
1449 dotest(ww_test_context_try, SUCCESS, LOCKTYPE_WW);
1450 dotest(ww_test_context_context, SUCCESS, LOCKTYPE_WW);
1451 printk("\n");
1452
1453 print_testname("try");
1454 dotest(ww_test_try_block, FAILURE, LOCKTYPE_WW);
1455 dotest(ww_test_try_try, SUCCESS, LOCKTYPE_WW);
1456 dotest(ww_test_try_context, FAILURE, LOCKTYPE_WW);
1457 printk("\n");
1458
1459 print_testname("block");
1460 dotest(ww_test_block_block, FAILURE, LOCKTYPE_WW);
1461 dotest(ww_test_block_try, SUCCESS, LOCKTYPE_WW);
1462 dotest(ww_test_block_context, FAILURE, LOCKTYPE_WW);
1463 printk("\n");
1464
1465 print_testname("spinlock");
1466 dotest(ww_test_spin_block, FAILURE, LOCKTYPE_WW);
1467 dotest(ww_test_spin_try, SUCCESS, LOCKTYPE_WW);
1468 dotest(ww_test_spin_context, FAILURE, LOCKTYPE_WW);
1469 printk("\n");
1470}
1111 1471
1112void locking_selftest(void) 1472void locking_selftest(void)
1113{ 1473{
@@ -1188,6 +1548,8 @@ void locking_selftest(void)
1188 DO_TESTCASE_6x2("irq read-recursion", irq_read_recursion); 1548 DO_TESTCASE_6x2("irq read-recursion", irq_read_recursion);
1189// DO_TESTCASE_6x2B("irq read-recursion #2", irq_read_recursion2); 1549// DO_TESTCASE_6x2B("irq read-recursion #2", irq_read_recursion2);
1190 1550
1551 ww_tests();
1552
1191 if (unexpected_testcase_failures) { 1553 if (unexpected_testcase_failures) {
1192 printk("-----------------------------------------------------------------\n"); 1554 printk("-----------------------------------------------------------------\n");
1193 debug_locks = 0; 1555 debug_locks = 0;