We add a new RCU type to test call_rcu_lazy(). This allows us to just override the '.call' callback. To compensate for the laziness, we force the laziness to a small number of jiffies. The idea of this test is to stress the new code paths for stability and ensure it at least is providing behavior in parity with, or similar to, call_rcu(). The actual check for amount of laziness is in another test (rcuscale). Signed-off-by: Joel Fernandes (Google) <joel@xxxxxxxxxxxxxxxxx> --- kernel/rcu/rcu.h | 1 + kernel/rcu/rcutorture.c | 60 ++++++++++++++++++- kernel/rcu/tree.c | 1 + .../selftests/rcutorture/configs/rcu/CFLIST | 1 + .../selftests/rcutorture/configs/rcu/TREE11 | 18 ++++++ .../rcutorture/configs/rcu/TREE11.boot | 8 +++ 6 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/rcutorture/configs/rcu/TREE11 create mode 100644 tools/testing/selftests/rcutorture/configs/rcu/TREE11.boot diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h index 8e7ff7c18072..c358387fd223 100644 --- a/kernel/rcu/rcu.h +++ b/kernel/rcu/rcu.h @@ -460,6 +460,7 @@ enum rcutorture_type { RCU_TASKS_TRACING_FLAVOR, RCU_TRIVIAL_FLAVOR, SRCU_FLAVOR, + RCU_LAZY_FLAVOR, INVALID_RCU_FLAVOR }; diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 7120165a9342..c52cc4c064f9 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -872,6 +872,64 @@ static struct rcu_torture_ops tasks_rude_ops = { #endif // #else #ifdef CONFIG_TASKS_RUDE_RCU +#ifdef CONFIG_RCU_LAZY + +/* + * Definitions for lazy RCU torture testing. + */ +static unsigned long orig_jiffies_till_flush; + +static void rcu_sync_torture_init_lazy(void) +{ + rcu_sync_torture_init(); + + orig_jiffies_till_flush = rcu_lazy_get_jiffies_till_flush(); + rcu_lazy_set_jiffies_till_flush(50); +} + +static void rcu_lazy_cleanup(void) +{ + rcu_lazy_set_jiffies_till_flush(orig_jiffies_till_flush); +} + +static struct rcu_torture_ops rcu_lazy_ops = { + .ttype = RCU_LAZY_FLAVOR, + .init = rcu_sync_torture_init_lazy, + .cleanup = rcu_lazy_cleanup, + .readlock = rcu_torture_read_lock, + .read_delay = rcu_read_delay, + .readunlock = rcu_torture_read_unlock, + .readlock_held = torture_readlock_not_held, + .get_gp_seq = rcu_get_gp_seq, + .gp_diff = rcu_seq_diff, + .deferred_free = rcu_torture_deferred_free, + .sync = synchronize_rcu, + .exp_sync = synchronize_rcu_expedited, + .get_gp_state = get_state_synchronize_rcu, + .start_gp_poll = start_poll_synchronize_rcu, + .poll_gp_state = poll_state_synchronize_rcu, + .cond_sync = cond_synchronize_rcu, + .call = call_rcu_lazy, + .cb_barrier = rcu_barrier, + .fqs = rcu_force_quiescent_state, + .stats = NULL, + .gp_kthread_dbg = show_rcu_gp_kthreads, + .check_boost_failed = rcu_check_boost_fail, + .stall_dur = rcu_jiffies_till_stall_check, + .irq_capable = 1, + .can_boost = IS_ENABLED(CONFIG_RCU_BOOST), + .extendables = RCUTORTURE_MAX_EXTEND, + .name = "rcu_lazy" +}; + +#define LAZY_OPS &rcu_lazy_ops, + +#else // #ifdef CONFIG_RCU_LAZY + +#define LAZY_OPS + +#endif // #else #ifdef CONFIG_RCU_LAZY + #ifdef CONFIG_TASKS_TRACE_RCU @@ -3145,7 +3203,7 @@ rcu_torture_init(void) unsigned long gp_seq = 0; static struct rcu_torture_ops *torture_ops[] = { &rcu_ops, &rcu_busted_ops, &srcu_ops, &srcud_ops, &busted_srcud_ops, - TASKS_OPS TASKS_RUDE_OPS TASKS_TRACING_OPS + TASKS_OPS TASKS_RUDE_OPS TASKS_TRACING_OPS LAZY_OPS &trivial_ops, }; diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index cdbdd56e64b1..24ec925b2dfc 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -600,6 +600,7 @@ void rcutorture_get_gp_data(enum rcutorture_type test_type, int *flags, { switch (test_type) { case RCU_FLAVOR: + case RCU_LAZY_FLAVOR: *flags = READ_ONCE(rcu_state.gp_flags); *gp_seq = rcu_seq_current(&rcu_state.gp_seq); break; diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST index 98b6175e5aa0..609c3370616f 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST +++ b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST @@ -5,6 +5,7 @@ TREE04 TREE05 TREE07 TREE09 +TREE11 SRCU-N SRCU-P SRCU-T diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE11 b/tools/testing/selftests/rcutorture/configs/rcu/TREE11 new file mode 100644 index 000000000000..436013f3e015 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE11 @@ -0,0 +1,18 @@ +CONFIG_SMP=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y +#CHECK#CONFIG_PREEMPT_RCU=y +CONFIG_HZ_PERIODIC=n +CONFIG_NO_HZ_IDLE=y +CONFIG_NO_HZ_FULL=n +CONFIG_RCU_TRACE=y +CONFIG_HOTPLUG_CPU=y +CONFIG_MAXSMP=y +CONFIG_CPUMASK_OFFSTACK=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_DEBUG_LOCK_ALLOC=n +CONFIG_RCU_BOOST=n +CONFIG_DEBUG_OBJECTS_RCU_HEAD=n +CONFIG_RCU_EXPERT=y +CONFIG_RCU_LAZY=y diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE11.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE11.boot new file mode 100644 index 000000000000..9b6f720d4ccd --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE11.boot @@ -0,0 +1,8 @@ +maxcpus=8 nr_cpus=43 +rcutree.gp_preinit_delay=3 +rcutree.gp_init_delay=3 +rcutree.gp_cleanup_delay=3 +rcu_nocbs=0-7 +rcutorture.torture_type=rcu_lazy +rcutorture.nocbs_nthreads=8 +rcutorture.fwd_progress=0 -- 2.37.0.144.g8ac04bfd2-goog