All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC tip/core/rcu 0/8] Waketorture, not for inclusion
@ 2016-06-15 22:27 Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 1/8] waketorture: Add a wakeup-torture module Paul E. McKenney
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Paul E. McKenney @ 2016-06-15 22:27 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani

Hello!

And for your amusement, this series provides a waketorture module.  It is
intended to increase the probability of a heisenbug or three I have been
chasing for longer than I care to admit.  Should it someday actually
significantly increase that probability, I might consider submitting it
for acceptance.  In the meantime, for your amusement:

1.	Add a wakeup-torture module.

2.	Update scripting to accommodate waketorture.

3.	Don't kick kthreads unless grace period or request.

4.	Add utilization measurement.

5.	Add hrtimer support for fine-grained event scheduling.

6.	Make waketorture always hotplug the same CPU.

7.	Make waketorture kill test if no hotpluggable CPUs.

8.	Affinity waiter tasks away from hotpluggable CPU.

							Thanx, Paul

------------------------------------------------------------------------

 kernel/rcu/Makefile                                              |    3 
 kernel/rcu/tree.c                                                |    3 
 kernel/rcu/waketorture.c                                         |  567 +++++++++-
 lib/Kconfig.debug                                                |   18 
 tools/testing/selftests/rcutorture/bin/kvm-recheck-wake.sh       |   39 
 tools/testing/selftests/rcutorture/bin/kvm-recheck.sh            |    2 
 tools/testing/selftests/rcutorture/bin/kvm.sh                    |    2 
 tools/testing/selftests/rcutorture/configs/wake/CFLIST           |    1 
 tools/testing/selftests/rcutorture/configs/wake/CFcommon         |    2 
 tools/testing/selftests/rcutorture/configs/wake/SH               |   19 
 tools/testing/selftests/rcutorture/configs/wake/SH.boot          |    1 
 tools/testing/selftests/rcutorture/configs/wake/STI              |   19 
 tools/testing/selftests/rcutorture/configs/wake/STI.boot         |    1 
 tools/testing/selftests/rcutorture/configs/wake/ver_functions.sh |   43 
 14 files changed, 701 insertions(+), 19 deletions(-)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH tip/core/rcu 1/8] waketorture: Add a wakeup-torture module
  2016-06-15 22:27 [PATCH RFC tip/core/rcu 0/8] Waketorture, not for inclusion Paul E. McKenney
