All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
To: lkml <linux-kernel@vger.kernel.org>
Cc: akpm@linux-foundation.org, mingo@elte.hu, ak@suse.de,
	sam@ravnborg.org, dhowells@redhat.com
Subject: [PATCH 5/7] Move synchro-test under tests/
Date: Thu, 10 Jan 2008 17:29:43 +0530	[thread overview]
Message-ID: <20080110115943.GF26577@in.ibm.com> (raw)
In-Reply-To: <20080110115428.GA26577@in.ibm.com>

From: Ananth N Mavinakayanahalli <ananth@in.ibm.com>

Move the synchro-test infrastructure to tests/

Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
---
 kernel/synchro-test.c |  526 --------------------------------------------------
 kernel/Makefile       |    1 
 lib/Kconfig.debug     |   14 -
 tests/Kconfig         |   14 +
 tests/Makefile        |    1 
 tests/synchro-test.c  |  526 ++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 541 insertions(+), 541 deletions(-)

Index: linux-2.6.24-rc6/kernel/Makefile
===================================================================
--- linux-2.6.24-rc6.orig/kernel/Makefile
+++ linux-2.6.24-rc6/kernel/Makefile
@@ -54,7 +54,6 @@ obj-$(CONFIG_SYSFS) += ksysfs.o
 obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
 obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
 obj-$(CONFIG_SECCOMP) += seccomp.o
-obj-$(CONFIG_DEBUG_SYNCHRO_TEST) += synchro-test.o
 obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o
 obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o
 ifeq ($(CONFIG_PREEMPT_RCU),y)
