On Tue, Sep 06, 2022 at 03:07:05AM +0000, Joel Fernandes wrote: > On Thu, Sep 01, 2022 at 10:17:06PM +0000, Joel Fernandes (Google) wrote: > From: "Joel Fernandes (Google)" <joel@xxxxxxxxxxxxxxxxx> > Subject: [PATCH v6] rcu: Fix late wakeup when flush of bypass cblist happens > > When the bypass cblist gets too big or its timeout has occurred, it is > flushed into the main cblist. However, the bypass timer is still running > and the behavior is that it would eventually expire and wake the GP > thread. > > Since we are going to use the bypass cblist for lazy CBs, do the wakeup > soon as the flush happens. Otherwise, the lazy-timer will go off much > later and the now-non-lazy cblist CBs can get stranded for the duration > of the timer. > > This is a good thing to do anyway (regardless of this series), since it > makes the behavior consistent with behavior of other code paths where queueing > something into the ->cblist makes the GP kthread in a non-sleeping state > quickly. > > [ Frederic Weisbec: changes to not do wake up GP thread unless needed ]. > > Signed-off-by: Joel Fernandes (Google) <joel@xxxxxxxxxxxxxxxxx> > --- > kernel/rcu/tree_nocb.h | 11 +++++++++-- > 1 file changed, 9 insertions(+), 2 deletions(-) > > diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h > index 0a5f0ef41484..4dc86274b3e8 100644 > --- a/kernel/rcu/tree_nocb.h > +++ b/kernel/rcu/tree_nocb.h > @@ -433,8 +433,9 @@ static bool rcu_nocb_try_bypass(struct rcu_data *rdp, struct rcu_head *rhp, > if ((ncbs && j != READ_ONCE(rdp->nocb_bypass_first)) || > ncbs >= qhimark) { > rcu_nocb_lock(rdp); > + *was_alldone = !rcu_segcblist_pend_cbs(&rdp->cblist); > + > if (!rcu_nocb_flush_bypass(rdp, rhp, j)) { > - *was_alldone = !rcu_segcblist_pend_cbs(&rdp->cblist); > if (*was_alldone) > trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, > TPS("FirstQ")); > @@ -447,7 +448,13 @@ static bool rcu_nocb_try_bypass(struct rcu_data *rdp, struct rcu_head *rhp, > rcu_advance_cbs_nowake(rdp->mynode, rdp); > rdp->nocb_gp_adv_time = j; > } > - rcu_nocb_unlock_irqrestore(rdp, flags); > + > + // The flush succeeded and we moved CBs into the ->cblist. > + // However, the bypass timer might still be running. Wakeup the That part of the comment mentioning the bypass timer looks strange... > + // GP thread by calling a helper with was_all_done set so that > + // wake up happens (needed if main CB list was empty before). How about: // The flush succeeded and we moved CBs into the regular list. // Don't wait for the wake up timer as it may be too far ahead. // Wake up now GP thread instead if the cblist was empty Thanks. Other than that the patch looks good, thanks! > + __call_rcu_nocb_wake(rdp, *was_alldone, flags); > + > return true; // Callback already enqueued. > } > > -- > 2.37.2.789.g6183377224-goog >