@ 2016-06-15 22:28 ` Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 2/8] waketorture: Update scripting to accommodate waketorture Paul E. McKenney
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2016-06-15 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Paul E. McKenney

This commit adds a wakeup-torture module to assist tracking down an
elusive lost-wakeup problem.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 kernel/rcu/Makefile      |   3 +-
 kernel/rcu/waketorture.c | 371 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/Kconfig.debug        |  17 +++
 3 files changed, 390 insertions(+), 1 deletion(-)
 create mode 100644 kernel/rcu/waketorture.c

diff --git a/kernel/rcu/Makefile b/kernel/rcu/Makefile
index 18dfc485225c..42cd319920b1 100644
--- a/kernel/rcu/Makefile
+++ b/kernel/rcu/Makefile
@@ -4,9 +4,10 @@ KCOV_INSTRUMENT := n
 
 obj-y += update.o sync.o
 obj-$(CONFIG_SRCU) += srcu.o
-obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_RCU_PERF_TEST) += rcuperf.o
+obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_TREE_RCU) += tree.o
 obj-$(CONFIG_PREEMPT_RCU) += tree.o
 obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o
 obj-$(CONFIG_TINY_RCU) += tiny.o
+obj-$(CONFIG_WAKE_TORTURE_TEST) += waketorture.o
diff --git a/kernel/rcu/waketorture.c b/kernel/rcu/waketorture.c
new file mode 100644
index 000000000000..75bc547206cc
--- /dev/null
+++ b/kernel/rcu/waketorture.c
@@ -0,0 +1,371 @@
+/*
+ * Specific stress-testing of wakeup logic in the presence of hotplug
+ * operations.
+ *
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2016
+ *
+ * Author: Paul E. McKenney <paulmck@us.ibm.com>
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/rcupdate.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/atomic.h>
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/moduleparam.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/freezer.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/stat.h>
+#include <linux/srcu.h>
+#include <linux/slab.h>
+#include <linux/trace_clock.h>
+#include <asm/byteorder.h>
+#include <linux/torture.h>
+#include <linux/vmalloc.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>");
+
+
+torture_param(int, nwaiters, -1, "Number of timed-wait threads");
+torture_param(int, onoff_holdoff, 0, "Time after boot before CPU hotplugs (s)");
+torture_param(int, onoff_interval, 0,
+	     "Time between CPU hotplugs (jiffies), 0=disable");
+torture_param(int, shutdown_secs, 0, "Shutdown time (s), <= zero to disable.");
+torture_param(int, stat_interval, 60,
+	     "Number of seconds between stats printk()s");
+torture_param(bool, verbose, true,
+	     "Enable verbose debugging printk()s");
+torture_param(int, wait_duration, 3,
+	     "Number of jiffies to wait each iteration");
+torture_param(int, wait_grace, 20,
+	     "Number of jiffies before complaining about long wait");
+
+static char *torture_type = "sti";
+module_param(torture_type, charp, 0444);
+MODULE_PARM_DESC(torture_type, "Type of wait to torture (sti, stui, ...)");
+
+static int nrealwaiters;
+static struct task_struct **waiter_tasks;
+static struct task_struct *stats_task;
+
+/* Yes, these cache-thrash, and it is inherent to the concurrency design. */
+static bool *waiter_done;		/* Waiter is done, don't wake. */
+static unsigned long *waiter_iter;	/* Number of wait iterations. */
+static bool *waiter_cts;		/* Waiter already checked. */
+static unsigned long *waiter_kicks;	/* Number of waiter starvations. */
+static unsigned long *waiter_ts;	/* Jiffies last run. */
+DEFINE_MUTEX(waiter_mutex);
+
+static int torture_runnable = IS_ENABLED(MODULE);
+module_param(torture_runnable, int, 0444);
+MODULE_PARM_DESC(torture_runnable, "Start waketorture at boot");
+
+/*
+ * Operations vector for selecting different types of tests.
+ */
+
+struct wake_torture_ops {
+	signed long (*wait)(signed long timeout);
+	const char *name;
+};
+
+static struct wake_torture_ops *cur_ops;
+
+/*
+ * Definitions for schedule_timeout_interruptible() torture testing.
+ */
+
+static struct wake_torture_ops sti_ops = {
+	.wait		= schedule_timeout_interruptible,
+	.name		= "sti"
+};
+
+/*
+ * Definitions for schedule_timeout_uninterruptible() torture testing.
+ */
+
+static struct wake_torture_ops stui_ops = {
+	.wait		= schedule_timeout_uninterruptible,
+	.name		= "stui"
+};
+
+/*
+ * Has the specified waiter thread run recently?
+ */
+static bool kthread_ran_recently(int tnum)
+{
+	smp_mb(); /* Ensure waiter_cts[] read before waiter_ts[].  [A] */
+	return time_before(READ_ONCE(waiter_ts[tnum]), jiffies + wait_grace);
+}
+
+/*
+ * Wakeup torture fake writer kthread.  Repeatedly calls sync, with a random
+ * delay between calls.
+ */
+static int wake_torture_waiter(void *arg)
+{
+	int i;
+	long me = (long)arg;
+
+	VERBOSE_TOROUT_STRING("wake_torture_waiter task started");
+	set_user_nice(current, MAX_NICE);
+
+	do {
+		waiter_ts[me] = jiffies;
+		smp_mb(); /* Ensure waiter_ts[] written before waiter_cts[]. */
+			  /* Pairs with [A]. */
+		waiter_cts[me] = false;
+		cur_ops->wait(wait_duration);
+		waiter_iter[me]++;
+		for (i = 0; i < nrealwaiters; i++) {
+			if (waiter_done[i] ||
+			    waiter_cts[i] ||
+			    kthread_ran_recently(i))
+				continue;
+			if (!mutex_trylock(&waiter_mutex)) {
+				break; /* Keep lock contention to dull roar. */
+			} else if (waiter_done[i] ||
+				   waiter_cts[i] ||
+				   kthread_ran_recently(i)) {
+				mutex_unlock(&waiter_mutex);
+			} else {
+				waiter_cts[i] = true;
+				waiter_kicks[i]++;
+				pr_alert("%s%s wake_torture_waiter(): P%d failing to awaken!\n", torture_type, TORTURE_FLAG, waiter_tasks[i]->pid);
+				rcu_ftrace_dump(DUMP_ALL);
+				wake_up_process(waiter_tasks[i]);
+				mutex_unlock(&waiter_mutex);
+			}
+		}
+		torture_shutdown_absorb("wake_torture_waiter");
+	} while (!torture_must_stop());
+	mutex_lock(&waiter_mutex);
+	waiter_done[me] = true;
+	mutex_unlock(&waiter_mutex);
+	torture_kthread_stopping("wake_torture_waiter");
+	return 0;
+}
+
+/*
+ * Print torture statistics.  Caller must ensure that there is only one
+ * call to this function at a given time!!!  This is normally accomplished
+ * by relying on the module system to only have one copy of the module
+ * loaded, and then by giving the wake_torture_stats kthread full control
+ * (or the init/cleanup functions when wake_torture_stats thread is not
+ * running).
+ *
+ * Note that some care is required because this can be called once during
+ * cleanup processing after a failed startup attempt.
+ */
+static void
+wake_torture_stats_print(void)
+{
+	int i;
+	bool tardy = false;
+
+	if (!waiter_done || !waiter_iter || !waiter_cts ||
+	    !waiter_kicks || !waiter_ts) {
+		TOROUT_STRING("Partial initialization, no stats print.\n");
+		return;
+	}
+	for (i = 0; i < nrealwaiters; i++)
+		if (waiter_kicks[i]) {
+			if (!tardy)
+				pr_alert("%s" TORTURE_FLAG " Tardy kthreads:",
+					 torture_type);
+			tardy = true;
+			pr_cont("  P%d%c: %lud/%lu",
+				waiter_tasks && waiter_tasks[i]
+					? waiter_tasks[i]->pid
+					: -1,
+				"!."[kthread_ran_recently(i)],
+				waiter_kicks[i], waiter_iter[i]);
+		}
+	if (tardy)
+		pr_cont("\n");
+	else
+		TOROUT_STRING(" No tardy kthreads");
+}
+
+/*
+ * Periodically prints torture statistics, if periodic statistics printing
+ * was specified via the stat_interval module parameter.
+ */
+static int
+wake_torture_stats(void *arg)
+{
+	VERBOSE_TOROUT_STRING("wake_torture_stats task started");
+	do {
+		schedule_timeout_interruptible(stat_interval * HZ);
+		wake_torture_stats_print();
+		torture_shutdown_absorb("wake_torture_stats");
+	} while (!torture_must_stop());
+	torture_kthread_stopping("wake_torture_stats");
+	return 0;
+}
+
+static inline void
+wake_torture_print_module_parms(struct wake_torture_ops *cur_ops,
+				const char *tag)
+{
+	pr_alert("%s" TORTURE_FLAG
+		 "--- %s: nwaiters=%d onoff_holdoff=%d onoff_interval=%d shutdown_secs=%d stat_interval=%d verbose=%d wait_duration=%d wait_grace=%d\n",
+		 torture_type, tag,
+		 nrealwaiters, onoff_holdoff, onoff_interval,
+		 shutdown_secs, stat_interval, verbose,
+		 wait_duration, wait_grace);
+}
+
+static void
+wake_torture_cleanup(void)
+{
+	int i;
+	bool success;
+
+	(void)torture_cleanup_begin();
+
+	if (waiter_tasks) {
+		for (i = 0; i < nrealwaiters; i++)
+			torture_stop_kthread(wake_torture_waiter,
+					     waiter_tasks[i]);
+		kfree(waiter_tasks);
+	}
+
+	torture_stop_kthread(wake_torture_stats, stats_task);
+
+	wake_torture_stats_print();  /* -After- the stats thread is stopped! */
+
+	success = !!waiter_kicks;
+	for (i = 0; i < nrealwaiters; i++)
+		if (!success || waiter_kicks[i]) {
+			success = false;
+			break;
+		}
+
+	kfree(waiter_done);
+	kfree(waiter_iter);
+	kfree(waiter_cts);
+	kfree(waiter_kicks);
+	kfree(waiter_ts);
+
+	wake_torture_print_module_parms(cur_ops,
+					success ? "End of test: SUCCESS"
+						: "End of test: FAILURE");
+	torture_cleanup_end();
+}
+
+static int __init
+wake_torture_init(void)
+{
+	int i;
+	int firsterr = 0;
+	static struct wake_torture_ops *torture_ops[] = { &sti_ops, &stui_ops };
+
+	if (!torture_init_begin(torture_type, verbose, &torture_runnable))
+		return -EBUSY;
+
+	/* Process args and tell the world that the torturer is on the job. */
+	for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
+		cur_ops = torture_ops[i];
+		if (strcmp(torture_type, cur_ops->name) == 0)
+			break;
+	}
+	if (i == ARRAY_SIZE(torture_ops)) {
+		pr_alert("wake-torture: invalid torture type: \"%s\"\n",
+			 torture_type);
+		pr_alert("wake-torture types:");
+		for (i = 0; i < ARRAY_SIZE(torture_ops); i++)
+			pr_alert(" %s", torture_ops[i]->name);
+		pr_alert("\n");
+		firsterr = -EINVAL;
+		goto unwind;
+	}
+
+	if (nwaiters >= 0) {
+		nrealwaiters = nwaiters;
+	} else {
+		nrealwaiters = num_online_cpus() - 2 - nwaiters;
+		if (nrealwaiters <= 0)
+			nrealwaiters = 1;
+	}
+	wake_torture_print_module_parms(cur_ops, "Start of test");
+
+	/* Initialize the statistics so that each run gets its own numbers. */
+
+	waiter_done = kcalloc(nrealwaiters, sizeof(*waiter_done), GFP_KERNEL);
+	waiter_iter = kcalloc(nrealwaiters, sizeof(*waiter_iter), GFP_KERNEL);
+	waiter_cts = kcalloc(nrealwaiters, sizeof(*waiter_cts), GFP_KERNEL);
+	waiter_kicks = kcalloc(nrealwaiters, sizeof(*waiter_kicks), GFP_KERNEL);
+	waiter_ts = kcalloc(nrealwaiters, sizeof(*waiter_ts), GFP_KERNEL);
+	if (!waiter_done || !waiter_iter || !waiter_cts || !waiter_kicks ||
+	    !waiter_ts) {
+		VERBOSE_TOROUT_ERRSTRING("out of memory");
+		firsterr = -ENOMEM;
+		goto unwind;
+	}
+
+	/* Start up the kthreads. */
+
+	waiter_tasks = kcalloc(nrealwaiters, sizeof(waiter_tasks[0]),
+			       GFP_KERNEL);
+	if (!waiter_tasks) {
+		VERBOSE_TOROUT_ERRSTRING("out of memory");
+		firsterr = -ENOMEM;
+		goto unwind;
+	}
+	for (i = 0; i < nrealwaiters; i++) {
+		firsterr = torture_create_kthread(wake_torture_waiter,
+						  NULL, waiter_tasks[i]);
+		if (firsterr)
+			goto unwind;
+	}
+	if (stat_interval > 0) {
+		firsterr = torture_create_kthread(wake_torture_stats, NULL,
+						  stats_task);
+		if (firsterr)
+			goto unwind;
+	}
+	firsterr = torture_shutdown_init(shutdown_secs, wake_torture_cleanup);
+	if (firsterr)
+		goto unwind;
+	firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval);
+	if (firsterr)
+		goto unwind;
+	torture_init_end();
+	return 0;
+
+unwind:
+	torture_init_end();
+	wake_torture_cleanup();
+	return firsterr;
+}
+
+module_init(wake_torture_init);
+module_exit(wake_torture_cleanup);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 805b7048a1bd..f0dcb4c0fe96 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1399,6 +1399,23 @@ config RCU_TORTURE_TEST_SLOW_CLEANUP_DELAY
 	  This option specifies the number of jiffies to wait between
 	  each rcu_node structure cleanup operation.
 
+config WAKE_TORTURE_TEST
+	tristate "Torture test for wakeups and CPU hotplug"
+	depends on DEBUG_KERNEL
+	depends on 64BIT
+	select TORTURE_TEST
+	default n
+	help
+	  This option provides a kernel module that runs torture tests
+	  on wakeups from timed waits in the presence of CPU hotplug.
+	  The kernel module may be built after the fact on the running
+	  kernel to be tested, if desired.
+
+	  Say Y here if you want wakeup torture tests to be built into
+	  the kernel.
+	  Say M if you want the wakeup torture tests to build as a module.
+	  Say N if you are unsure.
+
 config RCU_CPU_STALL_TIMEOUT
 	int "RCU CPU stall timeout in seconds"
 	depends on RCU_STALL_COMMON
-- 
2.5.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH tip/core/rcu 2/8] waketorture: Update scripting to accommodate waketorture
  2016-06-15 22:27 [PATCH RFC tip/core/rcu 0/8] Waketorture, not for inclusion Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 1/8] waketorture: Add a wakeup-torture module Paul E. McKenney
@ 2016-06-15 22:28 ` Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 3/8] waketorture: Don't kick unless grace period or request Paul E. McKenney
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2016-06-15 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Paul E. McKenney

