Skip to content

Commit

Permalink
locking/ww_mutex: Begin kselftests for ww_mutex
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Wilson <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Maarten Lankhorst <[email protected]>
Cc: Nicolai Hähnle <[email protected]>
Cc: Paul E. McKenney <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
ickle authored and Ingo Molnar committed Jan 14, 2017
1 parent 0186a6c commit f2a5fec
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 0 deletions.
1 change: 1 addition & 0 deletions kernel/locking/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem-xadd.o
obj-$(CONFIG_QUEUED_RWLOCKS) += qrwlock.o
obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o
obj-$(CONFIG_WW_MUTEX_SELFTEST) += test-ww_mutex.o
140 changes: 140 additions & 0 deletions kernel/locking/test-ww_mutex.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
* Module-based API test facility for ww_mutexes
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*/

#include <linux/kernel.h>

#include <linux/completion.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/ww_mutex.h>

static DEFINE_WW_CLASS(ww_class);

struct test_mutex {
struct work_struct work;
struct ww_mutex mutex;
struct completion ready, go, done;
unsigned int flags;
};

#define TEST_MTX_SPIN BIT(0)
#define TEST_MTX_TRY BIT(1)
#define TEST_MTX_CTX BIT(2)
#define __TEST_MTX_LAST BIT(3)

static void test_mutex_work(struct work_struct *work)
{
struct test_mutex *mtx = container_of(work, typeof(*mtx), work);

complete(&mtx->ready);
wait_for_completion(&mtx->go);

if (mtx->flags & TEST_MTX_TRY) {
while (!ww_mutex_trylock(&mtx->mutex))
cpu_relax();
} else {
ww_mutex_lock(&mtx->mutex, NULL);
}
complete(&mtx->done);
ww_mutex_unlock(&mtx->mutex);
}

static int __test_mutex(unsigned int flags)
{
#define TIMEOUT (HZ / 16)
struct test_mutex mtx;
struct ww_acquire_ctx ctx;
int ret;

ww_mutex_init(&mtx.mutex, &ww_class);
ww_acquire_init(&ctx, &ww_class);

INIT_WORK_ONSTACK(&mtx.work, test_mutex_work);
init_completion(&mtx.ready);
init_completion(&mtx.go);
init_completion(&mtx.done);
mtx.flags = flags;

schedule_work(&mtx.work);

wait_for_completion(&mtx.ready);
ww_mutex_lock(&mtx.mutex, (flags & TEST_MTX_CTX) ? &ctx : NULL);
complete(&mtx.go);
if (flags & TEST_MTX_SPIN) {
unsigned long timeout = jiffies + TIMEOUT;

ret = 0;
do {
if (completion_done(&mtx.done)) {
ret = -EINVAL;
break;
}
cpu_relax();
} while (time_before(jiffies, timeout));
} else {
ret = wait_for_completion_timeout(&mtx.done, TIMEOUT);
}
ww_mutex_unlock(&mtx.mutex);
ww_acquire_fini(&ctx);

if (ret) {
pr_err("%s(flags=%x): mutual exclusion failure\n",
__func__, flags);
ret = -EINVAL;
}

flush_work(&mtx.work);
destroy_work_on_stack(&mtx.work);
return ret;
#undef TIMEOUT
}

static int test_mutex(void)
{
int ret;
int i;

for (i = 0; i < __TEST_MTX_LAST; i++) {
ret = __test_mutex(i);
if (ret)
return ret;
}

return 0;
}

static int __init test_ww_mutex_init(void)
{
int ret;

ret = test_mutex();
if (ret)
return ret;

return 0;
}

static void __exit test_ww_mutex_exit(void)
{
}

module_init(test_ww_mutex_init);
module_exit(test_ww_mutex_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Intel Corporation");
12 changes: 12 additions & 0 deletions lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,18 @@ config LOCK_TORTURE_TEST
Say M if you want these torture tests to build as a module.
Say N if you are unsure.

config WW_MUTEX_SELFTEST
tristate "Wait/wound mutex selftests"
help
This option provides a kernel module that runs tests on the
on the struct ww_mutex locking API.

It is recommended to enable DEBUG_WW_MUTEX_SLOWPATH in conjunction
with this test harness.

Say M if you want these self tests to build as a module.
Say N if you are unsure.

endmenu # lock debugging

config TRACE_IRQFLAGS
Expand Down

0 comments on commit f2a5fec

Please sign in to comment.