Skip to content

Commit 58cb321

Browse files
paulmckrcuNeeraj Upadhyay
authored andcommitted
rcutorture: Add a stall_cpu_repeat module parameter
This commit adds an stall_cpu_repeat kernel, which is also the rcutorture.stall_cpu_repeat boot parameter, to test repeated CPU stalls. Note that only the first stall will pay attention to the stall_cpu_irqsoff module parameter. For the second and subsequent stalls, interrupts will be enabled. This is helpful when testing the interaction between RCU CPU stall warnings and CSD-lock stall warnings. Reported-by: Rik van Riel <[email protected]> Signed-off-by: "Paul E. McKenney" <[email protected]> Signed-off-by: Neeraj Upadhyay <[email protected]>
1 parent cfdbfb9 commit 58cb321

File tree

2 files changed

+47
-17
lines changed

2 files changed

+47
-17
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5384,7 +5384,13 @@
53845384
Time to wait (s) after boot before inducing stall.
53855385

53865386
rcutorture.stall_cpu_irqsoff= [KNL]
5387-
Disable interrupts while stalling if set.
5387+
Disable interrupts while stalling if set, but only
5388+
on the first stall in the set.
5389+
5390+
rcutorture.stall_cpu_repeat= [KNL]
5391+
Number of times to repeat the stall sequence,
5392+
so that rcutorture.stall_cpu_repeat=3 will result
5393+
in four stall sequences.
53885394

53895395
rcutorture.stall_gp_kthread= [KNL]
53905396
Duration (s) of forced sleep within RCU