Index: linux-2.6.24-rc6/kernel/synchro-test.c
===================================================================
--- linux-2.6.24-rc6.orig/kernel/synchro-test.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/* synchro-test.c: run some threads to test the synchronisation primitives
- *
- * Copyright (C) 2005, 2006 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * 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.
- *
- * The module should be run as something like:
- *
- *	insmod synchro-test.ko rd=2 wr=2
- *	insmod synchro-test.ko mx=1
- *	insmod synchro-test.ko sm=2 ism=1
- *	insmod synchro-test.ko sm=2 ism=2
- *
- * See Documentation/synchro-test.txt for more information.
- */
-
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/moduleparam.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <asm/atomic.h>
-#include <linux/personality.h>
-#include <linux/smp_lock.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/completion.h>
-#include <linux/mutex.h>
-
-#define MAX_THREADS 64
-
-/*
- * Turn on self-validation if we do a one-shot boot-time test:
- */
-#ifndef MODULE
-# define VALIDATE_OPERATORS
-#endif
-
-static int nummx;
-static int numsm, seminit = 4;
-static int numrd, numwr, numdg;
-static int elapse = 5, load = 2, do_sched, interval = 2;
-static int verbose = 0;
-
-MODULE_AUTHOR("David Howells");
-MODULE_DESCRIPTION("Synchronisation primitive test demo");
-MODULE_LICENSE("GPL");
-
-module_param_named(v, verbose, int, 0);
-MODULE_PARM_DESC(verbose, "Verbosity");
-
-module_param_named(mx, nummx, int, 0);
-MODULE_PARM_DESC(nummx, "Number of mutex threads");
-
-module_param_named(sm, numsm, int, 0);
-MODULE_PARM_DESC(numsm, "Number of semaphore threads");
-
-module_param_named(ism, seminit, int, 0);
-MODULE_PARM_DESC(seminit, "Initial semaphore value");
-
-module_param_named(rd, numrd, int, 0);
-MODULE_PARM_DESC(numrd, "Number of reader threads");
-
-module_param_named(wr, numwr, int, 0);
-MODULE_PARM_DESC(numwr, "Number of writer threads");
-
-module_param_named(dg, numdg, int, 0);
-MODULE_PARM_DESC(numdg, "Number of downgrader threads");
-
-module_param(elapse, int, 0);
-MODULE_PARM_DESC(elapse, "Number of seconds to run for");
-
-module_param(load, int, 0);
-MODULE_PARM_DESC(load, "Length of load in uS");
-
-module_param(interval, int, 0);
-MODULE_PARM_DESC(interval, "Length of interval in uS before re-getting lock");
-
-module_param(do_sched, int, 0);
-MODULE_PARM_DESC(do_sched, "True if each thread should schedule regularly");
-
-/* the semaphores under test */
-static struct mutex ____cacheline_aligned mutex;
-static struct semaphore ____cacheline_aligned sem;
-static struct rw_semaphore ____cacheline_aligned rwsem;
-
-static atomic_t ____cacheline_aligned do_stuff		= ATOMIC_INIT(0);
-
-#ifdef VALIDATE_OPERATORS
-static atomic_t ____cacheline_aligned mutexes		= ATOMIC_INIT(0);
-static atomic_t ____cacheline_aligned semaphores	= ATOMIC_INIT(0);
-static atomic_t ____cacheline_aligned readers		= ATOMIC_INIT(0);
-static atomic_t ____cacheline_aligned writers		= ATOMIC_INIT(0);
-#endif
-
-static unsigned int ____cacheline_aligned mutexes_taken		[MAX_THREADS];
-static unsigned int ____cacheline_aligned semaphores_taken	[MAX_THREADS];
-static unsigned int ____cacheline_aligned reads_taken		[MAX_THREADS];
-static unsigned int ____cacheline_aligned writes_taken		[MAX_THREADS];
-static unsigned int ____cacheline_aligned downgrades_taken	[MAX_THREADS];
-
-static struct completion ____cacheline_aligned mx_comp[MAX_THREADS];
-static struct completion ____cacheline_aligned sm_comp[MAX_THREADS];
-static struct completion ____cacheline_aligned rd_comp[MAX_THREADS];
-static struct completion ____cacheline_aligned wr_comp[MAX_THREADS];
-static struct completion ____cacheline_aligned dg_comp[MAX_THREADS];
-
-static struct timer_list ____cacheline_aligned timer;
-
-#define ACCOUNT(var, N) var##_taken[N]++;
-
-#ifdef VALIDATE_OPERATORS
-#define TRACK(var, dir) atomic_##dir(&(var))
-
-#define CHECK(var, cond, val)						\
-do {									\
-	int x = atomic_read(&(var));					\
-	if (unlikely(!(x cond (val))))					\
-		printk("check [%s %s %d, == %d] failed in %s\n",	\
-		       #var, #cond, (val), x, __func__);		\
-} while (0)
-
-#else
-#define TRACK(var, dir)		do {} while(0)
-#define CHECK(var, cond, val)	do {} while(0)
-#endif
-
-static inline void do_mutex_lock(unsigned int N)
-{
-	mutex_lock(&mutex);
-
-	ACCOUNT(mutexes, N);
-	TRACK(mutexes, inc);
-	CHECK(mutexes, ==, 1);
-}
-
-static inline void do_mutex_unlock(unsigned int N)
-{
-	CHECK(mutexes, ==, 1);
-	TRACK(mutexes, dec);
-
-	mutex_unlock(&mutex);
-}
-
-static inline void do_down(unsigned int N)
-{
-	CHECK(mutexes, <, seminit);
-
-	down(&sem);
-
-	ACCOUNT(semaphores, N);
-	TRACK(semaphores, inc);
-}
-
-static inline void do_up(unsigned int N)
-{
-	CHECK(semaphores, >, 0);
-	TRACK(semaphores, dec);
-
-	up(&sem);
-}
-
-static inline void do_down_read(unsigned int N)
-{
-	down_read(&rwsem);
-
-	ACCOUNT(reads, N);
-	TRACK(readers, inc);
-	CHECK(readers, >, 0);
-	CHECK(writers, ==, 0);
-}
-
-static inline void do_up_read(unsigned int N)
-{
-	CHECK(readers, >, 0);
-	CHECK(writers, ==, 0);
-	TRACK(readers, dec);
-
-	up_read(&rwsem);
-}
-
-static inline void do_down_write(unsigned int N)
-{
-	down_write(&rwsem);
-
-	ACCOUNT(writes, N);
-	TRACK(writers, inc);
-	CHECK(writers, ==, 1);
-	CHECK(readers, ==, 0);
-}
-
-static inline void do_up_write(unsigned int N)
-{
-	CHECK(writers, ==, 1);
-	CHECK(readers, ==, 0);
-	TRACK(writers, dec);
-
-	up_write(&rwsem);
-}
-
-static inline void do_downgrade_write(unsigned int N)
-{
-	CHECK(writers, ==, 1);
-	CHECK(readers, ==, 0);
-	TRACK(writers, dec);
-	TRACK(readers, inc);
-
-	downgrade_write(&rwsem);
-
-	ACCOUNT(downgrades, N);
-}
-
-static inline void sched(void)
-{
-	if (do_sched)
-		schedule();
-}
-
-static int mutexer(void *arg)
-{
-	unsigned int N = (unsigned long) arg;
-
-	daemonize("Mutex%u", N);
-	set_user_nice(current, 19);
-
-	while (atomic_read(&do_stuff)) {
-		do_mutex_lock(N);
-		if (load)
-			udelay(load);
-		do_mutex_unlock(N);
-		sched();
-		if (interval)
-			udelay(interval);
-	}
-
-	if (verbose >= 2)
-		printk("%s: done\n", current->comm);
-	complete_and_exit(&mx_comp[N], 0);
-}
-
-static int semaphorer(void *arg)
-{
-	unsigned int N = (unsigned long) arg;
-
-	daemonize("Sem%u", N);
-	set_user_nice(current, 19);
-
-	while (atomic_read(&do_stuff)) {
-		do_down(N);
-		if (load)
-			udelay(load);
-		do_up(N);
-		sched();
-		if (interval)
-			udelay(interval);
-	}
-
-	if (verbose >= 2)
-		printk("%s: done\n", current->comm);
-	complete_and_exit(&sm_comp[N], 0);
-}
-
-static int reader(void *arg)
-{
-	unsigned int N = (unsigned long) arg;
-
-	daemonize("Read%u", N);
-	set_user_nice(current, 19);
-
-	while (atomic_read(&do_stuff)) {
-		do_down_read(N);
-#ifdef LOAD_TEST
-		if (load)
-			udelay(load);
-#endif
-		do_up_read(N);
-		sched();
-		if (interval)
-			udelay(interval);
-	}
-
-	if (verbose >= 2)
-		printk("%s: done\n", current->comm);
-	complete_and_exit(&rd_comp[N], 0);
-}
-
-static int writer(void *arg)
-{
-	unsigned int N = (unsigned long) arg;
-
-	daemonize("Write%u", N);
-	set_user_nice(current, 19);
-
-	while (atomic_read(&do_stuff)) {
-		do_down_write(N);
-#ifdef LOAD_TEST
-		if (load)
-			udelay(load);
-#endif
-		do_up_write(N);
-		sched();
-		if (interval)
-			udelay(interval);
-	}
-
-	if (verbose >= 2)
-		printk("%s: done\n", current->comm);
-	complete_and_exit(&wr_comp[N], 0);
-}
-
-static int downgrader(void *arg)
-{
-	unsigned int N = (unsigned long) arg;
-
-	daemonize("Down%u", N);
-	set_user_nice(current, 19);
-
-	while (atomic_read(&do_stuff)) {
-		do_down_write(N);
-#ifdef LOAD_TEST
-		if (load)
-			udelay(load);
-#endif
-		do_downgrade_write(N);
-#ifdef LOAD_TEST
-		if (load)
-			udelay(load);
-#endif
-		do_up_read(N);
-		sched();
-		if (interval)
-			udelay(interval);
-	}
-
-	if (verbose >= 2)
-		printk("%s: done\n", current->comm);
-	complete_and_exit(&dg_comp[N], 0);
-}
-
-static void stop_test(unsigned long dummy)
-{
-	atomic_set(&do_stuff, 0);
-}
-
-static unsigned int total(const char *what, unsigned int counts[], int num)
-{
-	unsigned int tot = 0, max = 0, min = UINT_MAX, zeros = 0, cnt;
-	int loop;
-
-	for (loop = 0; loop < num; loop++) {
-		cnt = counts[loop];
-
-		if (cnt == 0) {
-			zeros++;
-			min = 0;
-			continue;
-		}
-
-		tot += cnt;
-		if (tot > max)
-			max = tot;
-		if (tot < min)
-			min = tot;
-	}
-
-	if (verbose && tot > 0) {
-		printk("%s:", what);
-
-		for (loop = 0; loop < num; loop++) {
-			cnt = counts[loop];
-
-			if (cnt == 0)
-				printk(" zzz");
-			else
-				printk(" %d%%", cnt * 100 / tot);
-		}
-
-		printk("\n");
-	}
-
-	return tot;
-}
-
-/*****************************************************************************/
-/*
- *
- */
-static int __init do_tests(void)
-{
-	unsigned long loop;
-	unsigned int mutex_total, sem_total, rd_total, wr_total, dg_total;
-
-	if (nummx < 0 || nummx > MAX_THREADS ||
-	    numsm < 0 || numsm > MAX_THREADS ||
-	    numrd < 0 || numrd > MAX_THREADS ||
-	    numwr < 0 || numwr > MAX_THREADS ||
-	    numdg < 0 || numdg > MAX_THREADS ||
-	    seminit < 1 ||
-	    elapse < 1 ||
-	    load < 0 || load > 999 ||
-	    interval < 0 || interval > 999
-	    ) {
-		printk("Parameter out of range\n");
-		return -ERANGE;
-	}
-
-	if ((nummx | numsm | numrd | numwr | numdg) == 0) {
-		int num = num_online_cpus();
-
-		if (num > MAX_THREADS)
-			num = MAX_THREADS;
-		nummx = numsm = numrd = numwr = numdg = num;
-
-		load = 1;
-		interval = 1;
-		do_sched = 1;
-		printk("No parameters - using defaults.\n");
-	}
-
-	if (verbose)
-		printk("\nStarting synchronisation primitive tests...\n");
-
-	mutex_init(&mutex);
-	sema_init(&sem, seminit);
-	init_rwsem(&rwsem);
-	atomic_set(&do_stuff, 1);
-
-	/* kick off all the children */
-	for (loop = 0; loop < MAX_THREADS; loop++) {
-		if (loop < nummx) {
-			init_completion(&mx_comp[loop]);
-			kernel_thread(mutexer, (void *) loop, 0);
-		}
-
-		if (loop < numsm) {
-			init_completion(&sm_comp[loop]);
-			kernel_thread(semaphorer, (void *) loop, 0);
-		}
-
-		if (loop < numrd) {
-			init_completion(&rd_comp[loop]);
-			kernel_thread(reader, (void *) loop, 0);
-		}
-
-		if (loop < numwr) {
-			init_completion(&wr_comp[loop]);
-			kernel_thread(writer, (void *) loop, 0);
-		}
-
-		if (loop < numdg) {
-			init_completion(&dg_comp[loop]);
-			kernel_thread(downgrader, (void *) loop, 0);
-		}
-	}
-
-	/* set a stop timer */
-	init_timer(&timer);
-	timer.function = stop_test;
-	timer.expires = jiffies + elapse * HZ;
-	add_timer(&timer);
-
-	/* now wait until it's all done */
-	for (loop = 0; loop < nummx; loop++)
-		wait_for_completion(&mx_comp[loop]);
-
-	for (loop = 0; loop < numsm; loop++)
-		wait_for_completion(&sm_comp[loop]);
-
-	for (loop = 0; loop < numrd; loop++)
-		wait_for_completion(&rd_comp[loop]);
-
-	for (loop = 0; loop < numwr; loop++)
-		wait_for_completion(&wr_comp[loop]);
-
-	for (loop = 0; loop < numdg; loop++)
-		wait_for_completion(&dg_comp[loop]);
-
-	atomic_set(&do_stuff, 0);
-	del_timer(&timer);
-
-	if (mutex_is_locked(&mutex))
-		printk(KERN_ERR "Mutex is still locked!\n");
-
-	/* count up */
-	mutex_total	= total("MTX", mutexes_taken, nummx);
-	sem_total	= total("SEM", semaphores_taken, numsm);
-	rd_total	= total("RD ", reads_taken, numrd);
-	wr_total	= total("WR ", writes_taken, numwr);
-	dg_total	= total("DG ", downgrades_taken, numdg);
-
-	/* print the results */
-	if (verbose) {
-		printk("mutexes taken: %u\n", mutex_total);
-		printk("semaphores taken: %u\n", sem_total);
-		printk("reads taken: %u\n", rd_total);
-		printk("writes taken: %u\n", wr_total);
-		printk("downgrades taken: %u\n", dg_total);
-	}
-	else {
-		char buf[30];
-
-		sprintf(buf, "%d/%d", interval, load);
-
-		printk("%3d %3d %3d %3d %3d %c %5s %9u %9u %9u %9u %9u\n",
-		       nummx, numsm, numrd, numwr, numdg,
-		       do_sched ? 's' : '-',
-		       buf,
-		       mutex_total,
-		       sem_total,
-		       rd_total,
-		       wr_total,
-		       dg_total);
-	}
-
-	/* tell insmod to discard the module */
-	if (verbose)
-		printk("Tests complete\n");
-	return -ENOANO;
-
-} /* end do_tests() */
-
-module_init(do_tests);
Index: linux-2.6.24-rc6/lib/Kconfig.debug
===================================================================
--- linux-2.6.24-rc6.orig/lib/Kconfig.debug
+++ linux-2.6.24-rc6/lib/Kconfig.debug
@@ -467,20 +467,6 @@ config BOOT_PRINTK_DELAY
 	  BOOT_PRINTK_DELAY also may cause DETECT_SOFTLOCKUP to detect
 	  what it believes to be lockup conditions.
 
-config DEBUG_SYNCHRO_TEST
-	tristate "Synchronisation primitive testing module"
-	depends on DEBUG_KERNEL
-	default n
-	help
-	  This option provides a kernel module that can thrash the sleepable
-	  synchronisation primitives (mutexes and semaphores).
-
-	  You should say N or M here. Whilst the module can be built in, it's
-	  not recommended as it requires module parameters supplying to get it
-	  to do anything.
-
-	  See Documentation/synchro-test.txt.
-
 config LKDTM
 	tristate "Linux Kernel Dump Test Tool Module"
 	depends on DEBUG_KERNEL
Index: linux-2.6.24-rc6/tests/Kconfig
===================================================================
--- linux-2.6.24-rc6.orig/tests/Kconfig
+++ linux-2.6.24-rc6/tests/Kconfig
@@ -37,5 +37,19 @@ config RT_MUTEX_TESTER
 	help
 	  This option enables a rt-mutex tester.
 
+config DEBUG_SYNCHRO_TEST
+	tristate "Synchronisation primitive testing module"
+	depends on DEBUG_KERNEL
+	default n
+	help
+	  This option provides a kernel module that can thrash the sleepable
+	  synchronisation primitives (mutexes and semaphores).
+
+	  You should say N or M here. Whilst the module can be built in, it's
+	  not recommended as it requires module parameters supplying to get it
+	  to do anything.
+
+	  See Documentation/synchro-test.txt.
+
 endif # KERNEL_TESTS
 
Index: linux-2.6.24-rc6/tests/Makefile
===================================================================
--- linux-2.6.24-rc6.orig/tests/Makefile
+++ linux-2.6.24-rc6/tests/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o
+obj-$(CONFIG_DEBUG_SYNCHRO_TEST) += synchro-test.o
Index: linux-2.6.24-rc6/tests/synchro-test.c
===================================================================
--- /dev/null
+++ linux-2.6.24-rc6/tests/synchro-test.c
@@ -0,0 +1,526 @@
+/* synchro-test.c: run some threads to test the synchronisation primitives
+ *
+ * Copyright (C) 2005, 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ *
+ * The module should be run as something like:
+ *
+ *	insmod synchro-test.ko rd=2 wr=2
+ *	insmod synchro-test.ko mx=1
+ *	insmod synchro-test.ko sm=2 ism=1
+ *	insmod synchro-test.ko sm=2 ism=2
+ *
+ * See Documentation/synchro-test.txt for more information.
+ */
+
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/moduleparam.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+#include <asm/atomic.h>
+#include <linux/personality.h>
+#include <linux/smp_lock.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+
+#define MAX_THREADS 64
+
+/*
+ * Turn on self-validation if we do a one-shot boot-time test:
+ */
+#ifndef MODULE
+# define VALIDATE_OPERATORS
+#endif
+
+static int nummx;
+static int numsm, seminit = 4;
+static int numrd, numwr, numdg;
+static int elapse = 5, load = 2, do_sched, interval = 2;
+static int verbose = 0;
+
+MODULE_AUTHOR("David Howells");
+MODULE_DESCRIPTION("Synchronisation primitive test demo");
+MODULE_LICENSE("GPL");
+
+module_param_named(v, verbose, int, 0);
+MODULE_PARM_DESC(verbose, "Verbosity");
+
+module_param_named(mx, nummx, int, 0);
+MODULE_PARM_DESC(nummx, "Number of mutex threads");
+
+module_param_named(sm, numsm, int, 0);
+MODULE_PARM_DESC(numsm, "Number of semaphore threads");
+
+module_param_named(ism, seminit, int, 0);
+MODULE_PARM_DESC(seminit, "Initial semaphore value");
+
+module_param_named(rd, numrd, int, 0);
+MODULE_PARM_DESC(numrd, "Number of reader threads");
+
+module_param_named(wr, numwr, int, 0);
+MODULE_PARM_DESC(numwr, "Number of writer threads");
+
+module_param_named(dg, numdg, int, 0);
+MODULE_PARM_DESC(numdg, "Number of downgrader threads");
+
+module_param(elapse, int, 0);
+MODULE_PARM_DESC(elapse, "Number of seconds to run for");
+
+module_param(load, int, 0);
+MODULE_PARM_DESC(load, "Length of load in uS");
+
+module_param(interval, int, 0);
+MODULE_PARM_DESC(interval, "Length of interval in uS before re-getting lock");
+
+module_param(do_sched, int, 0);
+MODULE_PARM_DESC(do_sched, "True if each thread should schedule regularly");
+
+/* the semaphores under test */
+static struct mutex ____cacheline_aligned mutex;
+static struct semaphore ____cacheline_aligned sem;
+static struct rw_semaphore ____cacheline_aligned rwsem;
+
+static atomic_t ____cacheline_aligned do_stuff		= ATOMIC_INIT(0);
+
+#ifdef VALIDATE_OPERATORS
+static atomic_t ____cacheline_aligned mutexes		= ATOMIC_INIT(0);
+static atomic_t ____cacheline_aligned semaphores	= ATOMIC_INIT(0);
+static atomic_t ____cacheline_aligned readers		= ATOMIC_INIT(0);
+static atomic_t ____cacheline_aligned writers		= ATOMIC_INIT(0);
+#endif
+
+static unsigned int ____cacheline_aligned mutexes_taken		[MAX_THREADS];
+static unsigned int ____cacheline_aligned semaphores_taken	[MAX_THREADS];
+static unsigned int ____cacheline_aligned reads_taken		[MAX_THREADS];
+static unsigned int ____cacheline_aligned writes_taken		[MAX_THREADS];
+static unsigned int ____cacheline_aligned downgrades_taken	[MAX_THREADS];
+
+static struct completion ____cacheline_aligned mx_comp[MAX_THREADS];
+static struct completion ____cacheline_aligned sm_comp[MAX_THREADS];
+static struct completion ____cacheline_aligned rd_comp[MAX_THREADS];
+static struct completion ____cacheline_aligned wr_comp[MAX_THREADS];
+static struct completion ____cacheline_aligned dg_comp[MAX_THREADS];
+
+static struct timer_list ____cacheline_aligned timer;
+
+#define ACCOUNT(var, N) var##_taken[N]++;
+
+#ifdef VALIDATE_OPERATORS
+#define TRACK(var, dir) atomic_##dir(&(var))
+
+#define CHECK(var, cond, val)						\
+do {									\
+	int x = atomic_read(&(var));					\
+	if (unlikely(!(x cond (val))))					\
+		printk("check [%s %s %d, == %d] failed in %s\n",	\
+		       #var, #cond, (val), x, __func__);		\
+} while (0)
+
+#else
+#define TRACK(var, dir)		do {} while(0)
+#define CHECK(var, cond, val)	do {} while(0)
+#endif
+
+static inline void do_mutex_lock(unsigned int N)
+{
+	mutex_lock(&mutex);
+
+	ACCOUNT(mutexes, N);
+	TRACK(mutexes, inc);
+	CHECK(mutexes, ==, 1);
+}
+
+static inline void do_mutex_unlock(unsigned int N)
+{
+	CHECK(mutexes, ==, 1);
+	TRACK(mutexes, dec);
+
+	mutex_unlock(&mutex);
+}
+
+static inline void do_down(unsigned int N)
+{
+	CHECK(mutexes, <, seminit);
+
+	down(&sem);
+
+	ACCOUNT(semaphores, N);
+	TRACK(semaphores, inc);
+}
+
+static inline void do_up(unsigned int N)
+{
+	CHECK(semaphores, >, 0);
+	TRACK(semaphores, dec);
+
+	up(&sem);
+}
+
+static inline void do_down_read(unsigned int N)
+{
+	down_read(&rwsem);
+
+	ACCOUNT(reads, N);
+	TRACK(readers, inc);
+	CHECK(readers, >, 0);
+	CHECK(writers, ==, 0);
+}
+
+static inline void do_up_read(unsigned int N)
+{
+	CHECK(readers, >, 0);
+	CHECK(writers, ==, 0);
+	TRACK(readers, dec);
+
+	up_read(&rwsem);
+}
+
+static inline void do_down_write(unsigned int N)
+{
+	down_write(&rwsem);
+
+	ACCOUNT(writes, N);
+	TRACK(writers, inc);
+	CHECK(writers, ==, 1);
+	CHECK(readers, ==, 0);
+}
+
+static inline void do_up_write(unsigned int N)
+{
+	CHECK(writers, ==, 1);
+	CHECK(readers, ==, 0);
+	TRACK(writers, dec);
+
+	up_write(&rwsem);
+}
+
+static inline void do_downgrade_write(unsigned int N)
+{
+	CHECK(writers, ==, 1);
+	CHECK(readers, ==, 0);
+	TRACK(writers, dec);
+	TRACK(readers, inc);
+
+	downgrade_write(&rwsem);
+
+	ACCOUNT(downgrades, N);
+}
+
+static inline void sched(void)
+{
+	if (do_sched)
+		schedule();
+}
+
+static int mutexer(void *arg)
+{
+	unsigned int N = (unsigned long) arg;
+
+	daemonize("Mutex%u", N);
+	set_user_nice(current, 19);
+
+	while (atomic_read(&do_stuff)) {
+		do_mutex_lock(N);
+		if (load)
+			udelay(load);
+		do_mutex_unlock(N);
+		sched();
+		if (interval)
+			udelay(interval);
+	}
+
+	if (verbose >= 2)
+		printk("%s: done\n", current->comm);
+	complete_and_exit(&mx_comp[N], 0);
+}
+
+static int semaphorer(void *arg)
+{
+	unsigned int N = (unsigned long) arg;
+
+	daemonize("Sem%u", N);
+	set_user_nice(current, 19);
+
+	while (atomic_read(&do_stuff)) {
+		do_down(N);
+		if (load)
+			udelay(load);
+		do_up(N);
+		sched();
+		if (interval)
+			udelay(interval);
+	}
+
+	if (verbose >= 2)
+		printk("%s: done\n", current->comm);
+	complete_and_exit(&sm_comp[N], 0);
+}
+
+static int reader(void *arg)
+{
+	unsigned int N = (unsigned long) arg;
+
+	daemonize("Read%u", N);
+	set_user_nice(current, 19);
+
+	while (atomic_read(&do_stuff)) {
+		do_down_read(N);
+#ifdef LOAD_TEST
+		if (load)
+			udelay(load);
+#endif
+		do_up_read(N);
+		sched();
+		if (interval)
+			udelay(interval);
+	}
+
+	if (verbose >= 2)
+		printk("%s: done\n", current->comm);
+	complete_and_exit(&rd_comp[N], 0);
+}
+
+static int writer(void *arg)
+{
+	unsigned int N = (unsigned long) arg;
+
+	daemonize("Write%u", N);
+	set_user_nice(current, 19);
+
+	while (atomic_read(&do_stuff)) {
+		do_down_write(N);
+#ifdef LOAD_TEST
+		if (load)
+			udelay(load);
+#endif
+		do_up_write(N);
+		sched();
+		if (interval)
+			udelay(interval);
+	}
+
+	if (verbose >= 2)
+		printk("%s: done\n", current->comm);
+	complete_and_exit(&wr_comp[N], 0);
+}
+
+static int downgrader(void *arg)
+{
+	unsigned int N = (unsigned long) arg;
+
+	daemonize("Down%u", N);
+	set_user_nice(current, 19);
+
+	while (atomic_read(&do_stuff)) {
+		do_down_write(N);
+#ifdef LOAD_TEST
+		if (load)
+			udelay(load);
+#endif
+		do_downgrade_write(N);
+#ifdef LOAD_TEST
+		if (load)
+			udelay(load);
+#endif
+		do_up_read(N);
+		sched();
+		if (interval)
+			udelay(interval);
+	}
+
+	if (verbose >= 2)
+		printk("%s: done\n", current->comm);
+	complete_and_exit(&dg_comp[N], 0);
+}
+
+static void stop_test(unsigned long dummy)
+{
+	atomic_set(&do_stuff, 0);
+}
+
+static unsigned int total(const char *what, unsigned int counts[], int num)
+{
+	unsigned int tot = 0, max = 0, min = UINT_MAX, zeros = 0, cnt;
+	int loop;
+
+	for (loop = 0; loop < num; loop++) {
+		cnt = counts[loop];
+
+		if (cnt == 0) {
+			zeros++;
+			min = 0;
+			continue;
+		}
+
+		tot += cnt;
+		if (tot > max)
+			max = tot;
+		if (tot < min)
+			min = tot;
+	}
+
+	if (verbose && tot > 0) {
+		printk("%s:", what);
+
+		for (loop = 0; loop < num; loop++) {
+			cnt = counts[loop];
+
+			if (cnt == 0)
+				printk(" zzz");
+			else
+				printk(" %d%%", cnt * 100 / tot);
+		}
+
+		printk("\n");
+	}
+
+	return tot;
+}
+
+/*****************************************************************************/
+/*
+ *
+ */
+static int __init do_tests(void)
+{
+	unsigned long loop;
+	unsigned int mutex_total, sem_total, rd_total, wr_total, dg_total;
+
+	if (nummx < 0 || nummx > MAX_THREADS ||
+	    numsm < 0 || numsm > MAX_THREADS ||
+	    numrd < 0 || numrd > MAX_THREADS ||
+	    numwr < 0 || numwr > MAX_THREADS ||
+	    numdg < 0 || numdg > MAX_THREADS ||
+	    seminit < 1 ||
+	    elapse < 1 ||
+	    load < 0 || load > 999 ||
+	    interval < 0 || interval > 999
+	    ) {
+		printk("Parameter out of range\n");
+		return -ERANGE;
+	}
+
+	if ((nummx | numsm | numrd | numwr | numdg) == 0) {
+		int num = num_online_cpus();
+
+		if (num > MAX_THREADS)
+			num = MAX_THREADS;
+		nummx = numsm = numrd = numwr = numdg = num;
+
+		load = 1;
+		interval = 1;
+		do_sched = 1;
+		printk("No parameters - using defaults.\n");
+	}
+
+	if (verbose)
+		printk("\nStarting synchronisation primitive tests...\n");
+
+	mutex_init(&mutex);
+	sema_init(&sem, seminit);
+	init_rwsem(&rwsem);
+	atomic_set(&do_stuff, 1);
+
+	/* kick off all the children */
+	for (loop = 0; loop < MAX_THREADS; loop++) {
+		if (loop < nummx) {
+			init_completion(&mx_comp[loop]);
+			kernel_thread(mutexer, (void *) loop, 0);
+		}
+
+		if (loop < numsm) {
+			init_completion(&sm_comp[loop]);
+			kernel_thread(semaphorer, (void *) loop, 0);
+		}
+
+		if (loop < numrd) {
+			init_completion(&rd_comp[loop]);
+			kernel_thread(reader, (void *) loop, 0);
+		}
+
+		if (loop < numwr) {
+			init_completion(&wr_comp[loop]);
+			kernel_thread(writer, (void *) loop, 0);
+		}
+
+		if (loop < numdg) {
+			init_completion(&dg_comp[loop]);
+			kernel_thread(downgrader, (void *) loop, 0);
+		}
+	}
+
+	/* set a stop timer */
+	init_timer(&timer);
+	timer.function = stop_test;
+	timer.expires = jiffies + elapse * HZ;
+	add_timer(&timer);
+
+	/* now wait until it's all done */
+	for (loop = 0; loop < nummx; loop++)
+		wait_for_completion(&mx_comp[loop]);
+
+	for (loop = 0; loop < numsm; loop++)
+		wait_for_completion(&sm_comp[loop]);
+
+	for (loop = 0; loop < numrd; loop++)
+		wait_for_completion(&rd_comp[loop]);
+
+	for (loop = 0; loop < numwr; loop++)
+		wait_for_completion(&wr_comp[loop]);
+
+	for (loop = 0; loop < numdg; loop++)
+		wait_for_completion(&dg_comp[loop]);
+
+	atomic_set(&do_stuff, 0);
+	del_timer(&timer);
+
+	if (mutex_is_locked(&mutex))
+		printk(KERN_ERR "Mutex is still locked!\n");
+
+	/* count up */
+	mutex_total	= total("MTX", mutexes_taken, nummx);
+	sem_total	= total("SEM", semaphores_taken, numsm);
+	rd_total	= total("RD ", reads_taken, numrd);
+	wr_total	= total("WR ", writes_taken, numwr);
+	dg_total	= total("DG ", downgrades_taken, numdg);
+
+	/* print the results */
+	if (verbose) {
+		printk("mutexes taken: %u\n", mutex_total);
+		printk("semaphores taken: %u\n", sem_total);
+		printk("reads taken: %u\n", rd_total);
+		printk("writes taken: %u\n", wr_total);
+		printk("downgrades taken: %u\n", dg_total);
+	}
+	else {
+		char buf[30];
+
+		sprintf(buf, "%d/%d", interval, load);
+
+		printk("%3d %3d %3d %3d %3d %c %5s %9u %9u %9u %9u %9u\n",
+		       nummx, numsm, numrd, numwr, numdg,
+		       do_sched ? 's' : '-',
+		       buf,
+		       mutex_total,
+		       sem_total,
+		       rd_total,
+		       wr_total,
+		       dg_total);
+	}
+
+	/* tell insmod to discard the module */
+	if (verbose)
+		printk("Tests complete\n");
+	return -ENOANO;
+
+} /* end do_tests() */
+
+module_init(do_tests);

  parent reply	other threads:[~2008-01-10 11:59 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-10 11:54 [PATCH 0/7] Create and populate toplevel tests/ directory Ananth N Mavinakayanahalli
2008-01-10 11:55 ` [PATCH 1/7] Add " Ananth N Mavinakayanahalli
2008-01-10 15:16   ` Sam Ravnborg
2008-01-10 15:54     ` Ananth N Mavinakayanahalli
2008-01-10 11:56 ` [PATCH 2/7] Move locking-selftest to tests/ Ananth N Mavinakayanahalli
2008-01-10 11:57 ` [PATCH 3/7] Move rcutorture " Ananth N Mavinakayanahalli
2008-01-10 23:14   ` Josh Triplett
2008-01-14  7:01     ` Paul E. McKenney
2008-01-10 11:58 ` [PATCH 4/7] Move rtmutex tests under tests/ Ananth N Mavinakayanahalli
2008-01-10 11:59 ` Ananth N Mavinakayanahalli [this message]
2008-01-10 12:00 ` [PATCH 6/7] Move lkdtm " Ananth N Mavinakayanahalli
2008-01-10 12:01 ` [PATCH 7/7] Add kprobes smoke tests " Ananth N Mavinakayanahalli
2008-01-10 15:17 ` [PATCH 0/7] Create and populate toplevel tests/ directory Sam Ravnborg
2008-01-14 22:55 ` Matt Mackall

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080110115943.GF26577@in.ibm.com \
    --to=ananth@in.ibm.com \
    --cc=ak@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=dhowells@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=sam@ravnborg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.