From: Ananth N Mavinakayanahalli <[EMAIL PROTECTED]>

Move the synchro-test infrastructure to tests/

Signed-off-by: Ananth N Mavinakayanahalli <[EMAIL PROTECTED]>
---
 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 ([EMAIL PROTECTED])
- *
- * 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 ([EMAIL PROTECTED])
+ *
+ * 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);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to