In non-preemptible kernels, a Tiny SRCU grace period implies an RCU grace period because any context switch suffices. But in preemptible kernels, it is possible for a Tiny SRCU grace period to elapse without a corresponding RCU grace period.
Which was OK until RCU Tasks Trace was re-implemented in terms of SRCU-fast, which in Tiny SRCU is implemented as SRCU, which is already fast. And RCU Tasks Trace grace periods are required to imply RCU grace periods. This commit therefore adds a synchronize_rcu(), but only in preemptible kernels. Because preemptible Tiny SRCU is not in mainline, this added call to synchronize_rcu() will not slow anything down: The comparison would instead be with TREE SRCU. But if this added call ever becomes a problem, the Tiny SRCU srcu_struct structure could track whether or not this is for SRCU-fast, and to add the synchronize_rcu() only in the SRCU-fast case. However, at the moment, this is seen as unnecessary complexity. Signed-off-by: Paul E. McKenney <[email protected]> --- kernel/rcu/srcutiny.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c index 5de9a6905838..32b37d63d58a 100644 --- a/kernel/rcu/srcutiny.c +++ b/kernel/rcu/srcutiny.c @@ -159,6 +159,8 @@ void srcu_drive_gp(struct work_struct *wp) WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1); WRITE_ONCE(ssp->srcu_gp_waiting, true); /* srcu_read_unlock() wakes! */ preempt_enable(); + if (IS_ENABLED(CONFIG_PREEMPTION)) + synchronize_rcu(); // Needed for RCU Tasks Trace to imply RCU grace period do { // Deadlock issues prevent __srcu_read_unlock() from // doing an unconditional wakeup, so polling is required. -- 2.40.1

