aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2006-07-03 03:24:48 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-03 18:27:03 -0400
commitcae2ed9aa573415c6e5de9a09b7ff0d74af793bc (patch)
tree1a7bcea760681872bcc6020843886c5597130eb4
parent1f194a4c393103ac925001d7e04b05fbb122580d (diff)
[PATCH] lockdep: locking API self tests
Introduce DEBUG_LOCKING_API_SELFTESTS, which uses the generic lock debugging code's silent-failure feature to run a matrix of testcases. There are 210 testcases currently: +----------------------- | Locking API testsuite: +------------------------------+------+------+------+------+------+------+ | spin |wlock |rlock |mutex | wsem | rsem | -------------------------------+------+------+------+------+------+------+ A-A deadlock: ok | ok | ok | ok | ok | ok | A-B-B-A deadlock: ok | ok | ok | ok | ok | ok | A-B-B-C-C-A deadlock: ok | ok | ok | ok | ok | ok | A-B-C-A-B-C deadlock: ok | ok | ok | ok | ok | ok | A-B-B-C-C-D-D-A deadlock: ok | ok | ok | ok | ok | ok | A-B-C-D-B-D-D-A deadlock: ok | ok | ok | ok | ok | ok | A-B-C-D-B-C-D-A deadlock: ok | ok | ok | ok | ok | ok | double unlock: ok | ok | ok | ok | ok | ok | bad unlock order: ok | ok | ok | ok | ok | ok | --------------------------------------+------+------+------+------+------+ recursive read-lock: | ok | | ok | --------------------------------------+------+------+------+------+------+ non-nested unlock: ok | ok | ok | ok | --------------------------------------+------+------+------+ hard-irqs-on + irq-safe-A/12: ok | ok | ok | soft-irqs-on + irq-safe-A/12: ok | ok | ok | hard-irqs-on + irq-safe-A/21: ok | ok | ok | soft-irqs-on + irq-safe-A/21: ok | ok | ok | sirq-safe-A => hirqs-on/12: ok | ok | ok | sirq-safe-A => hirqs-on/21: ok | ok | ok | hard-safe-A + irqs-on/12: ok | ok | ok | soft-safe-A + irqs-on/12: ok | ok | ok | hard-safe-A + irqs-on/21: ok | ok | ok | soft-safe-A + irqs-on/21: ok | ok | ok | hard-safe-A + unsafe-B #1/123: ok | ok | ok | soft-safe-A + unsafe-B #1/123: ok | ok | ok | hard-safe-A + unsafe-B #1/132: ok | ok | ok | soft-safe-A + unsafe-B #1/132: ok | ok | ok | hard-safe-A + unsafe-B #1/213: ok | ok | ok | soft-safe-A + unsafe-B #1/213: ok | ok | ok | hard-safe-A + unsafe-B #1/231: ok | ok | ok | soft-safe-A + unsafe-B #1/231: ok | ok | ok | hard-safe-A + unsafe-B #1/312: ok | ok | ok | soft-safe-A + unsafe-B #1/312: ok | ok | ok | hard-safe-A + unsafe-B #1/321: ok | ok | ok | soft-safe-A + unsafe-B #1/321: ok | ok | ok | hard-safe-A + unsafe-B #2/123: ok | ok | ok | soft-safe-A + unsafe-B #2/123: ok | ok | ok | hard-safe-A + unsafe-B #2/132: ok | ok | ok | soft-safe-A + unsafe-B #2/132: ok | ok | ok | hard-safe-A + unsafe-B #2/213: ok | ok | ok | soft-safe-A + unsafe-B #2/213: ok | ok | ok | hard-safe-A + unsafe-B #2/231: ok | ok | ok | soft-safe-A + unsafe-B #2/231: ok | ok | ok | hard-safe-A + unsafe-B #2/312: ok | ok | ok | soft-safe-A + unsafe-B #2/312: ok | ok | ok | hard-safe-A + unsafe-B #2/321: ok | ok | ok | soft-safe-A + unsafe-B #2/321: ok | ok | ok | hard-irq lock-inversion/123: ok | ok | ok | soft-irq lock-inversion/123: ok | ok | ok | hard-irq lock-inversion/132: ok | ok | ok | soft-irq lock-inversion/132: ok | ok | ok | hard-irq lock-inversion/213: ok | ok | ok | soft-irq lock-inversion/213: ok | ok | ok | hard-irq lock-inversion/231: ok | ok | ok | soft-irq lock-inversion/231: ok | ok | ok | hard-irq lock-inversion/312: ok | ok | ok | soft-irq lock-inversion/312: ok | ok | ok | hard-irq lock-inversion/321: ok | ok | ok | soft-irq lock-inversion/321: ok | ok | ok | hard-irq read-recursion/123: ok | soft-irq read-recursion/123: ok | hard-irq read-recursion/132: ok | soft-irq read-recursion/132: ok | hard-irq read-recursion/213: ok | soft-irq read-recursion/213: ok | hard-irq read-recursion/231: ok | soft-irq read-recursion/231: ok | hard-irq read-recursion/312: ok | soft-irq read-recursion/312: ok | hard-irq read-recursion/321: ok | soft-irq read-recursion/321: ok | --------------------------------+-----+---------------- Good, all 210 testcases passed! | --------------------------------+ Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--Documentation/kernel-parameters.txt9
-rw-r--r--lib/Kconfig.debug11
-rw-r--r--lib/Makefile1
-rw-r--r--lib/locking-selftest-hardirq.h9
-rw-r--r--lib/locking-selftest-mutex.h11
-rw-r--r--lib/locking-selftest-rlock-hardirq.h2
-rw-r--r--lib/locking-selftest-rlock-softirq.h2
-rw-r--r--lib/locking-selftest-rlock.h14
-rw-r--r--lib/locking-selftest-rsem.h14
-rw-r--r--lib/locking-selftest-softirq.h9
-rw-r--r--lib/locking-selftest-spin-hardirq.h2
-rw-r--r--lib/locking-selftest-spin-softirq.h2
-rw-r--r--lib/locking-selftest-spin.h11
-rw-r--r--lib/locking-selftest-wlock-hardirq.h2
-rw-r--r--lib/locking-selftest-wlock-softirq.h2
-rw-r--r--lib/locking-selftest-wlock.h14
-rw-r--r--lib/locking-selftest-wsem.h14
-rw-r--r--lib/locking-selftest.c1218
18 files changed, 1347 insertions, 0 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 86e9282d1c20..149f62ba14a5 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -435,6 +435,15 @@ running once the system is up.
435 435
436 debug [KNL] Enable kernel debugging (events log level). 436 debug [KNL] Enable kernel debugging (events log level).
437 437
438 debug_locks_verbose=
439 [KNL] verbose self-tests
440 Format=<0|1>
441 Print debugging info while doing the locking API
442 self-tests.
443 We default to 0 (no extra messages), setting it to
444 1 will print _a lot_ more information - normally
445 only useful to kernel developers.
446
438 decnet= [HW,NET] 447 decnet= [HW,NET]
439 Format: <area>[,<node>] 448 Format: <area>[,<node>]
440 See also Documentation/networking/decnet.txt. 449 See also Documentation/networking/decnet.txt.
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 91e338a3d069..16021b09c184 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -149,6 +149,17 @@ config DEBUG_SPINLOCK_SLEEP
149 If you say Y here, various routines which may sleep will become very 149 If you say Y here, various routines which may sleep will become very
150 noisy if they are called with a spinlock held. 150 noisy if they are called with a spinlock held.
151 151
152config DEBUG_LOCKING_API_SELFTESTS
153 bool "Locking API boot-time self-tests"
154 depends on DEBUG_KERNEL
155 help
156 Say Y here if you want the kernel to run a short self-test during
157 bootup. The self-test checks whether common types of locking bugs
158 are detected by debugging mechanisms or not. (if you disable
159 lock debugging then those bugs wont be detected of course.)
160 The following locking APIs are covered: spinlocks, rwlocks,
161 mutexes and rwsems.
162
152config STACKTRACE 163config STACKTRACE
153 bool 164 bool
154 depends on STACKTRACE_SUPPORT 165 depends on STACKTRACE_SUPPORT
diff --git a/lib/Makefile b/lib/Makefile
index 4f5d01922f82..be9719ae82d0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -18,6 +18,7 @@ CFLAGS_kobject.o += -DDEBUG
18CFLAGS_kobject_uevent.o += -DDEBUG 18CFLAGS_kobject_uevent.o += -DDEBUG
19endif 19endif
20 20
21obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
21obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o 22obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
22lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o 23lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
23lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o 24lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
diff --git a/lib/locking-selftest-hardirq.h b/lib/locking-selftest-hardirq.h
new file mode 100644
index 000000000000..10d4a150b259
--- /dev/null
+++ b/lib/locking-selftest-hardirq.h
@@ -0,0 +1,9 @@
1#undef IRQ_DISABLE
2#undef IRQ_ENABLE
3#undef IRQ_ENTER
4#undef IRQ_EXIT
5
6#define IRQ_ENABLE HARDIRQ_ENABLE
7#define IRQ_DISABLE HARDIRQ_DISABLE
8#define IRQ_ENTER HARDIRQ_ENTER
9#define IRQ_EXIT HARDIRQ_EXIT
diff --git a/lib/locking-selftest-mutex.h b/lib/locking-selftest-mutex.h
new file mode 100644
index 000000000000..68601b6f584b
--- /dev/null
+++ b/lib/locking-selftest-mutex.h
@@ -0,0 +1,11 @@
1#undef LOCK
2#define LOCK ML
3
4#undef UNLOCK
5#define UNLOCK MU
6
7#undef RLOCK
8#undef WLOCK
9
10#undef INIT
11#define INIT MI
diff --git a/lib/locking-selftest-rlock-hardirq.h b/lib/locking-selftest-rlock-hardirq.h
new file mode 100644
index 000000000000..9f517ebcb786
--- /dev/null
+++ b/lib/locking-selftest-rlock-hardirq.h
@@ -0,0 +1,2 @@
1#include "locking-selftest-rlock.h"
2#include "locking-selftest-hardirq.h"
diff --git a/lib/locking-selftest-rlock-softirq.h b/lib/locking-selftest-rlock-softirq.h
new file mode 100644
index 000000000000..981455db7ff0
--- /dev/null
+++ b/lib/locking-selftest-rlock-softirq.h
@@ -0,0 +1,2 @@
1#include "locking-selftest-rlock.h"
2#include "locking-selftest-softirq.h"
diff --git a/lib/locking-selftest-rlock.h b/lib/locking-selftest-rlock.h
new file mode 100644
index 000000000000..6789044f4d0e
--- /dev/null
+++ b/lib/locking-selftest-rlock.h
@@ -0,0 +1,14 @@
1#undef LOCK
2#define LOCK RL
3
4#undef UNLOCK
5#define UNLOCK RU
6
7#undef RLOCK
8#define RLOCK RL
9
10#undef WLOCK
11#define WLOCK WL
12
13#undef INIT
14#define INIT RWI
diff --git a/lib/locking-selftest-rsem.h b/lib/locking-selftest-rsem.h
new file mode 100644
index 000000000000..62da886680c7
--- /dev/null
+++ b/lib/locking-selftest-rsem.h
@@ -0,0 +1,14 @@
1#undef LOCK
2#define LOCK RSL
3
4#undef UNLOCK
5#define UNLOCK RSU
6
7#undef RLOCK
8#define RLOCK RSL
9
10#undef WLOCK
11#define WLOCK WSL
12
13#undef INIT
14#define INIT RWSI
diff --git a/lib/locking-selftest-softirq.h b/lib/locking-selftest-softirq.h
new file mode 100644
index 000000000000..a83de2a04ace
--- /dev/null
+++ b/lib/locking-selftest-softirq.h
@@ -0,0 +1,9 @@
1#undef IRQ_DISABLE
2#undef IRQ_ENABLE
3#undef IRQ_ENTER
4#undef IRQ_EXIT
5
6#define IRQ_DISABLE SOFTIRQ_DISABLE
7#define IRQ_ENABLE SOFTIRQ_ENABLE
8#define IRQ_ENTER SOFTIRQ_ENTER
9#define IRQ_EXIT SOFTIRQ_EXIT
diff --git a/lib/locking-selftest-spin-hardirq.h b/lib/locking-selftest-spin-hardirq.h
new file mode 100644
index 000000000000..693198dce30a
--- /dev/null
+++ b/lib/locking-selftest-spin-hardirq.h
@@ -0,0 +1,2 @@
1#include "locking-selftest-spin.h"
2#include "locking-selftest-hardirq.h"
diff --git a/lib/locking-selftest-spin-softirq.h b/lib/locking-selftest-spin-softirq.h
new file mode 100644
index 000000000000..c472e2a87ffc
--- /dev/null
+++ b/lib/locking-selftest-spin-softirq.h
@@ -0,0 +1,2 @@
1#include "locking-selftest-spin.h"
2#include "locking-selftest-softirq.h"
diff --git a/lib/locking-selftest-spin.h b/lib/locking-selftest-spin.h
new file mode 100644
index 000000000000..ccd1b4b09757
--- /dev/null
+++ b/lib/locking-selftest-spin.h
@@ -0,0 +1,11 @@
1#undef LOCK
2#define LOCK L
3
4#undef UNLOCK
5#define UNLOCK U
6
7#undef RLOCK
8#undef WLOCK
9
10#undef INIT
11#define INIT SI
diff --git a/lib/locking-selftest-wlock-hardirq.h b/lib/locking-selftest-wlock-hardirq.h
new file mode 100644
index 000000000000..2dd2e5122caa
--- /dev/null
+++ b/lib/locking-selftest-wlock-hardirq.h
@@ -0,0 +1,2 @@
1#include "locking-selftest-wlock.h"
2#include "locking-selftest-hardirq.h"
diff --git a/lib/locking-selftest-wlock-softirq.h b/lib/locking-selftest-wlock-softirq.h
new file mode 100644
index 000000000000..cb80d1cb944e
--- /dev/null
+++ b/lib/locking-selftest-wlock-softirq.h
@@ -0,0 +1,2 @@
1#include "locking-selftest-wlock.h"
2#include "locking-selftest-softirq.h"
diff --git a/lib/locking-selftest-wlock.h b/lib/locking-selftest-wlock.h
new file mode 100644
index 000000000000..0815322d99ed
--- /dev/null
+++ b/lib/locking-selftest-wlock.h
@@ -0,0 +1,14 @@
1#undef LOCK
2#define LOCK WL
3
4#undef UNLOCK
5#define UNLOCK WU
6
7#undef RLOCK
8#define RLOCK RL
9
10#undef WLOCK
11#define WLOCK WL
12
13#undef INIT
14#define INIT RWI
diff --git a/lib/locking-selftest-wsem.h b/lib/locking-selftest-wsem.h
new file mode 100644
index 000000000000..b88c5f2dc5f0
--- /dev/null
+++ b/lib/locking-selftest-wsem.h
@@ -0,0 +1,14 @@
1#undef LOCK
2#define LOCK WSL
3
4#undef UNLOCK
5#define UNLOCK WSU
6
7#undef RLOCK
8#define RLOCK RSL
9
10#undef WLOCK
11#define WLOCK WSL
12
13#undef INIT
14#define INIT RWSI
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
new file mode 100644
index 000000000000..5cd05f20bdec
--- /dev/null
+++ b/lib/locking-selftest.c
@@ -0,0 +1,1218 @@
1/*
2 * lib/locking-selftest.c
3 *
4 * Testsuite for various locking APIs: spinlocks, rwlocks,
5 * mutexes and rw-semaphores.
6 *
7 * It is checking both false positives and false negatives.
8 *
9 * Started by Ingo Molnar:
10 *
11 * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
12 */
13#include <linux/rwsem.h>
14#include <linux/mutex.h>
15#include <linux/sched.h>
16#include <linux/delay.h>
17#include <linux/module.h>
18#include <linux/spinlock.h>
19#include <linux/kallsyms.h>
20#include <linux/interrupt.h>
21#include <linux/debug_locks.h>
22#include <linux/irqflags.h>
23
24/*
25 * Change this to 1 if you want to see the failure printouts:
26 */
27static unsigned int debug_locks_verbose;
28
29static int __init setup_debug_locks_verbose(char *str)
30{
31 get_option(&str, &debug_locks_verbose);
32
33 return 1;
34}
35
36__setup("debug_locks_verbose=", setup_debug_locks_verbose);
37
38#define FAILURE 0
39#define SUCCESS 1
40
41#define LOCKTYPE_SPIN 0x1
42#define LOCKTYPE_RWLOCK 0x2
43#define LOCKTYPE_MUTEX 0x4
44#define LOCKTYPE_RWSEM 0x8
45
46/*
47 * Normal standalone locks, for the circular and irq-context
48 * dependency tests:
49 */
50static DEFINE_SPINLOCK(lock_A);
51static DEFINE_SPINLOCK(lock_B);
52static DEFINE_SPINLOCK(lock_C);
53static DEFINE_SPINLOCK(lock_D);
54
55static DEFINE_RWLOCK(rwlock_A);
56static DEFINE_RWLOCK(rwlock_B);
57static DEFINE_RWLOCK(rwlock_C);
58static DEFINE_RWLOCK(rwlock_D);
59
60static DEFINE_MUTEX(mutex_A);
61static DEFINE_MUTEX(mutex_B);
62static DEFINE_MUTEX(mutex_C);
63static DEFINE_MUTEX(mutex_D);
64
65static DECLARE_RWSEM(rwsem_A);
66static DECLARE_RWSEM(rwsem_B);
67static DECLARE_RWSEM(rwsem_C);
68static DECLARE_RWSEM(rwsem_D);
69
70/*
71 * Locks that we initialize dynamically as well so that
72 * e.g. X1 and X2 becomes two instances of the same class,
73 * but X* and Y* are different classes. We do this so that
74 * we do not trigger a real lockup:
75 */
76static DEFINE_SPINLOCK(lock_X1);
77static DEFINE_SPINLOCK(lock_X2);
78static DEFINE_SPINLOCK(lock_Y1);
79static DEFINE_SPINLOCK(lock_Y2);
80static DEFINE_SPINLOCK(lock_Z1);
81static DEFINE_SPINLOCK(lock_Z2);
82
83static DEFINE_RWLOCK(rwlock_X1);
84static DEFINE_RWLOCK(rwlock_X2);
85static DEFINE_RWLOCK(rwlock_Y1);
86static DEFINE_RWLOCK(rwlock_Y2);
87static DEFINE_RWLOCK(rwlock_Z1);
88static DEFINE_RWLOCK(rwlock_Z2);
89
90static DEFINE_MUTEX(mutex_X1);
91static DEFINE_MUTEX(mutex_X2);
92static DEFINE_MUTEX(mutex_Y1);
93static DEFINE_MUTEX(mutex_Y2);
94static DEFINE_MUTEX(mutex_Z1);
95static DEFINE_MUTEX(mutex_Z2);
96
97static DECLARE_RWSEM(rwsem_X1);
98static DECLARE_RWSEM(rwsem_X2);
99static DECLARE_RWSEM(rwsem_Y1);
100static DECLARE_RWSEM(rwsem_Y2);
101static DECLARE_RWSEM(rwsem_Z1);
102static DECLARE_RWSEM(rwsem_Z2);
103
104/*
105 * non-inlined runtime initializers, to let separate locks share
106 * the same lock-class:
107 */
108#define INIT_CLASS_FUNC(class) \
109static noinline void \
110init_class_##class(spinlock_t *lock, rwlock_t *rwlock, struct mutex *mutex, \
111 struct rw_semaphore *rwsem) \
112{ \
113 spin_lock_init(lock); \
114 rwlock_init(rwlock); \
115 mutex_init(mutex); \
116 init_rwsem(rwsem); \
117}
118
119INIT_CLASS_FUNC(X)
120INIT_CLASS_FUNC(Y)
121INIT_CLASS_FUNC(Z)
122
123static void init_shared_classes(void)
124{
125 init_class_X(&lock_X1, &rwlock_X1, &mutex_X1, &rwsem_X1);
126 init_class_X(&lock_X2, &rwlock_X2, &mutex_X2, &rwsem_X2);
127
128 init_class_Y(&lock_Y1, &rwlock_Y1, &mutex_Y1, &rwsem_Y1);
129 init_class_Y(&lock_Y2, &rwlock_Y2, &mutex_Y2, &rwsem_Y2);
130
131 init_class_Z(&lock_Z1, &rwlock_Z1, &mutex_Z1, &rwsem_Z1);
132 init_class_Z(&lock_Z2, &rwlock_Z2, &mutex_Z2, &rwsem_Z2);
133}
134
135/*
136 * For spinlocks and rwlocks we also do hardirq-safe / softirq-safe tests.
137 * The following functions use a lock from a simulated hardirq/softirq
138 * context, causing the locks to be marked as hardirq-safe/softirq-safe:
139 */
140
141#define HARDIRQ_DISABLE local_irq_disable
142#define HARDIRQ_ENABLE local_irq_enable
143
144#define HARDIRQ_ENTER() \
145 local_irq_disable(); \
146 irq_enter(); \
147 WARN_ON(!in_irq());
148
149#define HARDIRQ_EXIT() \
150 __irq_exit(); \
151 local_irq_enable();
152
153#define SOFTIRQ_DISABLE local_bh_disable
154#define SOFTIRQ_ENABLE local_bh_enable
155
156#define SOFTIRQ_ENTER() \
157 local_bh_disable(); \
158 local_irq_disable(); \
159 trace_softirq_enter(); \
160 WARN_ON(!in_softirq());
161
162#define SOFTIRQ_EXIT() \
163 trace_softirq_exit(); \
164 local_irq_enable(); \
165 local_bh_enable();
166
167/*
168 * Shortcuts for lock/unlock API variants, to keep
169 * the testcases compact:
170 */
171#define L(x) spin_lock(&lock_##x)
172#define U(x) spin_unlock(&lock_##x)
173#define LU(x) L(x); U(x)
174#define SI(x) spin_lock_init(&lock_##x)
175
176#define WL(x) write_lock(&rwlock_##x)
177#define WU(x) write_unlock(&rwlock_##x)
178#define WLU(x) WL(x); WU(x)
179
180#define RL(x) read_lock(&rwlock_##x)
181#define RU(x) read_unlock(&rwlock_##x)
182#define RLU(x) RL(x); RU(x)
183#define RWI(x) rwlock_init(&rwlock_##x)
184
185#define ML(x) mutex_lock(&mutex_##x)
186#define MU(x) mutex_unlock(&mutex_##x)
187#define MI(x) mutex_init(&mutex_##x)
188
189#define WSL(x) down_write(&rwsem_##x)
190#define WSU(x) up_write(&rwsem_##x)
191
192#define RSL(x) down_read(&rwsem_##x)
193#define RSU(x) up_read(&rwsem_##x)
194#define RWSI(x) init_rwsem(&rwsem_##x)
195
196#define LOCK_UNLOCK_2(x,y) LOCK(x); LOCK(y); UNLOCK(y); UNLOCK(x)
197
198/*
199 * Generate different permutations of the same testcase, using
200 * the same basic lock-dependency/state events:
201 */
202
203#define GENERATE_TESTCASE(name) \
204 \
205static void name(void) { E(); }
206
207#define GENERATE_PERMUTATIONS_2_EVENTS(name) \
208 \
209static void name##_12(void) { E1(); E2(); } \
210static void name##_21(void) { E2(); E1(); }
211
212#define GENERATE_PERMUTATIONS_3_EVENTS(name) \
213 \
214static void name##_123(void) { E1(); E2(); E3(); } \
215static void name##_132(void) { E1(); E3(); E2(); } \
216static void name##_213(void) { E2(); E1(); E3(); } \
217static void name##_231(void) { E2(); E3(); E1(); } \
218static void name##_312(void) { E3(); E1(); E2(); } \
219static void name##_321(void) { E3(); E2(); E1(); }
220
221/*
222 * AA deadlock:
223 */
224
225#define E() \
226 \
227 LOCK(X1); \
228 LOCK(X2); /* this one should fail */
229
230/*
231 * 6 testcases:
232 */
233#include "locking-selftest-spin.h"
234GENERATE_TESTCASE(AA_spin)
235#include "locking-selftest-wlock.h"
236GENERATE_TESTCASE(AA_wlock)
237#include "locking-selftest-rlock.h"
238GENERATE_TESTCASE(AA_rlock)
239#include "locking-selftest-mutex.h"
240GENERATE_TESTCASE(AA_mutex)
241#include "locking-selftest-wsem.h"
242GENERATE_TESTCASE(AA_wsem)
243#include "locking-selftest-rsem.h"
244GENERATE_TESTCASE(AA_rsem)
245
246#undef E
247
248/*
249 * Special-case for read-locking, they are
250 * allowed to recurse on the same lock instance:
251 */
252static void rlock_AA1(void)
253{
254 RL(X1);
255 RL(X1); // this one should NOT fail
256}
257
258static void rlock_AA1B(void)
259{
260 RL(X1);
261 RL(X2); // this one should fail
262}
263
264static void rsem_AA1(void)
265{
266 RSL(X1);
267 RSL(X1); // this one should fail
268}
269
270static void rsem_AA1B(void)
271{
272 RSL(X1);
273 RSL(X2); // this one should fail
274}
275/*
276 * The mixing of read and write locks is not allowed:
277 */
278static void rlock_AA2(void)
279{
280 RL(X1);
281 WL(X2); // this one should fail
282}
283
284static void rsem_AA2(void)
285{
286 RSL(X1);
287 WSL(X2); // this one should fail
288}
289
290static void rlock_AA3(void)
291{
292 WL(X1);
293 RL(X2); // this one should fail
294}
295
296static void rsem_AA3(void)
297{
298 WSL(X1);
299 RSL(X2); // this one should fail
300}
301
302/*
303 * ABBA deadlock:
304 */
305
306#define E() \
307 \
308 LOCK_UNLOCK_2(A, B); \
309 LOCK_UNLOCK_2(B, A); /* fail */
310
311/*
312 * 6 testcases:
313 */
314#include "locking-selftest-spin.h"
315GENERATE_TESTCASE(ABBA_spin)
316#include "locking-selftest-wlock.h"
317GENERATE_TESTCASE(ABBA_wlock)
318#include "locking-selftest-rlock.h"
319GENERATE_TESTCASE(ABBA_rlock)
320#include "locking-selftest-mutex.h"
321GENERATE_TESTCASE(ABBA_mutex)
322#include "locking-selftest-wsem.h"
323GENERATE_TESTCASE(ABBA_wsem)
324#include "locking-selftest-rsem.h"
325GENERATE_TESTCASE(ABBA_rsem)
326
327#undef E
328
329/*
330 * AB BC CA deadlock:
331 */
332
333#define E() \
334 \
335 LOCK_UNLOCK_2(A, B); \
336 LOCK_UNLOCK_2(B, C); \
337 LOCK_UNLOCK_2(C, A); /* fail */
338
339/*
340 * 6 testcases:
341 */
342#include "locking-selftest-spin.h"
343GENERATE_TESTCASE(ABBCCA_spin)
344#include "locking-selftest-wlock.h"
345GENERATE_TESTCASE(ABBCCA_wlock)
346#include "locking-selftest-rlock.h"
347GENERATE_TESTCASE(ABBCCA_rlock)
348#include "locking-selftest-mutex.h"
349GENERATE_TESTCASE(ABBCCA_mutex)
350#include "locking-selftest-wsem.h"
351GENERATE_TESTCASE(ABBCCA_wsem)
352#include "locking-selftest-rsem.h"
353GENERATE_TESTCASE(ABBCCA_rsem)
354
355#undef E
356
357/*
358 * AB CA BC deadlock:
359 */
360
361#define E() \
362 \
363 LOCK_UNLOCK_2(A, B); \
364 LOCK_UNLOCK_2(C, A); \
365 LOCK_UNLOCK_2(B, C); /* fail */
366
367/*
368 * 6 testcases:
369 */
370#include "locking-selftest-spin.h"
371GENERATE_TESTCASE(ABCABC_spin)
372#include "locking-selftest-wlock.h"
373GENERATE_TESTCASE(ABCABC_wlock)
374#include "locking-selftest-rlock.h"
375GENERATE_TESTCASE(ABCABC_rlock)
376#include "locking-selftest-mutex.h"
377GENERATE_TESTCASE(ABCABC_mutex)
378#include "locking-selftest-wsem.h"
379GENERATE_TESTCASE(ABCABC_wsem)
380#include "locking-selftest-rsem.h"
381GENERATE_TESTCASE(ABCABC_rsem)
382
383#undef E
384
385/*
386 * AB BC CD DA deadlock:
387 */
388
389#define E() \
390 \
391 LOCK_UNLOCK_2(A, B); \
392 LOCK_UNLOCK_2(B, C); \
393 LOCK_UNLOCK_2(C, D); \
394 LOCK_UNLOCK_2(D, A); /* fail */
395
396/*
397 * 6 testcases:
398 */
399#include "locking-selftest-spin.h"
400GENERATE_TESTCASE(ABBCCDDA_spin)
401#include "locking-selftest-wlock.h"
402GENERATE_TESTCASE(ABBCCDDA_wlock)
403#include "locking-selftest-rlock.h"
404GENERATE_TESTCASE(ABBCCDDA_rlock)
405#include "locking-selftest-mutex.h"
406GENERATE_TESTCASE(ABBCCDDA_mutex)
407#include "locking-selftest-wsem.h"
408GENERATE_TESTCASE(ABBCCDDA_wsem)
409#include "locking-selftest-rsem.h"
410GENERATE_TESTCASE(ABBCCDDA_rsem)
411
412#undef E
413
414/*
415 * AB CD BD DA deadlock:
416 */
417#define E() \
418 \
419 LOCK_UNLOCK_2(A, B); \
420 LOCK_UNLOCK_2(C, D); \
421 LOCK_UNLOCK_2(B, D); \
422 LOCK_UNLOCK_2(D, A); /* fail */
423
424/*
425 * 6 testcases:
426 */
427#include "locking-selftest-spin.h"
428GENERATE_TESTCASE(ABCDBDDA_spin)
429#include "locking-selftest-wlock.h"
430GENERATE_TESTCASE(ABCDBDDA_wlock)
431#include "locking-selftest-rlock.h"
432GENERATE_TESTCASE(ABCDBDDA_rlock)
433#include "locking-selftest-mutex.h"
434GENERATE_TESTCASE(ABCDBDDA_mutex)
435#include "locking-selftest-wsem.h"
436GENERATE_TESTCASE(ABCDBDDA_wsem)
437#include "locking-selftest-rsem.h"
438GENERATE_TESTCASE(ABCDBDDA_rsem)
439
440#undef E
441
442/*
443 * AB CD BC DA deadlock:
444 */
445#define E() \
446 \
447 LOCK_UNLOCK_2(A, B); \
448 LOCK_UNLOCK_2(C, D); \
449 LOCK_UNLOCK_2(B, C); \
450 LOCK_UNLOCK_2(D, A); /* fail */
451
452/*
453 * 6 testcases:
454 */
455#include "locking-selftest-spin.h"
456GENERATE_TESTCASE(ABCDBCDA_spin)
457#include "locking-selftest-wlock.h"
458GENERATE_TESTCASE(ABCDBCDA_wlock)
459#include "locking-selftest-rlock.h"
460GENERATE_TESTCASE(ABCDBCDA_rlock)
461#include "locking-selftest-mutex.h"
462GENERATE_TESTCASE(ABCDBCDA_mutex)
463#include "locking-selftest-wsem.h"
464GENERATE_TESTCASE(ABCDBCDA_wsem)
465#include "locking-selftest-rsem.h"
466GENERATE_TESTCASE(ABCDBCDA_rsem)
467
468#undef E
469
470/*
471 * Double unlock:
472 */
473#define E() \
474 \
475 LOCK(A); \
476 UNLOCK(A); \
477 UNLOCK(A); /* fail */
478
479/*
480 * 6 testcases:
481 */
482#include "locking-selftest-spin.h"
483GENERATE_TESTCASE(double_unlock_spin)
484#include "locking-selftest-wlock.h"
485GENERATE_TESTCASE(double_unlock_wlock)
486#include "locking-selftest-rlock.h"
487GENERATE_TESTCASE(double_unlock_rlock)
488#include "locking-selftest-mutex.h"
489GENERATE_TESTCASE(double_unlock_mutex)
490#include "locking-selftest-wsem.h"
491GENERATE_TESTCASE(double_unlock_wsem)
492#include "locking-selftest-rsem.h"
493GENERATE_TESTCASE(double_unlock_rsem)
494
495#undef E
496
497/*
498 * Bad unlock ordering:
499 */
500#define E() \
501 \
502 LOCK(A); \
503 LOCK(B); \
504 UNLOCK(A); /* fail */ \
505 UNLOCK(B);
506
507/*
508 * 6 testcases:
509 */
510#include "locking-selftest-spin.h"
511GENERATE_TESTCASE(bad_unlock_order_spin)
512#include "locking-selftest-wlock.h"
513GENERATE_TESTCASE(bad_unlock_order_wlock)
514#include "locking-selftest-rlock.h"
515GENERATE_TESTCASE(bad_unlock_order_rlock)
516#include "locking-selftest-mutex.h"
517GENERATE_TESTCASE(bad_unlock_order_mutex)
518#include "locking-selftest-wsem.h"
519GENERATE_TESTCASE(bad_unlock_order_wsem)
520#include "locking-selftest-rsem.h"
521GENERATE_TESTCASE(bad_unlock_order_rsem)
522
523#undef E
524
525/*
526 * initializing a held lock:
527 */
528#define E() \
529 \
530 LOCK(A); \
531 INIT(A); /* fail */
532
533/*
534 * 6 testcases:
535 */
536#include "locking-selftest-spin.h"
537GENERATE_TESTCASE(init_held_spin)
538#include "locking-selftest-wlock.h"
539GENERATE_TESTCASE(init_held_wlock)
540#include "locking-selftest-rlock.h"
541GENERATE_TESTCASE(init_held_rlock)
542#include "locking-selftest-mutex.h"
543GENERATE_TESTCASE(init_held_mutex)
544#include "locking-selftest-wsem.h"
545GENERATE_TESTCASE(init_held_wsem)
546#include "locking-selftest-rsem.h"
547GENERATE_TESTCASE(init_held_rsem)
548
549#undef E
550
551/*
552 * locking an irq-safe lock with irqs enabled:
553 */
554#define E1() \
555 \
556 IRQ_ENTER(); \
557 LOCK(A); \
558 UNLOCK(A); \
559 IRQ_EXIT();
560
561#define E2() \
562 \
563 LOCK(A); \
564 UNLOCK(A);
565
566/*
567 * Generate 24 testcases:
568 */
569#include "locking-selftest-spin-hardirq.h"
570GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_spin)
571
572#include "locking-selftest-rlock-hardirq.h"
573GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_rlock)
574
575#include "locking-selftest-wlock-hardirq.h"
576GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_wlock)
577
578#include "locking-selftest-spin-softirq.h"
579GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_spin)
580
581#include "locking-selftest-rlock-softirq.h"
582GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_rlock)
583
584#include "locking-selftest-wlock-softirq.h"
585GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_wlock)
586
587#undef E1
588#undef E2
589
590/*
591 * Enabling hardirqs with a softirq-safe lock held:
592 */
593#define E1() \
594 \
595 SOFTIRQ_ENTER(); \
596 LOCK(A); \
597 UNLOCK(A); \
598 SOFTIRQ_EXIT();
599
600#define E2() \
601 \
602 HARDIRQ_DISABLE(); \
603 LOCK(A); \
604 HARDIRQ_ENABLE(); \
605 UNLOCK(A);
606
607/*
608 * Generate 12 testcases:
609 */
610#include "locking-selftest-spin.h"
611GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_spin)
612
613#include "locking-selftest-wlock.h"
614GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_wlock)
615
616#include "locking-selftest-rlock.h"
617GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_rlock)
618
619#undef E1
620#undef E2
621
622/*
623 * Enabling irqs with an irq-safe lock held:
624 */
625#define E1() \
626 \
627 IRQ_ENTER(); \
628 LOCK(A); \
629 UNLOCK(A); \
630 IRQ_EXIT();
631
632#define E2() \
633 \
634 IRQ_DISABLE(); \
635 LOCK(A); \
636 IRQ_ENABLE(); \
637 UNLOCK(A);
638
639/*
640 * Generate 24 testcases:
641 */
642#include "locking-selftest-spin-hardirq.h"
643GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_spin)
644
645#include "locking-selftest-rlock-hardirq.h"
646GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_rlock)
647
648#include "locking-selftest-wlock-hardirq.h"
649GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_wlock)
650
651#include "locking-selftest-spin-softirq.h"
652GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_spin)
653
654#include "locking-selftest-rlock-softirq.h"
655GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_rlock)
656
657#include "locking-selftest-wlock-softirq.h"
658GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_wlock)
659
660#undef E1
661#undef E2
662
663/*
664 * Acquiring a irq-unsafe lock while holding an irq-safe-lock:
665 */
666#define E1() \
667 \
668 LOCK(A); \
669 LOCK(B); \
670 UNLOCK(B); \
671 UNLOCK(A); \
672
673#define E2() \
674 \
675 LOCK(B); \
676 UNLOCK(B);
677
678#define E3() \
679 \
680 IRQ_ENTER(); \
681 LOCK(A); \
682 UNLOCK(A); \
683 IRQ_EXIT();
684
685/*
686 * Generate 36 testcases:
687 */
688#include "locking-selftest-spin-hardirq.h"
689GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_spin)
690
691#include "locking-selftest-rlock-hardirq.h"
692GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_rlock)
693
694#include "locking-selftest-wlock-hardirq.h"
695GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_wlock)
696
697#include "locking-selftest-spin-softirq.h"
698GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_spin)
699
700#include "locking-selftest-rlock-softirq.h"
701GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_rlock)
702
703#include "locking-selftest-wlock-softirq.h"
704GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_wlock)
705
706#undef E1
707#undef E2
708#undef E3
709
710/*
711 * If a lock turns into softirq-safe, but earlier it took
712 * a softirq-unsafe lock:
713 */
714
715#define E1() \
716 IRQ_DISABLE(); \
717 LOCK(A); \
718 LOCK(B); \
719 UNLOCK(B); \
720 UNLOCK(A); \
721 IRQ_ENABLE();
722
723#define E2() \
724 LOCK(B); \
725 UNLOCK(B);
726
727#define E3() \
728 IRQ_ENTER(); \
729 LOCK(A); \
730 UNLOCK(A); \
731 IRQ_EXIT();
732
733/*
734 * Generate 36 testcases:
735 */
736#include "locking-selftest-spin-hardirq.h"
737GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_spin)
738
739#include "locking-selftest-rlock-hardirq.h"
740GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_rlock)
741
742#include "locking-selftest-wlock-hardirq.h"
743GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_wlock)
744
745#include "locking-selftest-spin-softirq.h"
746GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_spin)
747
748#include "locking-selftest-rlock-softirq.h"
749GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_rlock)
750
751#include "locking-selftest-wlock-softirq.h"
752GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_wlock)
753
754#undef E1
755#undef E2
756#undef E3
757
758/*
759 * read-lock / write-lock irq inversion.
760 *
761 * Deadlock scenario:
762 *
763 * CPU#1 is at #1, i.e. it has write-locked A, but has not
764 * taken B yet.
765 *
766 * CPU#2 is at #2, i.e. it has locked B.
767 *
768 * Hardirq hits CPU#2 at point #2 and is trying to read-lock A.
769 *
770 * The deadlock occurs because CPU#1 will spin on B, and CPU#2
771 * will spin on A.
772 */
773
774#define E1() \
775 \
776 IRQ_DISABLE(); \
777 WL(A); \
778 LOCK(B); \
779 UNLOCK(B); \
780 WU(A); \
781 IRQ_ENABLE();
782
783#define E2() \
784 \
785 LOCK(B); \
786 UNLOCK(B);
787
788#define E3() \
789 \
790 IRQ_ENTER(); \
791 RL(A); \
792 RU(A); \
793 IRQ_EXIT();
794
795/*
796 * Generate 36 testcases:
797 */
798#include "locking-selftest-spin-hardirq.h"
799GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_spin)
800
801#include "locking-selftest-rlock-hardirq.h"
802GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_rlock)
803
804#include "locking-selftest-wlock-hardirq.h"
805GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_wlock)
806
807#include "locking-selftest-spin-softirq.h"
808GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_spin)
809
810#include "locking-selftest-rlock-softirq.h"
811GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_rlock)
812
813#include "locking-selftest-wlock-softirq.h"
814GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_wlock)
815
816#undef E1
817#undef E2
818#undef E3
819
820/*
821 * read-lock / write-lock recursion that is actually safe.
822 */
823
824#define E1() \
825 \
826 IRQ_DISABLE(); \
827 WL(A); \
828 WU(A); \
829 IRQ_ENABLE();
830
831#define E2() \
832 \
833 RL(A); \
834 RU(A); \
835
836#define E3() \
837 \
838 IRQ_ENTER(); \
839 RL(A); \
840 L(B); \
841 U(B); \
842 RU(A); \
843 IRQ_EXIT();
844
845/*
846 * Generate 12 testcases:
847 */
848#include "locking-selftest-hardirq.h"
849GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_hard)
850
851#include "locking-selftest-softirq.h"
852GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft)
853
854#undef E1
855#undef E2
856#undef E3
857
858/*
859 * read-lock / write-lock recursion that is unsafe.
860 */
861
862#define E1() \
863 \
864 IRQ_DISABLE(); \
865 L(B); \
866 WL(A); \
867 WU(A); \
868 U(B); \
869 IRQ_ENABLE();
870
871#define E2() \
872 \
873 RL(A); \
874 RU(A); \
875
876#define E3() \
877 \
878 IRQ_ENTER(); \
879 L(B); \
880 U(B); \
881 IRQ_EXIT();
882
883/*
884 * Generate 12 testcases:
885 */
886#include "locking-selftest-hardirq.h"
887// GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion2_hard)
888
889#include "locking-selftest-softirq.h"
890// GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion2_soft)
891
892#define lockdep_reset()
893#define lockdep_reset_lock(x)
894
895#ifdef CONFIG_DEBUG_LOCK_ALLOC
896# define I_SPINLOCK(x) lockdep_reset_lock(&lock_##x.dep_map)
897# define I_RWLOCK(x) lockdep_reset_lock(&rwlock_##x.dep_map)
898# define I_MUTEX(x) lockdep_reset_lock(&mutex_##x.dep_map)
899# define I_RWSEM(x) lockdep_reset_lock(&rwsem_##x.dep_map)
900#else
901# define I_SPINLOCK(x)
902# define I_RWLOCK(x)
903# define I_MUTEX(x)
904# define I_RWSEM(x)
905#endif
906
907#define I1(x) \
908 do { \
909 I_SPINLOCK(x); \
910 I_RWLOCK(x); \
911 I_MUTEX(x); \
912 I_RWSEM(x); \
913 } while (0)
914
915#define I2(x) \
916 do { \
917 spin_lock_init(&lock_##x); \
918 rwlock_init(&rwlock_##x); \
919 mutex_init(&mutex_##x); \
920 init_rwsem(&rwsem_##x); \
921 } while (0)
922
923static void reset_locks(void)
924{
925 local_irq_disable();
926 I1(A); I1(B); I1(C); I1(D);
927 I1(X1); I1(X2); I1(Y1); I1(Y2); I1(Z1); I1(Z2);
928 lockdep_reset();
929 I2(A); I2(B); I2(C); I2(D);
930 init_shared_classes();
931 local_irq_enable();
932}
933
934#undef I
935
936static int testcase_total;
937static int testcase_successes;
938static int expected_testcase_failures;
939static int unexpected_testcase_failures;
940
941static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask)
942{
943 unsigned long saved_preempt_count = preempt_count();
944 int expected_failure = 0;
945
946 WARN_ON(irqs_disabled());
947
948 testcase_fn();
949 /*
950 * Filter out expected failures:
951 */
952#ifndef CONFIG_PROVE_LOCKING
953 if ((lockclass_mask & LOCKTYPE_SPIN) && debug_locks != expected)
954 expected_failure = 1;
955 if ((lockclass_mask & LOCKTYPE_RWLOCK) && debug_locks != expected)
956 expected_failure = 1;
957 if ((lockclass_mask & LOCKTYPE_MUTEX) && debug_locks != expected)
958 expected_failure = 1;
959 if ((lockclass_mask & LOCKTYPE_RWSEM) && debug_locks != expected)
960 expected_failure = 1;
961#endif
962 if (debug_locks != expected) {
963 if (expected_failure) {
964 expected_testcase_failures++;
965 printk("failed|");
966 } else {
967 unexpected_testcase_failures++;
968 printk("FAILED|");
969 }
970 } else {
971 testcase_successes++;
972 printk(" ok |");
973 }
974 testcase_total++;
975
976 if (debug_locks_verbose)
977 printk(" lockclass mask: %x, debug_locks: %d, expected: %d\n",
978 lockclass_mask, debug_locks, expected);
979 /*
980 * Some tests (e.g. double-unlock) might corrupt the preemption
981 * count, so restore it:
982 */
983 preempt_count() = saved_preempt_count;
984#ifdef CONFIG_TRACE_IRQFLAGS
985 if (softirq_count())
986 current->softirqs_enabled = 0;
987 else
988 current->softirqs_enabled = 1;
989#endif
990
991 reset_locks();
992}
993
994static inline void print_testname(const char *testname)
995{
996 printk("%33s:", testname);
997}
998
999#define DO_TESTCASE_1(desc, name, nr) \
1000 print_testname(desc"/"#nr); \
1001 dotest(name##_##nr, SUCCESS, LOCKTYPE_RWLOCK); \
1002 printk("\n");
1003
1004#define DO_TESTCASE_1B(desc, name, nr) \
1005 print_testname(desc"/"#nr); \
1006 dotest(name##_##nr, FAILURE, LOCKTYPE_RWLOCK); \
1007 printk("\n");
1008
1009#define DO_TESTCASE_3(desc, name, nr) \
1010 print_testname(desc"/"#nr); \
1011 dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN); \
1012 dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK); \
1013 dotest(name##_rlock_##nr, SUCCESS, LOCKTYPE_RWLOCK); \
1014 printk("\n");
1015
1016#define DO_TESTCASE_3RW(desc, name, nr) \
1017 print_testname(desc"/"#nr); \
1018 dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN|LOCKTYPE_RWLOCK);\
1019 dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK); \
1020 dotest(name##_rlock_##nr, SUCCESS, LOCKTYPE_RWLOCK); \
1021 printk("\n");
1022
1023#define DO_TESTCASE_6(desc, name) \
1024 print_testname(desc); \
1025 dotest(name##_spin, FAILURE, LOCKTYPE_SPIN); \
1026 dotest(name##_wlock, FAILURE, LOCKTYPE_RWLOCK); \
1027 dotest(name##_rlock, FAILURE, LOCKTYPE_RWLOCK); \
1028 dotest(name##_mutex, FAILURE, LOCKTYPE_MUTEX); \
1029 dotest(name##_wsem, FAILURE, LOCKTYPE_RWSEM); \
1030 dotest(name##_rsem, FAILURE, LOCKTYPE_RWSEM); \
1031 printk("\n");
1032
1033#define DO_TESTCASE_6_SUCCESS(desc, name) \
1034 print_testname(desc); \
1035 dotest(name##_spin, SUCCESS, LOCKTYPE_SPIN); \
1036 dotest(name##_wlock, SUCCESS, LOCKTYPE_RWLOCK); \
1037 dotest(name##_rlock, SUCCESS, LOCKTYPE_RWLOCK); \
1038 dotest(name##_mutex, SUCCESS, LOCKTYPE_MUTEX); \
1039 dotest(name##_wsem, SUCCESS, LOCKTYPE_RWSEM); \
1040 dotest(name##_rsem, SUCCESS, LOCKTYPE_RWSEM); \
1041 printk("\n");
1042
1043/*
1044 * 'read' variant: rlocks must not trigger.
1045 */
1046#define DO_TESTCASE_6R(desc, name) \
1047 print_testname(desc); \
1048 dotest(name##_spin, FAILURE, LOCKTYPE_SPIN); \
1049 dotest(name##_wlock, FAILURE, LOCKTYPE_RWLOCK); \
1050 dotest(name##_rlock, SUCCESS, LOCKTYPE_RWLOCK); \
1051 dotest(name##_mutex, FAILURE, LOCKTYPE_MUTEX); \
1052 dotest(name##_wsem, FAILURE, LOCKTYPE_RWSEM); \
1053 dotest(name##_rsem, FAILURE, LOCKTYPE_RWSEM); \
1054 printk("\n");
1055
1056#define DO_TESTCASE_2I(desc, name, nr) \
1057 DO_TESTCASE_1("hard-"desc, name##_hard, nr); \
1058 DO_TESTCASE_1("soft-"desc, name##_soft, nr);
1059
1060#define DO_TESTCASE_2IB(desc, name, nr) \
1061 DO_TESTCASE_1B("hard-"desc, name##_hard, nr); \
1062 DO_TESTCASE_1B("soft-"desc, name##_soft, nr);
1063
1064#define DO_TESTCASE_6I(desc, name, nr) \
1065 DO_TESTCASE_3("hard-"desc, name##_hard, nr); \
1066 DO_TESTCASE_3("soft-"desc, name##_soft, nr);
1067
1068#define DO_TESTCASE_6IRW(desc, name, nr) \
1069 DO_TESTCASE_3RW("hard-"desc, name##_hard, nr); \
1070 DO_TESTCASE_3RW("soft-"desc, name##_soft, nr);
1071
1072#define DO_TESTCASE_2x3(desc, name) \
1073 DO_TESTCASE_3(desc, name, 12); \
1074 DO_TESTCASE_3(desc, name, 21);
1075
1076#define DO_TESTCASE_2x6(desc, name) \
1077 DO_TESTCASE_6I(desc, name, 12); \
1078 DO_TESTCASE_6I(desc, name, 21);
1079
1080#define DO_TESTCASE_6x2(desc, name) \
1081 DO_TESTCASE_2I(desc, name, 123); \
1082 DO_TESTCASE_2I(desc, name, 132); \
1083 DO_TESTCASE_2I(desc, name, 213); \
1084 DO_TESTCASE_2I(desc, name, 231); \
1085 DO_TESTCASE_2I(desc, name, 312); \
1086 DO_TESTCASE_2I(desc, name, 321);
1087
1088#define DO_TESTCASE_6x2B(desc, name) \
1089 DO_TESTCASE_2IB(desc, name, 123); \
1090 DO_TESTCASE_2IB(desc, name, 132); \
1091 DO_TESTCASE_2IB(desc, name, 213); \
1092 DO_TESTCASE_2IB(desc, name, 231); \
1093 DO_TESTCASE_2IB(desc, name, 312); \
1094 DO_TESTCASE_2IB(desc, name, 321);
1095
1096#define DO_TESTCASE_6x6(desc, name) \
1097 DO_TESTCASE_6I(desc, name, 123); \
1098 DO_TESTCASE_6I(desc, name, 132); \
1099 DO_TESTCASE_6I(desc, name, 213); \
1100 DO_TESTCASE_6I(desc, name, 231); \
1101 DO_TESTCASE_6I(desc, name, 312); \
1102 DO_TESTCASE_6I(desc, name, 321);
1103
1104#define DO_TESTCASE_6x6RW(desc, name) \
1105 DO_TESTCASE_6IRW(desc, name, 123); \
1106 DO_TESTCASE_6IRW(desc, name, 132); \
1107 DO_TESTCASE_6IRW(desc, name, 213); \
1108 DO_TESTCASE_6IRW(desc, name, 231); \
1109 DO_TESTCASE_6IRW(desc, name, 312); \
1110 DO_TESTCASE_6IRW(desc, name, 321);
1111
1112
1113void locking_selftest(void)
1114{
1115 /*
1116 * Got a locking failure before the selftest ran?
1117 */
1118 if (!debug_locks) {
1119 printk("----------------------------------\n");
1120 printk("| Locking API testsuite disabled |\n");
1121 printk("----------------------------------\n");
1122 return;
1123 }
1124
1125 /*
1126 * Run the testsuite:
1127 */
1128 printk("------------------------\n");
1129 printk("| Locking API testsuite:\n");
1130 printk("----------------------------------------------------------------------------\n");
1131 printk(" | spin |wlock |rlock |mutex | wsem | rsem |\n");
1132 printk(" --------------------------------------------------------------------------\n");
1133
1134 init_shared_classes();
1135 debug_locks_silent = !debug_locks_verbose;
1136
1137 DO_TESTCASE_6("A-A deadlock", AA);
1138 DO_TESTCASE_6R("A-B-B-A deadlock", ABBA);
1139 DO_TESTCASE_6R("A-B-B-C-C-A deadlock", ABBCCA);
1140 DO_TESTCASE_6R("A-B-C-A-B-C deadlock", ABCABC);
1141 DO_TESTCASE_6R("A-B-B-C-C-D-D-A deadlock", ABBCCDDA);
1142 DO_TESTCASE_6R("A-B-C-D-B-D-D-A deadlock", ABCDBDDA);
1143 DO_TESTCASE_6R("A-B-C-D-B-C-D-A deadlock", ABCDBCDA);
1144 DO_TESTCASE_6("double unlock", double_unlock);
1145 DO_TESTCASE_6("initialize held", init_held);
1146 DO_TESTCASE_6_SUCCESS("bad unlock order", bad_unlock_order);
1147
1148 printk(" --------------------------------------------------------------------------\n");
1149 print_testname("recursive read-lock");
1150 printk(" |");
1151 dotest(rlock_AA1, SUCCESS, LOCKTYPE_RWLOCK);
1152 printk(" |");
1153 dotest(rsem_AA1, FAILURE, LOCKTYPE_RWSEM);
1154 printk("\n");
1155
1156 print_testname("recursive read-lock #2");
1157 printk(" |");
1158 dotest(rlock_AA1B, FAILURE, LOCKTYPE_RWLOCK);
1159 printk(" |");
1160 dotest(rsem_AA1B, FAILURE, LOCKTYPE_RWSEM);
1161 printk("\n");
1162
1163 print_testname("mixed read-write-lock");
1164 printk(" |");
1165 dotest(rlock_AA2, FAILURE, LOCKTYPE_RWLOCK);
1166 printk(" |");
1167 dotest(rsem_AA2, FAILURE, LOCKTYPE_RWSEM);
1168 printk("\n");
1169
1170 print_testname("mixed write-read-lock");
1171 printk(" |");
1172 dotest(rlock_AA3, FAILURE, LOCKTYPE_RWLOCK);
1173 printk(" |");
1174 dotest(rsem_AA3, FAILURE, LOCKTYPE_RWSEM);
1175 printk("\n");
1176
1177 printk(" --------------------------------------------------------------------------\n");
1178
1179 /*
1180 * irq-context testcases:
1181 */
1182 DO_TESTCASE_2x6("irqs-on + irq-safe-A", irqsafe1);
1183 DO_TESTCASE_2x3("sirq-safe-A => hirqs-on", irqsafe2A);
1184 DO_TESTCASE_2x6("safe-A + irqs-on", irqsafe2B);
1185 DO_TESTCASE_6x6("safe-A + unsafe-B #1", irqsafe3);
1186 DO_TESTCASE_6x6("safe-A + unsafe-B #2", irqsafe4);
1187 DO_TESTCASE_6x6RW("irq lock-inversion", irq_inversion);
1188
1189 DO_TESTCASE_6x2("irq read-recursion", irq_read_recursion);
1190// DO_TESTCASE_6x2B("irq read-recursion #2", irq_read_recursion2);
1191
1192 if (unexpected_testcase_failures) {
1193 printk("-----------------------------------------------------------------\n");
1194 debug_locks = 0;
1195 printk("BUG: %3d unexpected failures (out of %3d) - debugging disabled! |\n",
1196 unexpected_testcase_failures, testcase_total);
1197 printk("-----------------------------------------------------------------\n");
1198 } else if (expected_testcase_failures && testcase_successes) {
1199 printk("--------------------------------------------------------\n");
1200 printk("%3d out of %3d testcases failed, as expected. |\n",
1201 expected_testcase_failures, testcase_total);
1202 printk("----------------------------------------------------\n");
1203 debug_locks = 1;
1204 } else if (expected_testcase_failures && !testcase_successes) {
1205 printk("--------------------------------------------------------\n");
1206 printk("All %3d testcases failed, as expected. |\n",
1207 expected_testcase_failures);
1208 printk("----------------------------------------\n");
1209 debug_locks = 1;
1210 } else {
1211 printk("-------------------------------------------------------\n");
1212 printk("Good, all %3d testcases passed! |\n",
1213 testcase_successes);
1214 printk("---------------------------------\n");
1215 debug_locks = 1;
1216 }
1217 debug_locks_silent = 0;
1218}