@@ -109,6 +109,8 @@ torture_param(int, onoff_holdoff, 0, "Time after boot before CPU hotplugs (s)");
109
109
torture_param (int , onoff_interval , 0 , "Time between CPU hotplugs (jiffies), 0=disable" );
110
110
torture_param (int , nocbs_nthreads , 0 , "Number of NOCB toggle threads, 0 to disable" );
111
111
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)" );
112
114
torture_param (int , read_exit_delay , 13 , "Delay between read-then-exit episodes (s)" );
113
115
torture_param (int , read_exit_burst , 16 , "# of read-then-exit bursts per episode, zero to disable" );
114
116
torture_param (int , reader_flavor , 0x1 , "Reader flavors to use, one per bit." );
@@ -149,6 +151,7 @@ static struct task_struct **fwd_prog_tasks;
149
151
static struct task_struct * * barrier_cbs_tasks ;
150
152
static struct task_struct * barrier_task ;
151
153
static struct task_struct * read_exit_task ;
154
+ static struct task_struct * preempt_task ;
152
155
153
156
#define RCU_TORTURE_PIPE_LEN 10
154
157
@@ -2425,7 +2428,8 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
2425
2428
"read_exit_delay=%d read_exit_burst=%d "
2426
2429
"reader_flavor=%x "
2427
2430
"nocbs_nthreads=%d nocbs_toggle=%d "
2428
- "test_nmis=%d\n" ,
2431
+ "test_nmis=%d "
2432
+ "preempt_duration=%d preempt_interval=%d\n" ,
2429
2433
torture_type , tag , nrealreaders , nfakewriters ,
2430
2434
stat_interval , verbose , test_no_idle_hz , shuffle_interval ,
2431
2435
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)
2438
2442
read_exit_delay , read_exit_burst ,
2439
2443
reader_flavor ,
2440
2444
nocbs_nthreads , nocbs_toggle ,
2441
- test_nmis );
2445
+ test_nmis ,
2446
+ preempt_duration , preempt_interval );
2442
2447
}
2443
2448
2444
2449
static int rcutorture_booster_cleanup (unsigned int cpu )
@@ -3418,6 +3423,35 @@ static void rcutorture_test_nmis(int n)
3418
3423
#endif // #else // #if IS_BUILTIN(CONFIG_RCU_TORTURE_TEST)
3419
3424
}
3420
3425
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
+
3421
3455
static enum cpuhp_state rcutor_hp ;
3422
3456
3423
3457
static void
@@ -3446,6 +3480,7 @@ rcu_torture_cleanup(void)
3446
3480
3447
3481
if (cur_ops -> gp_kthread_dbg )
3448
3482
cur_ops -> gp_kthread_dbg ();
3483
+ torture_stop_kthread (rcu_torture_preempt , preempt_task );
3449
3484
rcu_torture_read_exit_cleanup ();
3450
3485
rcu_torture_barrier_cleanup ();
3451
3486
rcu_torture_fwd_prog_cleanup ();
@@ -4019,6 +4054,11 @@ rcu_torture_init(void)
4019
4054
firsterr = rcu_torture_read_exit_init ();
4020
4055
if (torture_init_error (firsterr ))
4021
4056
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
+ }
4022
4062
if (object_debug )
4023
4063
rcu_test_debug_objects ();
4024
4064
torture_init_end ();
0 commit comments