@@ -109,6 +109,8 @@ torture_param(int, onoff_holdoff, 0, "Time after boot before CPU hotplugs (s)");
109109torture_param (int , onoff_interval , 0 , "Time between CPU hotplugs (jiffies), 0=disable" );
110110torture_param (int , nocbs_nthreads , 0 , "Number of NOCB toggle threads, 0 to disable" );
111111torture_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)" );
112114torture_param (int , read_exit_delay , 13 , "Delay between read-then-exit episodes (s)" );
113115torture_param (int , read_exit_burst , 16 , "# of read-then-exit bursts per episode, zero to disable" );
114116torture_param (int , reader_flavor , 0x1 , "Reader flavors to use, one per bit." );
@@ -149,6 +151,7 @@ static struct task_struct **fwd_prog_tasks;
149151static struct task_struct * * barrier_cbs_tasks ;
150152static struct task_struct * barrier_task ;
151153static 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
24442449static 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+
34213455static enum cpuhp_state rcutor_hp ;
34223456
34233457static 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