Add those four test cases:

1.
        CPU1            CPU2            CPU3
        =============   =============   =============
        write_lock(X);
                        write_lock(Y);
                                        write_lock(Z);
        read_lock(Y);
                        read_lock(Z);
                                        read_lock(X);

        deadlock.

2.
        CPU1            CPU2            CPU3
        =============   =============   =============
        write_lock(X);
                        read_lock(Y);
                                        write_lock(Z);
        write_lock(Y);
                        read_lock(Z);
                                        read_lock(X);

        deadlock.

3.
        CPU1            CPU2            CPU3
        =============   =============   =============
        write_lock(X);
                        read_lock(Y);
                                        read_lock(Z);
        write_lock(Y);
                        read_lock(Z);
                                        write_lock(X);

        not deadlock.

4.
        CPU1            CPU2            CPU3
        =============   =============   =============
        write_lock(X);
                        read_lock(Y);
                                        write_lock(Z);
        read_lock(Y);
                        read_lock(Z);
                                        write_lock(X);

        not deadlock.

Those self testcases are valuable for the development of supporting
recursive read related deadlock detection.

Signed-off-by: Boqun Feng <boqun.f...@gmail.com>
---
 lib/locking-selftest.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 161 insertions(+)

diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 747a5379aeee..9c04b304008a 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -1070,6 +1070,133 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft)
 #undef E2
 #undef E3
 
+/*
+ * write-read / write-read / write-read deadlock even if read is recursive
+ */
+
+#define E1()                           \
+                                       \
+       WL(X1);                         \
+       RL(Y1);                         \
+       RU(Y1);                         \
+       WU(X1);
+
+#define E2()                           \
+                                       \
+       WL(Y1);                         \
+       RL(Z1);                         \
+       RU(Z1);                         \
+       WU(Y1);
+
+#define E3()                           \
+                                       \
+       WL(Z1);                         \
+       RL(X1);                         \
+       RU(X1);                         \
+       WU(Z1);
+
+#include "locking-selftest-rlock.h"
+GENERATE_PERMUTATIONS_3_EVENTS(W1R2_W2R3_W3R1)
+
+#undef E1
+#undef E2
+#undef E3
+
+/*
+ * write-write / read-read / write-read deadlock even if read is recursive
+ */
+
+#define E1()                           \
+                                       \
+       WL(X1);                         \
+       WL(Y1);                         \
+       WU(Y1);                         \
+       WU(X1);
+
+#define E2()                           \
+                                       \
+       RL(Y1);                         \
+       RL(Z1);                         \
+       RU(Z1);                         \
+       RU(Y1);
+
+#define E3()                           \
+                                       \
+       WL(Z1);                         \
+       RL(X1);                         \
+       RU(X1);                         \
+       WU(Z1);
+
+#include "locking-selftest-rlock.h"
+GENERATE_PERMUTATIONS_3_EVENTS(W1W2_R2R3_W3R1)
+
+#undef E1
+#undef E2
+#undef E3
+
+/*
+ * write-write / read-read / read-write is not deadlock when read is recursive
+ */
+
+#define E1()                           \
+                                       \
+       WL(X1);                         \
+       WL(Y1);                         \
+       WU(Y1);                         \
+       WU(X1);
+
+#define E2()                           \
+                                       \
+       RL(Y1);                         \
+       RL(Z1);                         \
+       RU(Z1);                         \
+       RU(Y1);
+
+#define E3()                           \
+                                       \
+       RL(Z1);                         \
+       WL(X1);                         \
+       WU(X1);                         \
+       RU(Z1);
+
+#include "locking-selftest-rlock.h"
+GENERATE_PERMUTATIONS_3_EVENTS(W1R2_R2R3_W3W1)
+
+#undef E1
+#undef E2
+#undef E3
+
+/*
+ * write-read / read-read / write-write is not deadlock when read is recursive
+ */
+
+#define E1()                           \
+                                       \
+       WL(X1);                         \
+       RL(Y1);                         \
+       RU(Y1);                         \
+       WU(X1);
+
+#define E2()                           \
+                                       \
+       RL(Y1);                         \
+       RL(Z1);                         \
+       RU(Z1);                         \
+       RU(Y1);
+
+#define E3()                           \
+                                       \
+       WL(Z1);                         \
+       WL(X1);                         \
+       WU(X1);                         \
+       WU(Z1);
+
+#include "locking-selftest-rlock.h"
+GENERATE_PERMUTATIONS_3_EVENTS(W1W2_R2R3_R3W1)
+
+#undef E1
+#undef E2
+#undef E3
 /*
  * read-lock / write-lock recursion that is unsafe.
  */
