rcu: Add CPU-stall capability to rcutorture
Add module parameters to rcutorture that induce a CPU stall. The stall_cpu parameter specifies how long to stall in seconds, defaulting to zero, which indicates no stalling is to be undertaken. The stall_cpu_holdoff parameter specifies how many seconds after insmod (or boot, if rcutorture is built into the kernel) that this stall is to start. The default value for stall_cpu_holdoff is ten seconds. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
This commit is contained in:
parent
105617da8d
commit
c13f3757d0
|
@ -86,6 +86,24 @@ shutdown_secs The number of seconds to run the test before terminating
|
||||||
zero, which disables test termination and system shutdown.
|
zero, which disables test termination and system shutdown.
|
||||||
This capability is useful for automated testing.
|
This capability is useful for automated testing.
|
||||||
|
|
||||||
|
stall_cpu The number of seconds that a CPU should be stalled while
|
||||||
|
within both an rcu_read_lock() and a preempt_disable().
|
||||||
|
This stall happens only once per rcutorture run.
|
||||||
|
If you need multiple stalls, use modprobe and rmmod to
|
||||||
|
repeatedly run rcutorture. The default for stall_cpu
|
||||||
|
is zero, which prevents rcutorture from stalling a CPU.
|
||||||
|
|
||||||
|
Note that attempts to rmmod rcutorture while the stall
|
||||||
|
is ongoing will hang, so be careful what value you
|
||||||
|
choose for this module parameter! In addition, too-large
|
||||||
|
values for stall_cpu might well induce failures and
|
||||||
|
warnings in other parts of the kernel. You have been
|
||||||
|
warned!
|
||||||
|
|
||||||
|
stall_cpu_holdoff
|
||||||
|
The number of seconds to wait after rcutorture starts
|
||||||
|
before stalling a CPU. Defaults to 10 seconds.
|
||||||
|
|
||||||
stat_interval The number of seconds between output of torture
|
stat_interval The number of seconds between output of torture
|
||||||
statistics (via printk()). Regardless of the interval,
|
statistics (via printk()). Regardless of the interval,
|
||||||
statistics are printed when the module is unloaded.
|
statistics are printed when the module is unloaded.
|
||||||
|
|
|
@ -67,6 +67,8 @@ static int fqs_stutter = 3; /* Wait time between bursts (s). */
|
||||||
static int onoff_interval; /* Wait time between CPU hotplugs, 0=disable. */
|
static int onoff_interval; /* Wait time between CPU hotplugs, 0=disable. */
|
||||||
static int onoff_holdoff; /* Seconds after boot before CPU hotplugs. */
|
static int onoff_holdoff; /* Seconds after boot before CPU hotplugs. */
|
||||||
static int shutdown_secs; /* Shutdown time (s). <=0 for no shutdown. */
|
static int shutdown_secs; /* Shutdown time (s). <=0 for no shutdown. */
|
||||||
|
static int stall_cpu; /* CPU-stall duration (s). 0 for no stall. */
|
||||||
|
static int stall_cpu_holdoff = 10; /* Time to wait until stall (s). */
|
||||||
static int test_boost = 1; /* Test RCU prio boost: 0=no, 1=maybe, 2=yes. */
|
static int test_boost = 1; /* Test RCU prio boost: 0=no, 1=maybe, 2=yes. */
|
||||||
static int test_boost_interval = 7; /* Interval between boost tests, seconds. */
|
static int test_boost_interval = 7; /* Interval between boost tests, seconds. */
|
||||||
static int test_boost_duration = 4; /* Duration of each boost test, seconds. */
|
static int test_boost_duration = 4; /* Duration of each boost test, seconds. */
|
||||||
|
@ -100,6 +102,10 @@ module_param(onoff_holdoff, int, 0444);
|
||||||
MODULE_PARM_DESC(onoff_holdoff, "Time after boot before CPU hotplugs (s)");
|
MODULE_PARM_DESC(onoff_holdoff, "Time after boot before CPU hotplugs (s)");
|
||||||
module_param(shutdown_secs, int, 0444);
|
module_param(shutdown_secs, int, 0444);
|
||||||
MODULE_PARM_DESC(shutdown_secs, "Shutdown time (s), zero to disable.");
|
MODULE_PARM_DESC(shutdown_secs, "Shutdown time (s), zero to disable.");
|
||||||
|
module_param(stall_cpu, int, 0444);
|
||||||
|
MODULE_PARM_DESC(stall_cpu, "Stall duration (s), zero to disable.");
|
||||||
|
module_param(stall_cpu_holdoff, int, 0444);
|
||||||
|
MODULE_PARM_DESC(stall_cpu_holdoff, "Time to wait before starting stall (s).");
|
||||||
module_param(test_boost, int, 0444);
|
module_param(test_boost, int, 0444);
|
||||||
MODULE_PARM_DESC(test_boost, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
|
MODULE_PARM_DESC(test_boost, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
|
||||||
module_param(test_boost_interval, int, 0444);
|
module_param(test_boost_interval, int, 0444);
|
||||||
|
@ -132,6 +138,7 @@ static struct task_struct *shutdown_task;
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
static struct task_struct *onoff_task;
|
static struct task_struct *onoff_task;
|
||||||
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
|
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
|
||||||
|
static struct task_struct *stall_task;
|
||||||
|
|
||||||
#define RCU_TORTURE_PIPE_LEN 10
|
#define RCU_TORTURE_PIPE_LEN 10
|
||||||
|
|
||||||
|
@ -1489,6 +1496,63 @@ static void rcu_torture_onoff_cleanup(void)
|
||||||
|
|
||||||
#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
|
#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then
|
||||||
|
* induces a CPU stall for the time specified by stall_cpu.
|
||||||
|
*/
|
||||||
|
static int __cpuinit rcu_torture_stall(void *args)
|
||||||
|
{
|
||||||
|
unsigned long stop_at;
|
||||||
|
|
||||||
|
VERBOSE_PRINTK_STRING("rcu_torture_stall task started");
|
||||||
|
if (stall_cpu_holdoff > 0) {
|
||||||
|
VERBOSE_PRINTK_STRING("rcu_torture_stall begin holdoff");
|
||||||
|
schedule_timeout_interruptible(stall_cpu_holdoff * HZ);
|
||||||
|
VERBOSE_PRINTK_STRING("rcu_torture_stall end holdoff");
|
||||||
|
}
|
||||||
|
if (!kthread_should_stop()) {
|
||||||
|
stop_at = get_seconds() + stall_cpu;
|
||||||
|
/* RCU CPU stall is expected behavior in following code. */
|
||||||
|
printk(KERN_ALERT "rcu_torture_stall start.\n");
|
||||||
|
rcu_read_lock();
|
||||||
|
preempt_disable();
|
||||||
|
while (ULONG_CMP_LT(get_seconds(), stop_at))
|
||||||
|
continue; /* Induce RCU CPU stall warning. */
|
||||||
|
preempt_enable();
|
||||||
|
rcu_read_unlock();
|
||||||
|
printk(KERN_ALERT "rcu_torture_stall end.\n");
|
||||||
|
}
|
||||||
|
rcutorture_shutdown_absorb("rcu_torture_stall");
|
||||||
|
while (!kthread_should_stop())
|
||||||
|
schedule_timeout_interruptible(10 * HZ);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spawn CPU-stall kthread, if stall_cpu specified. */
|
||||||
|
static int __init rcu_torture_stall_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (stall_cpu <= 0)
|
||||||
|
return 0;
|
||||||
|
stall_task = kthread_run(rcu_torture_stall, NULL, "rcu_torture_stall");
|
||||||
|
if (IS_ERR(stall_task)) {
|
||||||
|
ret = PTR_ERR(stall_task);
|
||||||
|
stall_task = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up after the CPU-stall kthread, if one was spawned. */
|
||||||
|
static void rcu_torture_stall_cleanup(void)
|
||||||
|
{
|
||||||
|
if (stall_task == NULL)
|
||||||
|
return;
|
||||||
|
VERBOSE_PRINTK_STRING("Stopping rcu_torture_stall_task.");
|
||||||
|
kthread_stop(stall_task);
|
||||||
|
}
|
||||||
|
|
||||||
static int rcutorture_cpu_notify(struct notifier_block *self,
|
static int rcutorture_cpu_notify(struct notifier_block *self,
|
||||||
unsigned long action, void *hcpu)
|
unsigned long action, void *hcpu)
|
||||||
{
|
{
|
||||||
|
@ -1531,6 +1595,7 @@ rcu_torture_cleanup(void)
|
||||||
fullstop = FULLSTOP_RMMOD;
|
fullstop = FULLSTOP_RMMOD;
|
||||||
mutex_unlock(&fullstop_mutex);
|
mutex_unlock(&fullstop_mutex);
|
||||||
unregister_reboot_notifier(&rcutorture_shutdown_nb);
|
unregister_reboot_notifier(&rcutorture_shutdown_nb);
|
||||||
|
rcu_torture_stall_cleanup();
|
||||||
if (stutter_task) {
|
if (stutter_task) {
|
||||||
VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
|
VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
|
||||||
kthread_stop(stutter_task);
|
kthread_stop(stutter_task);
|
||||||
|
@ -1831,6 +1896,7 @@ rcu_torture_init(void)
|
||||||
}
|
}
|
||||||
rcu_torture_onoff_init();
|
rcu_torture_onoff_init();
|
||||||
register_reboot_notifier(&rcutorture_shutdown_nb);
|
register_reboot_notifier(&rcutorture_shutdown_nb);
|
||||||
|
rcu_torture_stall_init();
|
||||||
rcutorture_record_test_transition();
|
rcutorture_record_test_transition();
|
||||||
mutex_unlock(&fullstop_mutex);
|
mutex_unlock(&fullstop_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue