Commit cae2ed9aa573415c6e5de9a09b7ff0d74af793bc

Authored by Ingo Molnar
Committed by Linus Torvalds
1 parent 1f194a4c39

[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>

Showing 18 changed files with 1347 additions and 0 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -435,6 +435,15 @@
435 435  
436 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 447 decnet= [HW,NET]
439 448 Format: <area>[,<node>]
440 449 See also Documentation/networking/decnet.txt.
... ... @@ -149,6 +149,17 @@
149 149 If you say Y here, various routines which may sleep will become very
150 150 noisy if they are called with a spinlock held.
151 151  
  152 +config 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 +
152 163 config STACKTRACE
153 164 bool
154 165 depends on STACKTRACE_SUPPORT
... ... @@ -18,6 +18,7 @@
18 18 CFLAGS_kobject_uevent.o += -DDEBUG
19 19 endif
20 20  
  21 +obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
21 22 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
22 23 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
23 24 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
lib/locking-selftest-hardirq.h
  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
lib/locking-selftest-mutex.h
  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
lib/locking-selftest-rlock-hardirq.h
  1 +#include "locking-selftest-rlock.h"
  2 +#include "locking-selftest-hardirq.h"
lib/locking-selftest-rlock-softirq.h
  1 +#include "locking-selftest-rlock.h"
  2 +#include "locking-selftest-softirq.h"
lib/locking-selftest-rlock.h
  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
lib/locking-selftest-rsem.h
  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
lib/locking-selftest-softirq.h
  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
lib/locking-selftest-spin-hardirq.h
  1 +#include "locking-selftest-spin.h"
  2 +#include "locking-selftest-hardirq.h"
lib/locking-selftest-spin-softirq.h
  1 +#include "locking-selftest-spin.h"
  2 +#include "locking-selftest-softirq.h"
lib/locking-selftest-spin.h
  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
lib/locking-selftest-wlock-hardirq.h
  1 +#include "locking-selftest-wlock.h"
  2 +#include "locking-selftest-hardirq.h"
lib/locking-selftest-wlock-softirq.h
  1 +#include "locking-selftest-wlock.h"
  2 +#include "locking-selftest-softirq.h"
lib/locking-selftest-wlock.h
  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
lib/locking-selftest-wsem.h
  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
lib/locking-selftest.c
Changes suppressed. Click to show
  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 + */
  27 +static unsigned int debug_locks_verbose;
  28 +
  29 +static 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 + */
  50 +static DEFINE_SPINLOCK(lock_A);
  51 +static DEFINE_SPINLOCK(lock_B);
  52 +static DEFINE_SPINLOCK(lock_C);
  53 +static DEFINE_SPINLOCK(lock_D);
  54 +
  55 +static DEFINE_RWLOCK(rwlock_A);
  56 +static DEFINE_RWLOCK(rwlock_B);
  57 +static DEFINE_RWLOCK(rwlock_C);
  58 +static DEFINE_RWLOCK(rwlock_D);
  59 +
  60 +static DEFINE_MUTEX(mutex_A);
  61 +static DEFINE_MUTEX(mutex_B);
  62 +static DEFINE_MUTEX(mutex_C);
  63 +static DEFINE_MUTEX(mutex_D);
  64 +
  65 +static DECLARE_RWSEM(rwsem_A);
  66 +static DECLARE_RWSEM(rwsem_B);
  67 +static DECLARE_RWSEM(rwsem_C);
  68 +static 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 + */
  76 +static DEFINE_SPINLOCK(lock_X1);
  77 +static DEFINE_SPINLOCK(lock_X2);
  78 +static DEFINE_SPINLOCK(lock_Y1);
  79 +static DEFINE_SPINLOCK(lock_Y2);
  80 +static DEFINE_SPINLOCK(lock_Z1);
  81 +static DEFINE_SPINLOCK(lock_Z2);
  82 +
  83 +static DEFINE_RWLOCK(rwlock_X1);
  84 +static DEFINE_RWLOCK(rwlock_X2);
  85 +static DEFINE_RWLOCK(rwlock_Y1);
  86 +static DEFINE_RWLOCK(rwlock_Y2);
  87 +static DEFINE_RWLOCK(rwlock_Z1);
  88 +static DEFINE_RWLOCK(rwlock_Z2);
  89 +
  90 +static DEFINE_MUTEX(mutex_X1);
  91 +static DEFINE_MUTEX(mutex_X2);
  92 +static DEFINE_MUTEX(mutex_Y1);
  93 +static DEFINE_MUTEX(mutex_Y2);
  94 +static DEFINE_MUTEX(mutex_Z1);
  95 +static DEFINE_MUTEX(mutex_Z2);
  96 +
  97 +static DECLARE_RWSEM(rwsem_X1);
  98 +static DECLARE_RWSEM(rwsem_X2);
  99 +static DECLARE_RWSEM(rwsem_Y1);
  100 +static DECLARE_RWSEM(rwsem_Y2);
  101 +static DECLARE_RWSEM(rwsem_Z1);
  102 +static 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) \
  109 +static noinline void \
  110 +init_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 +
  119 +INIT_CLASS_FUNC(X)
  120 +INIT_CLASS_FUNC(Y)
  121 +INIT_CLASS_FUNC(Z)
  122 +
  123 +static 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 + \
  205 +static void name(void) { E(); }
  206 +
  207 +#define GENERATE_PERMUTATIONS_2_EVENTS(name) \
  208 + \
  209 +static void name##_12(void) { E1(); E2(); } \
  210 +static void name##_21(void) { E2(); E1(); }
  211 +
  212 +#define GENERATE_PERMUTATIONS_3_EVENTS(name) \
  213 + \
  214 +static void name##_123(void) { E1(); E2(); E3(); } \
  215 +static void name##_132(void) { E1(); E3(); E2(); } \
  216 +static void name##_213(void) { E2(); E1(); E3(); } \
  217 +static void name##_231(void) { E2(); E3(); E1(); } \
  218 +static void name##_312(void) { E3(); E1(); E2(); } \
  219 +static 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"
  234 +GENERATE_TESTCASE(AA_spin)
  235 +#include "locking-selftest-wlock.h"
  236 +GENERATE_TESTCASE(AA_wlock)
  237 +#include "locking-selftest-rlock.h"
  238 +GENERATE_TESTCASE(AA_rlock)
  239 +#include "locking-selftest-mutex.h"
  240 +GENERATE_TESTCASE(AA_mutex)
  241 +#include "locking-selftest-wsem.h"
  242 +GENERATE_TESTCASE(AA_wsem)
  243 +#include "locking-selftest-rsem.h"
  244 +GENERATE_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 + */
  252 +static void rlock_AA1(void)
  253 +{
  254 + RL(X1);
  255 + RL(X1); // this one should NOT fail
  256 +}
  257 +
  258 +static void rlock_AA1B(void)
  259 +{
  260 + RL(X1);
  261 + RL(X2); // this one should fail
  262 +}
  263 +
  264 +static void rsem_AA1(void)
  265 +{
  266 + RSL(X1);
  267 + RSL(X1); // this one should fail
  268 +}
  269 +
  270 +static 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 + */
  278 +static void rlock_AA2(void)
  279 +{
  280 + RL(X1);
  281 + WL(X2); // this one should fail
  282 +}
  283 +
  284 +static void rsem_AA2(void)
  285 +{
  286 + RSL(X1);
  287 + WSL(X2); // this one should fail
  288 +}
  289 +
  290 +static void rlock_AA3(void)
  291 +{
  292 + WL(X1);
  293 + RL(X2); // this one should fail
  294 +}
  295 +
  296 +static 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"
  315 +GENERATE_TESTCASE(ABBA_spin)
  316 +#include "locking-selftest-wlock.h"
  317 +GENERATE_TESTCASE(ABBA_wlock)
  318 +#include "locking-selftest-rlock.h"
  319 +GENERATE_TESTCASE(ABBA_rlock)
  320 +#include "locking-selftest-mutex.h"
  321 +GENERATE_TESTCASE(ABBA_mutex)
  322 +#include "locking-selftest-wsem.h"
  323 +GENERATE_TESTCASE(ABBA_wsem)
  324 +#include "locking-selftest-rsem.h"
  325 +GENERATE_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"
  343 +GENERATE_TESTCASE(ABBCCA_spin)
  344 +#include "locking-selftest-wlock.h"
  345 +GENERATE_TESTCASE(ABBCCA_wlock)
  346 +#include "locking-selftest-rlock.h"
  347 +GENERATE_TESTCASE(ABBCCA_rlock)
  348 +#include "locking-selftest-mutex.h"
  349 +GENERATE_TESTCASE(ABBCCA_mutex)
  350 +#include "locking-selftest-wsem.h"
  351 +GENERATE_TESTCASE(ABBCCA_wsem)
  352 +#include "locking-selftest-rsem.h"
  353 +GENERATE_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"
  371 +GENERATE_TESTCASE(ABCABC_spin)
  372 +#include "locking-selftest-wlock.h"
  373 +GENERATE_TESTCASE(ABCABC_wlock)
  374 +#include "locking-selftest-rlock.h"
  375 +GENERATE_TESTCASE(ABCABC_rlock)
  376 +#include "locking-selftest-mutex.h"
  377 +GENERATE_TESTCASE(ABCABC_mutex)
  378 +#include "locking-selftest-wsem.h"
  379 +GENERATE_TESTCASE(ABCABC_wsem)
  380 +#include "locking-selftest-rsem.h"
  381 +GENERATE_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"
  400 +GENERATE_TESTCASE(ABBCCDDA_spin)
  401 +#include "locking-selftest-wlock.h"
  402 +GENERATE_TESTCASE(ABBCCDDA_wlock)
  403 +#include "locking-selftest-rlock.h"
  404 +GENERATE_TESTCASE(ABBCCDDA_rlock)
  405 +#include "locking-selftest-mutex.h"
  406 +GENERATE_TESTCASE(ABBCCDDA_mutex)
  407 +#include "locking-selftest-wsem.h"
  408 +GENERATE_TESTCASE(ABBCCDDA_wsem)
  409 +#include "locking-selftest-rsem.h"
  410 +GENERATE_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"
  428 +GENERATE_TESTCASE(ABCDBDDA_spin)
  429 +#include "locking-selftest-wlock.h"
  430 +GENERATE_TESTCASE(ABCDBDDA_wlock)
  431 +#include "locking-selftest-rlock.h"
  432 +GENERATE_TESTCASE(ABCDBDDA_rlock)
  433 +#include "locking-selftest-mutex.h"
  434 +GENERATE_TESTCASE(ABCDBDDA_mutex)
  435 +#include "locking-selftest-wsem.h"
  436 +GENERATE_TESTCASE(ABCDBDDA_wsem)
  437 +#include "locking-selftest-rsem.h"
  438 +GENERATE_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"
  456 +GENERATE_TESTCASE(ABCDBCDA_spin)
  457 +#include "locking-selftest-wlock.h"
  458 +GENERATE_TESTCASE(ABCDBCDA_wlock)
  459 +#include "locking-selftest-rlock.h"
  460 +GENERATE_TESTCASE(ABCDBCDA_rlock)
  461 +#include "locking-selftest-mutex.h"
  462 +GENERATE_TESTCASE(ABCDBCDA_mutex)
  463 +#include "locking-selftest-wsem.h"
  464 +GENERATE_TESTCASE(ABCDBCDA_wsem)
  465 +#include "locking-selftest-rsem.h"
  466 +GENERATE_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"
  483 +GENERATE_TESTCASE(double_unlock_spin)
  484 +#include "locking-selftest-wlock.h"
  485 +GENERATE_TESTCASE(double_unlock_wlock)
  486 +#include "locking-selftest-rlock.h"
  487 +GENERATE_TESTCASE(double_unlock_rlock)
  488 +#include "locking-selftest-mutex.h"
  489 +GENERATE_TESTCASE(double_unlock_mutex)
  490 +#include "locking-selftest-wsem.h"
  491 +GENERATE_TESTCASE(double_unlock_wsem)
  492 +#include "locking-selftest-rsem.h"
  493 +GENERATE_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"
  511 +GENERATE_TESTCASE(bad_unlock_order_spin)
  512 +#include "locking-selftest-wlock.h"
  513 +GENERATE_TESTCASE(bad_unlock_order_wlock)
  514 +#include "locking-selftest-rlock.h"
  515 +GENERATE_TESTCASE(bad_unlock_order_rlock)
  516 +#include "locking-selftest-mutex.h"
  517 +GENERATE_TESTCASE(bad_unlock_order_mutex)
  518 +#include "locking-selftest-wsem.h"
  519 +GENERATE_TESTCASE(bad_unlock_order_wsem)
  520 +#include "locking-selftest-rsem.h"
  521 +GENERATE_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"
  537 +GENERATE_TESTCASE(init_held_spin)
  538 +#include "locking-selftest-wlock.h"
  539 +GENERATE_TESTCASE(init_held_wlock)
  540 +#include "locking-selftest-rlock.h"
  541 +GENERATE_TESTCASE(init_held_rlock)
  542 +#include "locking-selftest-mutex.h"
  543 +GENERATE_TESTCASE(init_held_mutex)
  544 +#include "locking-selftest-wsem.h"
  545 +GENERATE_TESTCASE(init_held_wsem)
  546 +#include "locking-selftest-rsem.h"
  547 +GENERATE_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"
  570 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_spin)
  571 +
  572 +#include "locking-selftest-rlock-hardirq.h"
  573 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_rlock)
  574 +
  575 +#include "locking-selftest-wlock-hardirq.h"
  576 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_wlock)
  577 +
  578 +#include "locking-selftest-spin-softirq.h"
  579 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_spin)
  580 +
  581 +#include "locking-selftest-rlock-softirq.h"
  582 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_rlock)
  583 +
  584 +#include "locking-selftest-wlock-softirq.h"
  585 +GENERATE_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"
  611 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_spin)
  612 +
  613 +#include "locking-selftest-wlock.h"
  614 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_wlock)
  615 +
  616 +#include "locking-selftest-rlock.h"
  617 +GENERATE_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"
  643 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_spin)
  644 +
  645 +#include "locking-selftest-rlock-hardirq.h"
  646 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_rlock)
  647 +
  648 +#include "locking-selftest-wlock-hardirq.h"
  649 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_wlock)
  650 +
  651 +#include "locking-selftest-spin-softirq.h"
  652 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_spin)
  653 +
  654 +#include "locking-selftest-rlock-softirq.h"
  655 +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_rlock)
  656 +
  657 +#include "locking-selftest-wlock-softirq.h"
  658 +GENERATE_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"
  689 +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_spin)
  690 +
  691 +#include "locking-selftest-rlock-hardirq.h"
  692 +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_rlock)
  693 +
  694 +#include "locking-selftest-wlock-hardirq.h"
  695 +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_wlock)
  696 +
  697 +#include "locking-selftest-spin-softirq.h"
  698 +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_spin)
  699 +
  700 +#include "locking-selftest-rlock-softirq.h"
  701 +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_rlock)
  702 +
  703 +#include "locking-selftest-wlock-softirq.h"
  704 +GENERATE_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"
  737 +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_spin)
  738 +
  739 +#include "locking-selftest-rlock-hardirq.h"
  740 +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_rlock)
  741 +
  742 +#include "locking-selftest-wlock-hardirq.h"
  743 +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_wlock)
  744 +
  745 +#include "locking-selftest-spin-softirq.h"
  746 +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_spin)
  747 +
  748 +#include "locking-selftest-rlock-softirq.h"
  749 +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_rlock)
  750 +
  751 +#include "locking-selftest-wlock-softirq.h"
  752 +GENERATE_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"
  799 +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_spin)
  800 +
  801 +#include "locking-selftest-rlock-hardirq.h"
  802 +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_rlock)
  803 +
  804 +#include "locking-selftest-wlock-hardirq.h"
  805 +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_wlock)
  806 +
  807 +#include "locking-selftest-spin-softirq.h"
  808 +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_spin)
  809 +
  810 +#include "locking-selftest-rlock-softirq.h"
  811 +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_rlock)
  812 +
  813 +#include "locking-selftest-wlock-softirq.h"
  814 +GENERATE_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"
  849 +GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_hard)
  850 +
  851 +#include "locking-selftest-softirq.h"
  852 +GENERATE_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 +
  923 +static 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 +
  936 +static int testcase_total;
  937 +static int testcase_successes;
  938 +static int expected_testcase_failures;
  939 +static int unexpected_testcase_failures;
  940 +
  941 +static 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 +
  994 +static 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 +
  1113 +void 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 +}