This commit adds the scripting changes to add support for the shiny
new waketorture kernel module.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 .../selftests/rcutorture/bin/kvm-recheck-wake.sh   | 39 ++++++++++++++++++++
 .../selftests/rcutorture/bin/kvm-recheck.sh        |  2 +-
 tools/testing/selftests/rcutorture/bin/kvm.sh      |  2 +-
 .../selftests/rcutorture/configs/wake/CFLIST       |  1 +
 .../selftests/rcutorture/configs/wake/CFcommon     |  2 +
 .../testing/selftests/rcutorture/configs/wake/STI  | 19 ++++++++++
 .../selftests/rcutorture/configs/wake/STI.boot     |  1 +
 .../rcutorture/configs/wake/ver_functions.sh       | 43 ++++++++++++++++++++++
 8 files changed, 107 insertions(+), 2 deletions(-)
 create mode 100755 tools/testing/selftests/rcutorture/bin/kvm-recheck-wake.sh
 create mode 100644 tools/testing/selftests/rcutorture/configs/wake/CFLIST
 create mode 100644 tools/testing/selftests/rcutorture/configs/wake/CFcommon
 create mode 100644 tools/testing/selftests/rcutorture/configs/wake/STI
 create mode 100644 tools/testing/selftests/rcutorture/configs/wake/STI.boot
 create mode 100644 tools/testing/selftests/rcutorture/configs/wake/ver_functions.sh

diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-wake.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-wake.sh
new file mode 100755
index 000000000000..fc9ee1920acb
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-wake.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+#
+# Analyze a given results directory for waketorture diagnostics.
+#
+# Usage: kvm-recheck-wake resdir
+#
+# 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.
+#
+# Copyright (C) IBM Corporation, 2016
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+i="$1"
+if test -d $i
+then
+	:
+else
+	echo Unreadable results directory: $i
+	exit 1
+fi
+PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH
+. tools/testing/selftests/rcutorture/bin/functions.sh
+
+configfile=`echo $i | sed -e 's/^.*\///'`
+
+sed -e 's/^\[[^]]*]//' < $i/console.log | grep -e -torture |
+	grep "Tardy kthreads" | tail -1
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
index f659346d3358..060c1eec73f4 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
@@ -48,7 +48,7 @@ do
 				cat $i/Make.oldconfig.err
 			fi
 			parse-build.sh $i/Make.out $configfile
-			if test "$TORTURE_SUITE" != rcuperf
+			if test "$TORTURE_SUITE" != rcuperf -a "$TORTURE_SUITE" != wake
 			then
 				parse-torture.sh $i/console.log $configfile
 			fi
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 0aed965f0062..0109ddf7b666 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -163,7 +163,7 @@ do
 		shift
 		;;
 	--torture)
-		checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\|rcuperf\)$' '^--'
+		checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\|rcuperf\|wake\)$' '^--'
 		TORTURE_SUITE=$2
 		shift
 		;;
diff --git a/tools/testing/selftests/rcutorture/configs/wake/CFLIST b/tools/testing/selftests/rcutorture/configs/wake/CFLIST
new file mode 100644
index 000000000000..850c262a6226
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/wake/CFLIST
@@ -0,0 +1 @@
+STI
diff --git a/tools/testing/selftests/rcutorture/configs/wake/CFcommon b/tools/testing/selftests/rcutorture/configs/wake/CFcommon
new file mode 100644
index 000000000000..ffba1816cb6c
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/wake/CFcommon
@@ -0,0 +1,2 @@
+CONFIG_WAKE_TORTURE_TEST=y
+CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/wake/STI b/tools/testing/selftests/rcutorture/configs/wake/STI
new file mode 100644
index 000000000000..7a17c503b382
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/wake/STI
@@ -0,0 +1,19 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_PREEMPT_RCU=y
+CONFIG_HZ_PERIODIC=y
+CONFIG_NO_HZ_IDLE=n
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_TRACE=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_RCU_FANOUT=2
+CONFIG_RCU_FANOUT_LEAF=2
+CONFIG_RCU_NOCB_CPU=n
+CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_KTHREAD_PRIO=2
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
+CONFIG_RCU_EXPERT=y
diff --git a/tools/testing/selftests/rcutorture/configs/wake/STI.boot b/tools/testing/selftests/rcutorture/configs/wake/STI.boot
new file mode 100644
index 000000000000..67ac1ad46672
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/wake/STI.boot
@@ -0,0 +1 @@
+rcupdate.rcu_expedited waketorture.torture_type=sti
diff --git a/tools/testing/selftests/rcutorture/configs/wake/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/wake/ver_functions.sh
new file mode 100644
index 000000000000..7331a1884d99
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/wake/ver_functions.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+#
+# Kernel-version-dependent shell functions for the rest of the scripts.
+#
+# 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.
+#
+# Copyright (C) IBM Corporation, 2016
+#
+# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+# waketorture_param_onoff bootparam-string config-file
+#
+# Adds onoff waketorture module parameters to kernels having it.
+waketorture_param_onoff () {
+	if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
+	then
+		echo CPU-hotplug kernel, adding waketorture onoff. 1>&2
+		echo waketorture.onoff_interval=50 waketorture.onoff_holdoff=30
+	fi
+}
+
+# per_version_boot_params bootparam-string config-file seconds
+#
+# Adds per-version torture-module parameters to kernels supporting them.
+per_version_boot_params () {
+	echo $1 `waketorture_param_onoff "$1" "$2"` \
+		waketorture.stat_interval=15 \
+		waketorture.shutdown_secs=$3 \
+		waketorture.torture_runnable=1 \
+		waketorture.verbose=1
+}
-- 
2.5.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH tip/core/rcu 3/8] waketorture: Don't kick unless grace period or request
  2016-06-15 22:27 [PATCH RFC tip/core/rcu 0/8] Waketorture, not for inclusion Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 1/8] waketorture: Add a wakeup-torture module Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 2/8] waketorture: Update scripting to accommodate waketorture Paul E. McKenney
