Skip to content

Commit 584975c

Browse files
paulmckrcuurezki
authored andcommitted
rcutorture: Add random real-time preemption
This commit adds the rcutorture.preempt_duration kernel module parameter, which gives the real-time preemption duration in milliseconds (zero to disable, which is the default) and also the rcutorture.preempt_interval module parameter, which gives the interval between successive preemptions, also in milliseconds, defaulting to one second. The CPU to preempt is chosen at random from those online at that time. Races between preempting a given CPU and that CPU going offline are ignored, and preemption is forgone when this occurs. Signed-off-by: Paul E. McKenney <[email protected]> Signed-off-by: Uladzislau Rezki (Sony) <[email protected]>
1 parent 0203b48 commit 584975c

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5424,6 +5424,22 @@
54245424
Set time (jiffies) between CPU-hotplug operations,
54255425
or zero to disable CPU-hotplug testing.
54265426

5427+
rcutorture.preempt_duration= [KNL]
5428+
Set duration (in milliseconds) of preemptions
5429+
by a high-priority FIFO real-time task. Set to
5430+
zero (the default) to disable. The CPUs to
5431+
preempt are selected randomly from the set that
5432+
are online at a given point in time. Races with
5433+
CPUs going offline are ignored, with that attempt
5434+
at preemption skipped.
5435+
5436+
rcutorture.preempt_interval= [KNL]
5437+
Set interval (in milliseconds, defaulting to one
5438+
second) between preemptions by a high-priority
5439+
FIFO real-time task. This delay is mediated
5440+
by an hrtimer and is further fuzzed to avoid
5441+
inadvertent synchronizations.
5442+
54275443
rcutorture.read_exit_burst= [KNL]
54285444
The number of times in a given read-then-exit
54295445
episode that a set of read-then-exit kthreads

kernel/rcu/rcutorture.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ torture_param(int, onoff_holdoff, 0, "Time after boot before CPU hotplugs (s)");
109109
torture_param(int, onoff_interval, 0, "Time between CPU hotplugs (jiffies), 0=disable");
110110
torture_param(int, nocbs_nthreads, 0, "Number of NOCB toggle threads, 0 to disable");
111111
torture_param(int, nocbs_toggle, 1000, "Time between toggling nocb state (ms)");
112+
torture_param(int, preempt_duration, 0, "Preemption duration (ms), zero to disable");
113+
torture_param(int, preempt_interval, MSEC_PER_SEC, "Interval between preemptions (ms)");
112114
torture_param(int, read_exit_delay, 13, "Delay between read-then-exit episodes (s)");
113115
torture_param(int, read_exit_burst, 16, "# of read-then-exit bursts per episode, zero to disable");
114116
torture_param(int, reader_flavor, 0x1, "Reader flavors to use, one per bit.");
@@ -149,6 +151,7 @@ static struct task_struct **fwd_prog_tasks;
149151
static struct task_struct **barrier_cbs_tasks;
150152
static struct task_struct *barrier_task;
151153
static struct task_struct *read_exit_task;
154+
static struct task_struct *preempt_task;
152155

153156
#define RCU_TORTURE_PIPE_LEN 10
154157

@@ -2425,7 +2428,8 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
24252428
"read_exit_delay=%d read_exit_burst=%d "
24262429
"reader_flavor=%x "
24272430
"nocbs_nthreads=%d nocbs_toggle=%d "
2428-
"test_nmis=%d\n",
2431+
"test_nmis=%d "
2432+
"preempt_duration=%d preempt_interval=%d\n",
24292433
torture_type, tag, nrealreaders, nfakewriters,
24302434
stat_interval, verbose, test_no_idle_hz, shuffle_interval,
24312435
stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
@@ -2438,7 +2442,8 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
24382442
read_exit_delay, read_exit_burst,
24392443
reader_flavor,
24402444
nocbs_nthreads, nocbs_toggle,
2441-
test_nmis);
2445+
test_nmis,
2446+
preempt_duration, preempt_interval);
24422447
}
24432448

24442449
static int rcutorture_booster_cleanup(unsigned int cpu)
@@ -3418,6 +3423,35 @@ static void rcutorture_test_nmis(int n)
34183423
#endif // #else // #if IS_BUILTIN(CONFIG_RCU_TORTURE_TEST)
34193424
}
34203425

3426+
// Randomly preempt online CPUs.
3427+
static int rcu_torture_preempt(void *unused)
3428+
{
3429+
int cpu = -1;
3430+
DEFINE_TORTURE_RANDOM(rand);
3431+
3432+
schedule_timeout_idle(stall_cpu_holdoff);
3433+
do {
3434+
// Wait for preempt_interval ms with up to 100us fuzz.
3435+
torture_hrtimeout_ms(preempt_interval, 100, &rand);
3436+
// Select online CPU.
3437+
cpu = cpumask_next(cpu, cpu_online_mask);
3438+
if (cpu >= nr_cpu_ids)
3439+
cpu = cpumask_next(-1, cpu_online_mask);
3440+
WARN_ON_ONCE(cpu >= nr_cpu_ids);
3441+
// Move to that CPU, if can't do so, retry later.
3442+
if (torture_sched_setaffinity(current->pid, cpumask_of(cpu), false))
3443+
continue;
3444+
// Preempt at high-ish priority, then reset to normal.
3445+
sched_set_fifo(current);
3446+
torture_sched_setaffinity(current->pid, cpu_present_mask, true);
3447+
mdelay(preempt_duration);
3448+
sched_set_normal(current, 0);
3449+
stutter_wait("rcu_torture_preempt");
3450+
} while (!torture_must_stop());
3451+
torture_kthread_stopping("rcu_torture_preempt");
3452+
return 0;
3453+
}
3454+
34213455
static enum cpuhp_state rcutor_hp;
34223456

34233457
static void
@@ -3446,6 +3480,7 @@ rcu_torture_cleanup(void)
34463480

34473481
if (cur_ops->gp_kthread_dbg)
34483482
cur_ops->gp_kthread_dbg();
3483+
torture_stop_kthread(rcu_torture_preempt, preempt_task);
34493484
rcu_torture_read_exit_cleanup();
34503485
rcu_torture_barrier_cleanup();
34513486
rcu_torture_fwd_prog_cleanup();
@@ -4019,6 +4054,11 @@ rcu_torture_init(void)
40194054
firsterr = rcu_torture_read_exit_init();
40204055
if (torture_init_error(firsterr))
40214056
goto unwind;
4057+
if (preempt_duration > 0) {
4058+
firsterr = torture_create_kthread(rcu_torture_preempt, NULL, preempt_task);
4059+
if (torture_init_error(firsterr))
4060+
goto unwind;
4061+
}
40224062
if (object_debug)
40234063
rcu_test_debug_objects();
40244064
torture_init_end();

0 commit comments

Comments
 (0)