aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutorture.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2012-01-20 18:36:33 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-02-21 12:03:52 -0500
commitc13f3757d0fcdcc2b7fc5d5e38da76b8913e6648 (patch)
tree7ae68a12459fc4f18b87fa1a44239e29f82cd244 /kernel/rcutorture.c
parent105617da8dc0ae3cf5f5a581330b1e4846fe87f2 (diff)
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>
Diffstat (limited to 'kernel/rcutorture.c')
-rw-r--r--kernel/rcutorture.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 2914cafe171b..5cfa23be43bd 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -67,6 +67,8 @@ static int fqs_stutter = 3; /* Wait time between bursts (s). */
67static int onoff_interval; /* Wait time between CPU hotplugs, 0=disable. */ 67static int onoff_interval; /* Wait time between CPU hotplugs, 0=disable. */
68static int onoff_holdoff; /* Seconds after boot before CPU hotplugs. */ 68static int onoff_holdoff; /* Seconds after boot before CPU hotplugs. */
69static int shutdown_secs; /* Shutdown time (s). <=0 for no shutdown. */ 69static int shutdown_secs; /* Shutdown time (s). <=0 for no shutdown. */
70static int stall_cpu; /* CPU-stall duration (s). 0 for no stall. */
71static int stall_cpu_holdoff = 10; /* Time to wait until stall (s). */
70static int test_boost = 1; /* Test RCU prio boost: 0=no, 1=maybe, 2=yes. */ 72static int test_boost = 1; /* Test RCU prio boost: 0=no, 1=maybe, 2=yes. */
71static int test_boost_interval = 7; /* Interval between boost tests, seconds. */ 73static int test_boost_interval = 7; /* Interval between boost tests, seconds. */
72static int test_boost_duration = 4; /* Duration of each boost test, seconds. */ 74static int test_boost_duration = 4; /* Duration of each boost test, seconds. */
@@ -100,6 +102,10 @@ module_param(onoff_holdoff, int, 0444);
100MODULE_PARM_DESC(onoff_holdoff, "Time after boot before CPU hotplugs (s)"); 102MODULE_PARM_DESC(onoff_holdoff, "Time after boot before CPU hotplugs (s)");
101module_param(shutdown_secs, int, 0444); 103module_param(shutdown_secs, int, 0444);
102MODULE_PARM_DESC(shutdown_secs, "Shutdown time (s), zero to disable."); 104MODULE_PARM_DESC(shutdown_secs, "Shutdown time (s), zero to disable.");
105module_param(stall_cpu, int, 0444);
106MODULE_PARM_DESC(stall_cpu, "Stall duration (s), zero to disable.");
107module_param(stall_cpu_holdoff, int, 0444);
108MODULE_PARM_DESC(stall_cpu_holdoff, "Time to wait before starting stall (s).");
103module_param(test_boost, int, 0444); 109module_param(test_boost, int, 0444);
104MODULE_PARM_DESC(test_boost, "Test RCU prio boost: 0=no, 1=maybe, 2=yes."); 110MODULE_PARM_DESC(test_boost, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
105module_param(test_boost_interval, int, 0444); 111module_param(test_boost_interval, int, 0444);
@@ -132,6 +138,7 @@ static struct task_struct *shutdown_task;
132#ifdef CONFIG_HOTPLUG_CPU 138#ifdef CONFIG_HOTPLUG_CPU
133static struct task_struct *onoff_task; 139static struct task_struct *onoff_task;
134#endif /* #ifdef CONFIG_HOTPLUG_CPU */ 140#endif /* #ifdef CONFIG_HOTPLUG_CPU */
141static struct task_struct *stall_task;
135 142
136#define RCU_TORTURE_PIPE_LEN 10 143#define RCU_TORTURE_PIPE_LEN 10
137 144
@@ -1489,6 +1496,63 @@ static void rcu_torture_onoff_cleanup(void)
1489 1496
1490#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */ 1497#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
1491 1498
1499/*
1500 * CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then
1501 * induces a CPU stall for the time specified by stall_cpu.
1502 */
1503static int __cpuinit rcu_torture_stall(void *args)
1504{
1505 unsigned long stop_at;
1506
1507 VERBOSE_PRINTK_STRING("rcu_torture_stall task started");
1508 if (stall_cpu_holdoff > 0) {
1509 VERBOSE_PRINTK_STRING("rcu_torture_stall begin holdoff");
1510 schedule_timeout_interruptible(stall_cpu_holdoff * HZ);
1511 VERBOSE_PRINTK_STRING("rcu_torture_stall end holdoff");
1512 }
1513 if (!kthread_should_stop()) {
1514 stop_at = get_seconds() + stall_cpu;
1515 /* RCU CPU stall is expected behavior in following code. */
1516 printk(KERN_ALERT "rcu_torture_stall start.\n");
1517 rcu_read_lock();
1518 preempt_disable();
1519 while (ULONG_CMP_LT(get_seconds(), stop_at))
1520 continue; /* Induce RCU CPU stall warning. */
1521 preempt_enable();
1522 rcu_read_unlock();
1523 printk(KERN_ALERT "rcu_torture_stall end.\n");
1524 }
1525 rcutorture_shutdown_absorb("rcu_torture_stall");
1526 while (!kthread_should_stop())
1527 schedule_timeout_interruptible(10 * HZ);
1528 return 0;
1529}
1530
1531/* Spawn CPU-stall kthread, if stall_cpu specified. */
1532static int __init rcu_torture_stall_init(void)
1533{
1534 int ret;
1535
1536 if (stall_cpu <= 0)
1537 return 0;
1538 stall_task = kthread_run(rcu_torture_stall, NULL, "rcu_torture_stall");
1539 if (IS_ERR(stall_task)) {
1540 ret = PTR_ERR(stall_task);
1541 stall_task = NULL;
1542 return ret;
1543 }
1544 return 0;
1545}
1546
1547/* Clean up after the CPU-stall kthread, if one was spawned. */
1548static void rcu_torture_stall_cleanup(void)
1549{
1550 if (stall_task == NULL)
1551 return;
1552 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stall_task.");
1553 kthread_stop(stall_task);
1554}
1555
1492static int rcutorture_cpu_notify(struct notifier_block *self, 1556static int rcutorture_cpu_notify(struct notifier_block *self,
1493 unsigned long action, void *hcpu) 1557 unsigned long action, void *hcpu)
1494{ 1558{
@@ -1531,6 +1595,7 @@ rcu_torture_cleanup(void)
1531 fullstop = FULLSTOP_RMMOD; 1595 fullstop = FULLSTOP_RMMOD;
1532 mutex_unlock(&fullstop_mutex); 1596 mutex_unlock(&fullstop_mutex);
1533 unregister_reboot_notifier(&rcutorture_shutdown_nb); 1597 unregister_reboot_notifier(&rcutorture_shutdown_nb);
1598 rcu_torture_stall_cleanup();
1534 if (stutter_task) { 1599 if (stutter_task) {
1535 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task"); 1600 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stutter task");
1536 kthread_stop(stutter_task); 1601 kthread_stop(stutter_task);
@@ -1831,6 +1896,7 @@ rcu_torture_init(void)
1831 } 1896 }
1832 rcu_torture_onoff_init(); 1897 rcu_torture_onoff_init();
1833 register_reboot_notifier(&rcutorture_shutdown_nb); 1898 register_reboot_notifier(&rcutorture_shutdown_nb);
1899 rcu_torture_stall_init();
1834 rcutorture_record_test_transition(); 1900 rcutorture_record_test_transition();
1835 mutex_unlock(&fullstop_mutex); 1901 mutex_unlock(&fullstop_mutex);
1836 return 0; 1902 return 0;