@ 2016-06-15 22:28 ` Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 4/8] waketorture: Add utilization measurement Paul E. McKenney
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2016-06-15 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Paul E. McKenney

The current code can result in spurious kicks when there are no grace
periods in progress and no grace-period-related requests.  This is
sort of OK for a diagnostic aid, but the resulting ftrace-dump messages
in dmesg are annoying.  This commit therefore avoids spurious kicks
in the common case.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 kernel/rcu/tree.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index f433959e9322..88d3f9590322 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -1306,7 +1306,8 @@ static void rcu_stall_kick_kthreads(struct rcu_state *rsp)
 	if (!rcu_kick_kthreads)
 		return;
 	j = READ_ONCE(rsp->jiffies_kick_kthreads);
-	if (time_after(jiffies, j) && rsp->gp_kthread) {
+	if (time_after(jiffies, j) && rsp->gp_kthread &&
+	    (rcu_gp_in_progress(rsp) || READ_ONCE(rsp->gp_flags))) {
 		WARN_ONCE(1, "Kicking %s grace-period kthread\n", rsp->name);
 		rcu_ftrace_dump(DUMP_ALL);
 		wake_up_process(rsp->gp_kthread);
-- 
2.5.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH tip/core/rcu 4/8] waketorture: Add utilization measurement
  2016-06-15 22:27 [PATCH RFC tip/core/rcu 0/8] Waketorture, not for inclusion Paul E. McKenney
                   ` (2 preceding siblings ...)
  2016-06-15 22:28 ` [PATCH tip/core/rcu 3/8] waketorture: Don't kick unless grace period or request Paul E. McKenney
@ 2016-06-15 22:28 ` Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 5/8] waketorture: Add hrtimer support Paul E. McKenney
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2016-06-15 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Paul E. McKenney

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 kernel/rcu/waketorture.c | 29 ++++++++++++++++++++++++++++-
 lib/Kconfig.debug        |  1 +
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/kernel/rcu/waketorture.c b/kernel/rcu/waketorture.c
index 75bc547206cc..3068a5c858c8 100644
--- a/kernel/rcu/waketorture.c
+++ b/kernel/rcu/waketorture.c
@@ -81,7 +81,9 @@ static unsigned long *waiter_iter;	/* Number of wait iterations. */
 static bool *waiter_cts;		/* Waiter already checked. */
 static unsigned long *waiter_kicks;	/* Number of waiter starvations. */
 static unsigned long *waiter_ts;	/* Jiffies last run. */
-DEFINE_MUTEX(waiter_mutex);
+static DEFINE_MUTEX(waiter_mutex);
+static DEFINE_PER_CPU(u64, waiter_cputime); /* Nanoseconds. */
+static u64 starttime;
 
 static int torture_runnable = IS_ENABLED(MODULE);
 module_param(torture_runnable, int, 0444);
@@ -133,16 +135,23 @@ static int wake_torture_waiter(void *arg)
 {
 	int i;
 	long me = (long)arg;
+	u64 ts;
 
 	VERBOSE_TOROUT_STRING("wake_torture_waiter task started");
 	set_user_nice(current, MAX_NICE);
 
+	preempt_disable();
+	ts = trace_clock_local();
 	do {
 		waiter_ts[me] = jiffies;
 		smp_mb(); /* Ensure waiter_ts[] written before waiter_cts[]. */
 			  /* Pairs with [A]. */
 		waiter_cts[me] = false;
+		__this_cpu_add(waiter_cputime, trace_clock_local() - ts);
+		preempt_enable();
 		cur_ops->wait(wait_duration);
+		preempt_disable();
+		ts = trace_clock_local();
 		waiter_iter[me]++;
 		for (i = 0; i < nrealwaiters; i++) {
 			if (waiter_done[i] ||
@@ -164,8 +173,14 @@ static int wake_torture_waiter(void *arg)
 				mutex_unlock(&waiter_mutex);
 			}
 		}
+		__this_cpu_add(waiter_cputime, trace_clock_local() - ts);
+		preempt_enable();
 		torture_shutdown_absorb("wake_torture_waiter");
+		preempt_disable();
+		ts = trace_clock_local();
 	} while (!torture_must_stop());
+	__this_cpu_add(waiter_cputime, trace_clock_local() - ts);
+	preempt_enable();
 	mutex_lock(&waiter_mutex);
 	waiter_done[me] = true;
 	mutex_unlock(&waiter_mutex);
@@ -189,6 +204,8 @@ wake_torture_stats_print(void)
 {
 	int i;
 	bool tardy = false;
+	u64 timediff;
+	u64 timetot;
 
 	if (!waiter_done || !waiter_iter || !waiter_cts ||
 	    !waiter_kicks || !waiter_ts) {
@@ -212,6 +229,15 @@ wake_torture_stats_print(void)
 		pr_cont("\n");
 	else
 		TOROUT_STRING(" No tardy kthreads");
+	timediff = (trace_clock_global() - starttime) / 1000;
+	timetot = 0;
+	for_each_possible_cpu(i)
+		timetot += READ_ONCE(per_cpu(waiter_cputime, i));
+	timetot /= nr_cpu_ids;
+	timetot /= timediff;
+	pr_alert("%s" TORTURE_FLAG " timediff: %llu utilization: %llu.%llu nr_cpu_ids: %d\n",
+		 torture_type, timediff,
+		 timetot / 1000ULL, timetot % 1000ULL, nr_cpu_ids);
 }
 
 /*
@@ -290,6 +316,7 @@ wake_torture_init(void)
 
 	if (!torture_init_begin(torture_type, verbose, &torture_runnable))
 		return -EBUSY;
+	starttime = trace_clock_global();
 
 	/* Process args and tell the world that the torturer is on the job. */
 	for (i = 0; i < ARRAY_SIZE(torture_ops); i++) {
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index f0dcb4c0fe96..c8fb7dad5062 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1403,6 +1403,7 @@ config WAKE_TORTURE_TEST
 	tristate "Torture test for wakeups and CPU hotplug"
 	depends on DEBUG_KERNEL
 	depends on 64BIT
+	depends on TRACE_CLOCK
 	select TORTURE_TEST
 	default n
 	help
-- 
2.5.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH tip/core/rcu 5/8] waketorture: Add hrtimer support
  2016-06-15 22:27 [PATCH RFC tip/core/rcu 0/8] Waketorture, not for inclusion Paul E. McKenney
                   ` (3 preceding siblings ...)
  2016-06-15 22:28 ` [PATCH tip/core/rcu 4/8] waketorture: Add utilization measurement Paul E. McKenney
@ 2016-06-15 22:28 ` Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 6/8] torture: Make waketorture always hotplug the same CPU Paul E. McKenney
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2016-06-15 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Paul E. McKenney

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 kernel/rcu/waketorture.c                           | 50 ++++++++++++++++++----
 tools/testing/selftests/rcutorture/configs/wake/SH | 19 ++++++++
 .../selftests/rcutorture/configs/wake/SH.boot      |  1 +
 3 files changed, 61 insertions(+), 9 deletions(-)
 create mode 100644 tools/testing/selftests/rcutorture/configs/wake/SH
 create mode 100644 tools/testing/selftests/rcutorture/configs/wake/SH.boot

diff --git a/kernel/rcu/waketorture.c b/kernel/rcu/waketorture.c
index 3068a5c858c8..bf04c65296bd 100644
--- a/kernel/rcu/waketorture.c
+++ b/kernel/rcu/waketorture.c
@@ -62,12 +62,12 @@ torture_param(int, stat_interval, 60,
 	     "Number of seconds between stats printk()s");
 torture_param(bool, verbose, true,
 	     "Enable verbose debugging printk()s");
-torture_param(int, wait_duration, 3,
-	     "Number of jiffies to wait each iteration");
+torture_param(int, wait_duration, 127,
+	     "Number of microseconds to wait each iteration");
 torture_param(int, wait_grace, 20,
 	     "Number of jiffies before complaining about long wait");
 
-static char *torture_type = "sti";
+static char *torture_type = "sh";
 module_param(torture_type, charp, 0444);
 MODULE_PARM_DESC(torture_type, "Type of wait to torture (sti, stui, ...)");
 
@@ -94,18 +94,40 @@ MODULE_PARM_DESC(torture_runnable, "Start waketorture at boot");
  */
 
 struct wake_torture_ops {
-	signed long (*wait)(signed long timeout);
+	void (*wait)(void);
 	const char *name;
 };
 
 static struct wake_torture_ops *cur_ops;
 
 /*
+ * Definitions for schedule_hrtimeout() torture testing.
+ */
+
+static void wait_schedule_hrtimeout(void)
+{
+	ktime_t wait = ns_to_ktime(wait_duration * 1000);
+
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
+}
+
+static struct wake_torture_ops sh_ops = {
+	.wait		= wait_schedule_hrtimeout,
+	.name		= "sh"
+};
+
+/*
  * Definitions for schedule_timeout_interruptible() torture testing.
  */
 
+static void wait_schedule_timeout_interruptible(void)
+{
+	schedule_timeout_interruptible((wait_duration + 999) / 1000);
+}
+
 static struct wake_torture_ops sti_ops = {
-	.wait		= schedule_timeout_interruptible,
+	.wait		= wait_schedule_timeout_interruptible,
 	.name		= "sti"
 };
 
@@ -113,8 +135,13 @@ static struct wake_torture_ops sti_ops = {
  * Definitions for schedule_timeout_uninterruptible() torture testing.
  */
 
+static void wait_schedule_timeout_uninterruptible(void)
+{
+	schedule_timeout_uninterruptible((wait_duration + 999) / 1000);
+}
+
 static struct wake_torture_ops stui_ops = {
-	.wait		= schedule_timeout_uninterruptible,
+	.wait		= wait_schedule_timeout_uninterruptible,
 	.name		= "stui"
 };
 
@@ -149,7 +176,7 @@ static int wake_torture_waiter(void *arg)
 		waiter_cts[me] = false;
 		__this_cpu_add(waiter_cputime, trace_clock_local() - ts);
 		preempt_enable();
-		cur_ops->wait(wait_duration);
+		cur_ops->wait();
 		preempt_disable();
 		ts = trace_clock_local();
 		waiter_iter[me]++;
@@ -167,7 +194,10 @@ static int wake_torture_waiter(void *arg)
 			} else {
 				waiter_cts[i] = true;
 				waiter_kicks[i]++;
-				pr_alert("%s%s wake_torture_waiter(): P%d failing to awaken!\n", torture_type, TORTURE_FLAG, waiter_tasks[i]->pid);
+				pr_alert("%s%s wake_torture_waiter(): P%d (%#lx) failing to awaken!\n",
+					 torture_type, TORTURE_FLAG,
+					 waiter_tasks[i]->pid,
+					 waiter_tasks[i]->state);
 				rcu_ftrace_dump(DUMP_ALL);
 				wake_up_process(waiter_tasks[i]);
 				mutex_unlock(&waiter_mutex);
@@ -312,7 +342,9 @@ wake_torture_init(void)
 {
 	int i;
 	int firsterr = 0;
-	static struct wake_torture_ops *torture_ops[] = { &sti_ops, &stui_ops };
+	static struct wake_torture_ops *torture_ops[] = {
+		&sh_ops, &sti_ops, &stui_ops
+	};
 
 	if (!torture_init_begin(torture_type, verbose, &torture_runnable))
 		return -EBUSY;
diff --git a/tools/testing/selftests/rcutorture/configs/wake/SH b/tools/testing/selftests/rcutorture/configs/wake/SH
new file mode 100644
index 000000000000..7a17c503b382
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/wake/SH
@@ -0,0 +1,19 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
+#CHECK#CONFIG_PREEMPT_RCU=y
+CONFIG_HZ_PERIODIC=y
+CONFIG_NO_HZ_IDLE=n
+CONFIG_NO_HZ_FULL=n
+CONFIG_RCU_TRACE=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_RCU_FANOUT=2
+CONFIG_RCU_FANOUT_LEAF=2
+CONFIG_RCU_NOCB_CPU=n
+CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_RCU_BOOST=y
+CONFIG_RCU_KTHREAD_PRIO=2
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
+CONFIG_RCU_EXPERT=y
diff --git a/tools/testing/selftests/rcutorture/configs/wake/SH.boot b/tools/testing/selftests/rcutorture/configs/wake/SH.boot
new file mode 100644
index 000000000000..a631c878cb27
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/wake/SH.boot
@@ -0,0 +1 @@
+rcupdate.rcu_expedited waketorture.torture_type=sh
-- 
2.5.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH tip/core/rcu 6/8] torture: Make waketorture always hotplug the same CPU
  2016-06-15 22:27 [PATCH RFC tip/core/rcu 0/8] Waketorture, not for inclusion Paul E. McKenney
                   ` (4 preceding siblings ...)
  2016-06-15 22:28 ` [PATCH tip/core/rcu 5/8] waketorture: Add hrtimer support Paul E. McKenney
@ 2016-06-15 22:28 ` Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 7/8] torture: Make waketorture kill test if no hotpluggable CPUs Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 8/8] torture: Affinity waiter tasks away from hotpluggable CPU Paul E. McKenney
  7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2016-06-15 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Paul E. McKenney

