This is useful to check for any improvements or degradation related to number of GP kthread wakeups during testing. Signed-off-by: Joel Fernandes (Google) <joel@xxxxxxxxxxxxxxxxx> --- kernel/rcu/Kconfig.debug | 1 + kernel/rcu/rcu.h | 2 ++ kernel/rcu/rcutorture.c | 23 ++++++++++++++++++++++- kernel/rcu/tree.c | 7 +++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/kernel/rcu/Kconfig.debug b/kernel/rcu/Kconfig.debug index 3cf6132a4bb9f..3323e3378af5a 100644 --- a/kernel/rcu/Kconfig.debug +++ b/kernel/rcu/Kconfig.debug @@ -50,6 +50,7 @@ config RCU_TORTURE_TEST select TASKS_RCU select TASKS_RUDE_RCU select TASKS_TRACE_RCU + select SCHEDSTATS default n help This option provides a kernel module that runs torture tests diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h index cf66a3ccd7573..7e867e81d9738 100644 --- a/kernel/rcu/rcu.h +++ b/kernel/rcu/rcu.h @@ -511,6 +511,7 @@ srcu_batches_completed(struct srcu_struct *sp) { return 0; } static inline void rcu_force_quiescent_state(void) { } static inline void show_rcu_gp_kthreads(void) { } static inline int rcu_get_gp_kthreads_prio(void) { return 0; } +static inline struct task_struct *rcu_get_main_gp_kthread(void) { return 0; } static inline void rcu_fwd_progress_check(unsigned long j) { } #else /* #ifdef CONFIG_TINY_RCU */ bool rcu_dynticks_zero_in_eqs(int cpu, int *vp); @@ -519,6 +520,7 @@ unsigned long rcu_exp_batches_completed(void); unsigned long srcu_batches_completed(struct srcu_struct *sp); void show_rcu_gp_kthreads(void); int rcu_get_gp_kthreads_prio(void); +struct task_struct *rcu_get_main_gp_kthread(void); void rcu_fwd_progress_check(unsigned long j); void rcu_force_quiescent_state(void); extern struct workqueue_struct *rcu_gp_wq; diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index d0d265304d147..959a1f84d6904 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -23,6 +23,7 @@ #include <linux/rcupdate_wait.h> #include <linux/interrupt.h> #include <linux/sched/signal.h> +#include <linux/sched/stat.h> #include <uapi/linux/sched/types.h> #include <linux/atomic.h> #include <linux/bitops.h> @@ -460,9 +461,29 @@ static void rcu_sync_torture_init(void) INIT_LIST_HEAD(&rcu_torture_removed); } +unsigned long rcu_gp_nr_wakeups; + +static void rcu_flavor_init(void) +{ + rcu_sync_torture_init(); + + /* Make sure schedstat is enabled for GP thread wakeup count. */ + force_schedstat_enabled(); + rcu_gp_nr_wakeups = rcu_get_main_gp_kthread()->se.statistics.nr_wakeups; +} + +static void rcu_flavor_cleanup(void) +{ + unsigned long now_nr = rcu_get_main_gp_kthread()->se.statistics.nr_wakeups; + + pr_alert("End-test: Cleanup: Total GP-kthread wakeups: %lu\n", + now_nr - rcu_gp_nr_wakeups); +} + static struct rcu_torture_ops rcu_ops = { .ttype = RCU_FLAVOR, - .init = rcu_sync_torture_init, + .init = rcu_flavor_init, + .cleanup = rcu_flavor_cleanup, .readlock = rcu_torture_read_lock, .read_delay = rcu_read_delay, .readunlock = rcu_torture_read_unlock, diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index c3bae7a83d792..a3a175feb310a 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -175,6 +175,13 @@ int rcu_get_gp_kthreads_prio(void) } EXPORT_SYMBOL_GPL(rcu_get_gp_kthreads_prio); +/* Retrieve RCU's main GP kthread task_struct */ +struct task_struct *rcu_get_main_gp_kthread(void) +{ + return rcu_state.gp_kthread; +} +EXPORT_SYMBOL_GPL(rcu_get_main_gp_kthread); + /* * Number of grace periods between delays, normalized by the duration of * the delay. The longer the delay, the more the grace periods between -- 2.27.0.111.gc72c7da667-goog