@@ -1241,6 +1368,19 @@ static inline void print_testname(const char *testname)
        dotest(name##_##nr, FAILURE, LOCKTYPE_RWLOCK);          \
        pr_cont("\n");
 
+#define DO_TESTCASE_1RR(desc, name, nr)                                \
+       print_testname(desc"/"#nr);                             \
+       pr_cont("             |");                              \
+       dotest(name##_##nr, SUCCESS, LOCKTYPE_RWLOCK);          \
+       pr_cont("\n");
+
+#define DO_TESTCASE_1RRB(desc, name, nr)                       \
+       print_testname(desc"/"#nr);                             \
+       pr_cont("             |");                              \
+       dotest(name##_##nr, FAILURE, LOCKTYPE_RWLOCK);          \
+       pr_cont("\n");
+
+
 #define DO_TESTCASE_3(desc, name, nr)                          \
        print_testname(desc"/"#nr);                             \
        dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN);       \
@@ -1331,6 +1471,22 @@ static inline void print_testname(const char *testname)
        DO_TESTCASE_2IB(desc, name, 312);                       \
        DO_TESTCASE_2IB(desc, name, 321);
 
+#define DO_TESTCASE_6x1RR(desc, name)                          \
+       DO_TESTCASE_1RR(desc, name, 123);                       \
+       DO_TESTCASE_1RR(desc, name, 132);                       \
+       DO_TESTCASE_1RR(desc, name, 213);                       \
+       DO_TESTCASE_1RR(desc, name, 231);                       \
+       DO_TESTCASE_1RR(desc, name, 312);                       \
+       DO_TESTCASE_1RR(desc, name, 321);
+
+#define DO_TESTCASE_6x1RRB(desc, name)                         \
+       DO_TESTCASE_1RRB(desc, name, 123);                      \
+       DO_TESTCASE_1RRB(desc, name, 132);                      \
+       DO_TESTCASE_1RRB(desc, name, 213);                      \
+       DO_TESTCASE_1RRB(desc, name, 231);                      \
+       DO_TESTCASE_1RRB(desc, name, 312);                      \
+       DO_TESTCASE_1RRB(desc, name, 321);
+
 #define DO_TESTCASE_6x6(desc, name)                            \
        DO_TESTCASE_6I(desc, name, 123);                        \
        DO_TESTCASE_6I(desc, name, 132);                        \
@@ -2093,6 +2249,11 @@ void locking_selftest(void)
        pr_cont("             |");
        dotest(rlock_chaincache_ABBA1, FAILURE, LOCKTYPE_RWLOCK);
 
+       DO_TESTCASE_6x1RRB("rlock W1R2/W2R3/W3R1", W1R2_W2R3_W3R1);
+       DO_TESTCASE_6x1RRB("rlock W1W2/R2R3/W3R1", W1W2_R2R3_W3R1);
+       DO_TESTCASE_6x1RR("rlock W1W2/R2R3/R3W1", W1W2_R2R3_R3W1);
+       DO_TESTCASE_6x1RR("rlock W1R2/R2R3/W3W1", W1R2_R2R3_W3W1);
+
        printk("  
--------------------------------------------------------------------------\n");
 
        /*
-- 
2.14.1

Reply via email to