This commit causes waketorture to always hotplug the same CPU,
namely, the highest-numbered CPU that can be hotplugged.  This
will be used by later commits to force race conditions with
higher probability.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 kernel/rcu/waketorture.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 85 insertions(+), 3 deletions(-)

diff --git a/kernel/rcu/waketorture.c b/kernel/rcu/waketorture.c
index bf04c65296bd..8568688607ac 100644
--- a/kernel/rcu/waketorture.c
+++ b/kernel/rcu/waketorture.c
@@ -74,6 +74,7 @@ MODULE_PARM_DESC(torture_type, "Type of wait to torture (sti, stui, ...)");
 static int nrealwaiters;
 static struct task_struct **waiter_tasks;
 static struct task_struct *stats_task;
+static struct task_struct *onoff_task;
 
 /* Yes, these cache-thrash, and it is inherent to the concurrency design. */
 static bool *waiter_done;		/* Waiter is done, don't wake. */
@@ -85,6 +86,18 @@ static DEFINE_MUTEX(waiter_mutex);
 static DEFINE_PER_CPU(u64, waiter_cputime); /* Nanoseconds. */
 static u64 starttime;
 
+static int onoff_cpu = -1;
+static long n_offline_attempts;
+static long n_offline_successes;
+static unsigned long sum_offline;
+static int min_offline = -1;
+static int max_offline;
+static long n_online_attempts;
+static long n_online_successes;
+static unsigned long sum_online;
+static int min_online = -1;
+static int max_online;
+
 static int torture_runnable = IS_ENABLED(MODULE);
 module_param(torture_runnable, int, 0444);
 MODULE_PARM_DESC(torture_runnable, "Start waketorture at boot");
@@ -219,6 +232,67 @@ static int wake_torture_waiter(void *arg)
 }
 
 /*
+ * Find a hotpluggable CPU and repeatedly take it online and offline.
+ */
+static int wake_torture_onoff(void *args)
+{
+	int cpu;
+
+	VERBOSE_TOROUT_STRING("wake_torture_onoff task started");
+	if (onoff_holdoff > 0) {
+		VERBOSE_TOROUT_STRING("wake_torture_onoff begin holdoff");
+		schedule_timeout_interruptible(onoff_holdoff * HZ);
+		VERBOSE_TOROUT_STRING("wake_torture_onoff end holdoff");
+	}
+	for_each_online_cpu(cpu) {
+		if (cpu_is_hotpluggable(cpu))
+			onoff_cpu = cpu;
+	}
+	pr_alert("%s" TORTURE_FLAG " wake_torture_onoff: onoff_cpu: %d\n", torture_type, onoff_cpu);
+	if (onoff_cpu < 0)
+		VERBOSE_TOROUT_STRING("wake_torture_onoff: no hotpluggable CPUs!");
+	while (!torture_must_stop() && onoff_cpu >= 0) {
+		if (!torture_offline(onoff_cpu,
+				    &n_offline_attempts, &n_offline_successes,
+				    &sum_offline, &min_offline, &max_offline))
+			torture_online(onoff_cpu,
+				       &n_online_attempts, &n_online_successes,
+				       &sum_online, &min_online, &max_online);
+		schedule_timeout_interruptible(onoff_interval);
+	}
+	torture_kthread_stopping("wake_torture_onoff");
+	return 0;
+}
+
+/*
+ * Initiate waketorture-specific online-offline handling, which
+ * focuses on a single CPU.
+ */
+static int wake_torture_onoff_init(void)
+{
+	int ret = 0;
+
+	if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
+		return ret;
+	if (onoff_interval <= 0)
+		return 0;
+	ret = torture_create_kthread(wake_torture_onoff, NULL, onoff_task);
+	return ret;
+}
+
+/*
+ * Clean up after waketorture-specific online-offline handling.
+ */
+static void wake_torture_onoff_cleanup(void)
+{
+	if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
+		return;
+	VERBOSE_TOROUT_STRING("Stopping wake_torture_onoff task");
+	kthread_stop(onoff_task);
+	onoff_task = NULL;
+}
+
+/*
  * Print torture statistics.  Caller must ensure that there is only one
  * call to this function at a given time!!!  This is normally accomplished
  * by relying on the module system to only have one copy of the module
@@ -265,9 +339,14 @@ wake_torture_stats_print(void)
 		timetot += READ_ONCE(per_cpu(waiter_cputime, i));
 	timetot /= nr_cpu_ids;
 	timetot /= timediff;
-	pr_alert("%s" TORTURE_FLAG " timediff: %llu utilization: %llu.%llu nr_cpu_ids: %d\n",
+	pr_alert("%s" TORTURE_FLAG " timediff: %llu utilization: %llu.%llu nr_cpu_ids: %d onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d)\n",
 		 torture_type, timediff,
-		 timetot / 1000ULL, timetot % 1000ULL, nr_cpu_ids);
+		 timetot / 1000ULL, timetot % 1000ULL, nr_cpu_ids,
+		 n_online_successes, n_online_attempts,
+		 n_offline_successes, n_offline_attempts,
+		 min_online, max_online,
+		 min_offline, max_offline,
+		 sum_online, sum_offline, HZ);
 }
 
 /*
@@ -307,6 +386,9 @@ wake_torture_cleanup(void)
 
 	(void)torture_cleanup_begin();
 
+	if (onoff_task)
+		wake_torture_onoff_cleanup();
+
 	if (waiter_tasks) {
 		for (i = 0; i < nrealwaiters; i++)
 			torture_stop_kthread(wake_torture_waiter,
@@ -414,7 +496,7 @@ wake_torture_init(void)
 	firsterr = torture_shutdown_init(shutdown_secs, wake_torture_cleanup);
 	if (firsterr)
 		goto unwind;
-	firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval);
+	firsterr = wake_torture_onoff_init();
 	if (firsterr)
 		goto unwind;
 	torture_init_end();
-- 
2.5.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH tip/core/rcu 7/8] torture: Make waketorture kill test if no hotpluggable CPUs
  2016-06-15 22:27 [PATCH RFC tip/core/rcu 0/8] Waketorture, not for inclusion Paul E. McKenney
                   ` (5 preceding siblings ...)
  2016-06-15 22:28 ` [PATCH tip/core/rcu 6/8] torture: Make waketorture always hotplug the same CPU Paul E. McKenney
@ 2016-06-15 22:28 ` Paul E. McKenney
  2016-06-15 22:28 ` [PATCH tip/core/rcu 8/8] torture: Affinity waiter tasks away from hotpluggable CPU Paul E. McKenney
  7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2016-06-15 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Paul E. McKenney

This commit shuts down the kernel if a shutdown time was specified and
if there were no hotpluggable CPUs.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 kernel/rcu/waketorture.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/kernel/rcu/waketorture.c b/kernel/rcu/waketorture.c
index 8568688607ac..f9843eb3f7b7 100644
--- a/kernel/rcu/waketorture.c
+++ b/kernel/rcu/waketorture.c
@@ -248,9 +248,15 @@ static int wake_torture_onoff(void *args)
 		if (cpu_is_hotpluggable(cpu))
 			onoff_cpu = cpu;
 	}
-	pr_alert("%s" TORTURE_FLAG " wake_torture_onoff: onoff_cpu: %d\n", torture_type, onoff_cpu);
-	if (onoff_cpu < 0)
+	if (onoff_cpu < 0) {
 		VERBOSE_TOROUT_STRING("wake_torture_onoff: no hotpluggable CPUs!");
+		if (shutdown_secs > 0) {
+			VERBOSE_TOROUT_STRING("wake_torture_onoff: Shutting down");
+			kernel_power_off();
+			VERBOSE_TOROUT_STRING("wake_torture_onoff: Survived kernel_power_off()?");
+		}
+	}
+	pr_alert("%s" TORTURE_FLAG " wake_torture_onoff: onoff_cpu: %d\n", torture_type, onoff_cpu);
 	while (!torture_must_stop() && onoff_cpu >= 0) {
 		if (!torture_offline(onoff_cpu,
 				    &n_offline_attempts, &n_offline_successes,
-- 
2.5.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH tip/core/rcu 8/8] torture: Affinity waiter tasks away from hotpluggable CPU
  2016-06-15 22:27 [PATCH RFC tip/core/rcu 0/8] Waketorture, not for inclusion Paul E. McKenney
                   ` (6 preceding siblings ...)
  2016-06-15 22:28 ` [PATCH tip/core/rcu 7/8] torture: Make waketorture kill test if no hotpluggable CPUs Paul E. McKenney
@ 2016-06-15 22:28 ` Paul E. McKenney
  7 siblings, 0 replies; 9+ messages in thread
From: Paul E. McKenney @ 2016-06-15 22:28 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Paul E. McKenney

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 kernel/rcu/waketorture.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/kernel/rcu/waketorture.c b/kernel/rcu/waketorture.c
index f9843eb3f7b7..68be40400f51 100644
--- a/kernel/rcu/waketorture.c
+++ b/kernel/rcu/waketorture.c
@@ -236,7 +236,9 @@ static int wake_torture_waiter(void *arg)
  */
 static int wake_torture_onoff(void *args)
 {
+	cpumask_var_t cm;
 	int cpu;
+	int i;
 
 	VERBOSE_TOROUT_STRING("wake_torture_onoff task started");
 	if (onoff_holdoff > 0) {
@@ -244,6 +246,11 @@ static int wake_torture_onoff(void *args)
 		schedule_timeout_interruptible(onoff_holdoff * HZ);
 		VERBOSE_TOROUT_STRING("wake_torture_onoff end holdoff");
 	}
+
+	/*
+	 * Find the last hotpluggable CPU, and affinity the waiter
+	 * tasks elsewhere.
+	 */
 	for_each_online_cpu(cpu) {
 		if (cpu_is_hotpluggable(cpu))
 			onoff_cpu = cpu;
@@ -257,6 +264,18 @@ static int wake_torture_onoff(void *args)
 		}
 	}
 	pr_alert("%s" TORTURE_FLAG " wake_torture_onoff: onoff_cpu: %d\n", torture_type, onoff_cpu);
