Skip to content

Commit f2a5fec

Browse files
ickleIngo Molnar
authored and
Ingo Molnar
committed
locking/ww_mutex: Begin kselftests for ww_mutex
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Maarten Lankhorst <dev@mblankhorst.nl> Cc: Nicolai Hähnle <nhaehnle@gmail.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20161201114711.28697-4-chris@chris-wilson.co.uk Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 0186a6c commit f2a5fec

File tree

3 files changed

+153
-0
lines changed

3 files changed

+153
-0
lines changed

kernel/locking/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
2828
obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem-xadd.o
2929
obj-$(CONFIG_QUEUED_RWLOCKS) += qrwlock.o
3030
obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o
31+
obj-$(CONFIG_WW_MUTEX_SELFTEST) += test-ww_mutex.o

kernel/locking/test-ww_mutex.c

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Module-based API test facility for ww_mutexes
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, you can access it online at
16+
* http://www.gnu.org/licenses/gpl-2.0.html.
17+
*/
18+
19+
#include <linux/kernel.h>
20+
21+
#include <linux/completion.h>
22+
#include <linux/kthread.h>
23+
#include <linux/module.h>
24+
#include <linux/ww_mutex.h>
25+
26+
static DEFINE_WW_CLASS(ww_class);
27+
28+
struct test_mutex {
29+
struct work_struct work;
30+
struct ww_mutex mutex;
31+
struct completion ready, go, done;
32+
unsigned int flags;
33+
};
34+
35+
#define TEST_MTX_SPIN BIT(0)
36+
#define TEST_MTX_TRY BIT(1)
37+
#define TEST_MTX_CTX BIT(2)
38+
#define __TEST_MTX_LAST BIT(3)
39+
40+
static void test_mutex_work(struct work_struct *work)
41+
{
42+
struct test_mutex *mtx = container_of(work, typeof(*mtx), work);
43+
44+
complete(&mtx->ready);
45+
wait_for_completion(&mtx->go);
46+
47+
if (mtx->flags & TEST_MTX_TRY) {
48+
while (!ww_mutex_trylock(&mtx->mutex))
49+
cpu_relax();
50+
} else {
51+
ww_mutex_lock(&mtx->mutex, NULL);
52+
}
53+
complete(&mtx->done);
54+
ww_mutex_unlock(&mtx->mutex);
55+
}
56+
57+
static int __test_mutex(unsigned int flags)
58+
{
59+
#define TIMEOUT (HZ / 16)
60+
struct test_mutex mtx;
61+
struct ww_acquire_ctx ctx;
62+
int ret;
63+
64+
ww_mutex_init(&mtx.mutex, &ww_class);
65+
ww_acquire_init(&ctx, &ww_class);
66+
67+
INIT_WORK_ONSTACK(&mtx.work, test_mutex_work);
68+
init_completion(&mtx.ready);
69+
init_completion(&mtx.go);
70+
init_completion(&mtx.done);
71+
mtx.flags = flags;
72+
73+
schedule_work(&mtx.work);
74+
75+
wait_for_completion(&mtx.ready);
76+
ww_mutex_lock(&mtx.mutex, (flags & TEST_MTX_CTX) ? &ctx : NULL);
77+
complete(&mtx.go);
78+
if (flags & TEST_MTX_SPIN) {
79+
unsigned long timeout = jiffies + TIMEOUT;
80+
81+
ret = 0;
82+
do {
83+
if (completion_done(&mtx.done)) {
84+
ret = -EINVAL;
85+
break;
86+
}
87+
cpu_relax();
88+
} while (time_before(jiffies, timeout));
89+
} else {
90+
ret = wait_for_completion_timeout(&mtx.done, TIMEOUT);
91+
}
92+
ww_mutex_unlock(&mtx.mutex);
93+
ww_acquire_fini(&ctx);
94+
95+
if (ret) {
96+
pr_err("%s(flags=%x): mutual exclusion failure\n",
97+
__func__, flags);
98+
ret = -EINVAL;
99+
}
100+
101+
flush_work(&mtx.work);
102+
destroy_work_on_stack(&mtx.work);
103+
return ret;
104+
#undef TIMEOUT
105+
}
106+
107+
static int test_mutex(void)
108+
{
109+
int ret;
110+
int i;
111+
112+
for (i = 0; i < __TEST_MTX_LAST; i++) {
113+
ret = __test_mutex(i);
114+
if (ret)
115+
return ret;
116+
}
117+
118+
return 0;
119+
}
120+
121+
static int __init test_ww_mutex_init(void)
122+
{
123+
int ret;
124+
125+
ret = test_mutex();
126+
if (ret)
127+
return ret;
128+
129+
return 0;
130+
}
131+
132+
static void __exit test_ww_mutex_exit(void)
133+
{
134+
}
135+
136+
module_init(test_ww_mutex_init);
137+
module_exit(test_ww_mutex_exit);
138+
139+
MODULE_LICENSE("GPL");
140+
MODULE_AUTHOR("Intel Corporation");

lib/Kconfig.debug

+12
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,18 @@ config LOCK_TORTURE_TEST
11801180
Say M if you want these torture tests to build as a module.
11811181
Say N if you are unsure.
11821182

1183+
config WW_MUTEX_SELFTEST
1184+
tristate "Wait/wound mutex selftests"
1185+
help
1186+
This option provides a kernel module that runs tests on the
1187+
on the struct ww_mutex locking API.
1188+
1189+
It is recommended to enable DEBUG_WW_MUTEX_SLOWPATH in conjunction
1190+
with this test harness.
1191+
1192+
Say M if you want these self tests to build as a module.
1193+
Say N if you are unsure.
1194+
11831195
endmenu # lock debugging
11841196

11851197
config TRACE_IRQFLAGS

0 commit comments

Comments
 (0)