kernel/rcu/rcutorture.c

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ torture_param(int, stall_cpu_holdoff, 10, "Time to wait before starting stall (s
115115
torture_param(bool, stall_no_softlockup, false, "Avoid softlockup warning during cpu stall.");
116116
torture_param(int, stall_cpu_irqsoff, 0, "Disable interrupts while stalling.");
117117
torture_param(int, stall_cpu_block, 0, "Sleep while stalling.");
118+
torture_param(int, stall_cpu_repeat, 0, "Number of additional stalls after the first one.");
118119
torture_param(int, stall_gp_kthread, 0, "Grace-period kthread stall duration (s).");
119120
torture_param(int, stat_interval, 60, "Number of seconds between stats printk()s");
120121
torture_param(int, stutter, 5, "Number of seconds to run/halt test");
@@ -1393,7 +1394,8 @@ rcu_torture_writer(void *arg)
13931394

13941395
// If a new stall test is added, this must be adjusted.
13951396
if (stall_cpu_holdoff + stall_gp_kthread + stall_cpu)
1396-
stallsdone += (stall_cpu_holdoff + stall_gp_kthread + stall_cpu + 60) * HZ;
1397+
stallsdone += (stall_cpu_holdoff + stall_gp_kthread + stall_cpu + 60) *
1398+
HZ * (stall_cpu_repeat + 1);
13971399
VERBOSE_TOROUT_STRING("rcu_torture_writer task started");
13981400
if (!can_expedite)
13991401
pr_alert("%s" TORTURE_FLAG
@@ -2391,7 +2393,7 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
23912393
"test_boost=%d/%d test_boost_interval=%d "
23922394
"test_boost_duration=%d shutdown_secs=%d "
23932395
"stall_cpu=%d stall_cpu_holdoff=%d stall_cpu_irqsoff=%d "
2394-
"stall_cpu_block=%d "
2396+
"stall_cpu_block=%d stall_cpu_repeat=%d "
23952397
"n_barrier_cbs=%d "
23962398
"onoff_interval=%d onoff_holdoff=%d "
23972399
"read_exit_delay=%d read_exit_burst=%d "
@@ -2403,7 +2405,7 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
24032405
test_boost, cur_ops->can_boost,
24042406
test_boost_interval, test_boost_duration, shutdown_secs,
24052407
stall_cpu, stall_cpu_holdoff, stall_cpu_irqsoff,
2406-
stall_cpu_block,
2408+
stall_cpu_block, stall_cpu_repeat,
24072409
n_barrier_cbs,
24082410
onoff_interval, onoff_holdoff,
24092411
read_exit_delay, read_exit_burst,
@@ -2481,19 +2483,11 @@ static struct notifier_block rcu_torture_stall_block = {
24812483
* induces a CPU stall for the time specified by stall_cpu. If a new
24822484
* stall test is added, stallsdone in rcu_torture_writer() must be adjusted.
24832485
*/
2484-
static int rcu_torture_stall(void *args)
2486+
static void rcu_torture_stall_one(int rep, int irqsoff)
24852487
{
24862488
int idx;
2487-
int ret;
24882489
unsigned long stop_at;
24892490

2490-
VERBOSE_TOROUT_STRING("rcu_torture_stall task started");
2491-
if (rcu_cpu_stall_notifiers) {
2492-
ret = rcu_stall_chain_notifier_register(&rcu_torture_stall_block);
2493-
if (ret)
2494-
pr_info("%s: rcu_stall_chain_notifier_register() returned %d, %sexpected.\n",
2495-
__func__, ret, !IS_ENABLED(CONFIG_RCU_STALL_COMMON) ? "un" : "");
2496-
}
24972491
if (stall_cpu_holdoff > 0) {
24982492
VERBOSE_TOROUT_STRING("rcu_torture_stall begin holdoff");
24992493
schedule_timeout_interruptible(stall_cpu_holdoff * HZ);
@@ -2513,12 +2507,12 @@ static int rcu_torture_stall(void *args)
25132507
stop_at = ktime_get_seconds() + stall_cpu;
25142508
/* RCU CPU stall is expected behavior in following code. */
25152509
idx = cur_ops->readlock();
2516-
if (stall_cpu_irqsoff)
2510+
if (irqsoff)
25172511
local_irq_disable();
25182512
else if (!stall_cpu_block)
25192513
preempt_disable();
2520-
pr_alert("%s start on CPU %d.\n",
2521-
__func__, raw_smp_processor_id());
2514+
pr_alert("%s start stall episode %d on CPU %d.\n",
2515+
__func__, rep + 1, raw_smp_processor_id());
25222516
while (ULONG_CMP_LT((unsigned long)ktime_get_seconds(), stop_at) &&
25232517
!kthread_should_stop())
25242518
if (stall_cpu_block) {
@@ -2530,12 +2524,42 @@ static int rcu_torture_stall(void *args)
25302524
} else if (stall_no_softlockup) {
25312525
touch_softlockup_watchdog();
25322526
}
2533-
if (stall_cpu_irqsoff)
2527+
if (irqsoff)
25342528
local_irq_enable();
25352529
else if (!stall_cpu_block)
25362530
preempt_enable();
25372531
cur_ops->readunlock(idx);
25382532
}
2533+
}
2534+
2535+
/*
2536+
* CPU-stall kthread. Invokes rcu_torture_stall_one() once, and then as many
2537+
* additional times as specified by the stall_cpu_repeat module parameter.
2538+
* Note that stall_cpu_irqsoff is ignored on the second and subsequent
2539+
* stall.
2540+
*/
2541+
static int rcu_torture_stall(void *args)
2542+
{
2543+
int i;
2544+
int repeat = stall_cpu_repeat;
2545+
int ret;
2546+
2547+
VERBOSE_TOROUT_STRING("rcu_torture_stall task started");
2548+
if (repeat < 0) {
2549+
repeat = 0;
2550+
WARN_ON_ONCE(IS_BUILTIN(CONFIG_RCU_TORTURE_TEST));
2551+
}
2552+
if (rcu_cpu_stall_notifiers) {
2553+
ret = rcu_stall_chain_notifier_register(&rcu_torture_stall_block);
2554+
if (ret)
2555+
pr_info("%s: rcu_stall_chain_notifier_register() returned %d, %sexpected.\n",
2556+
__func__, ret, !IS_ENABLED(CONFIG_RCU_STALL_COMMON) ? "un" : "");
2557+
}
2558+
for (i = 0; i <= repeat; i++) {
2559+
if (kthread_should_stop())
2560+
break;
2561+
rcu_torture_stall_one(i, i == 0 ? stall_cpu_irqsoff : 0);
2562+
}
25392563
pr_alert("%s end.\n", __func__);
25402564
if (rcu_cpu_stall_notifiers && !ret) {
25412565
ret = rcu_stall_chain_notifier_unregister(&rcu_torture_stall_block);

0 commit comments

Comments
 (0)