+	if (!zalloc_cpumask_var(&cm, GFP_KERNEL)) {
+		VERBOSE_TOROUT_STRING("wake_torture_onoff: Out of memory, no affinity");
+	} else {
+		cpumask_copy(cm, cpu_online_mask);
+		cpumask_clear_cpu(onoff_cpu, cm);
+		if (cpumask_weight(cm) == 0)
+			cpumask_setall(cm);
+		for (i = 0; i < nrealwaiters; i++)
+			set_cpus_allowed_ptr(waiter_tasks[i], cm);
+	}
+
+	/* Cycle the victim CPU online and offline! */
 	while (!torture_must_stop() && onoff_cpu >= 0) {
 		if (!torture_offline(onoff_cpu,
 				    &n_offline_attempts, &n_offline_successes,
-- 
2.5.2

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-06-15 22:29 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-15 22:27 [PATCH RFC tip/core/rcu 0/8] Waketorture, not for inclusion Paul E. McKenney
2016-06-15 22:28 ` [PATCH tip/core/rcu 1/8] waketorture: Add a wakeup-torture module Paul E. McKenney
2016-06-15 22:28 ` [PATCH tip/core/rcu 2/8] waketorture: Update scripting to accommodate waketorture Paul E. McKenney
2016-06-15 22:28 ` [PATCH tip/core/rcu 3/8] waketorture: Don't kick unless grace period or request Paul E. McKenney
2016-06-15 22:28 ` [PATCH tip/core/rcu 4/8] waketorture: Add utilization measurement Paul E. McKenney
2016-06-15 22:28 ` [PATCH tip/core/rcu 5/8] waketorture: Add hrtimer support Paul E. McKenney
2016-06-15 22:28 ` [PATCH tip/core/rcu 6/8] torture: Make waketorture always hotplug the same CPU Paul E. McKenney
2016-06-15 22:28 ` [PATCH tip/core/rcu 7/8] torture: Make waketorture kill test if no hotpluggable CPUs Paul E. McKenney
2016-06-15 22:28 ` [PATCH tip/core/rcu 8/8] torture: Affinity waiter tasks away from hotpluggable CPU Paul E. McKenney

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.