mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] rcu/nocb: Keep lazy timer intact on second lazy callback
@ 2026-11-15  2:07 Chris Wiseman
  2026-11-15  2:31 ` jfern
  0 siblings, 1 reply; 2+ messages in thread
From: Chris Wiseman @ 2026-11-15  2:07 UTC (permalink / raw)
  To: Frederic Weisbecker, Paul E. McKenney, Joel Fernandes,
	Joel Fernandes, Neeraj Upadhyay
  Cc: Uladzislau Rezki, Boqun Feng, Josh Triplett, Tze-nan Wu,
	Cheng-jui Wang, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan,
	Zqiang, rcu, linux-kernel, stable, Chris Wiseman

wake_nocb_gp_defer() checks waketype == RCU_NOCB_WAKE_LAZY and
rdp_gp->nocb_defer_wakeup == RCU_NOCB_WAKE_NOT in one if-statement.

When the first lazy call_rcu() in a NOCB group arms rdp_gp->nocb_timer
for the 10-second lazy flush delay and sets rdp_gp->nocb_defer_wakeup to
RCU_NOCB_WAKE_LAZY, the next CPU in the group that queues its first lazy
callback calls wake_nocb_gp_defer(rdp, RCU_NOCB_WAKE_LAZY, ...). Because
rdp_gp->nocb_defer_wakeup is no longer RCU_NOCB_WAKE_NOT, it misses the
first branch and falls into the else block for RCU_NOCB_WAKE, calling
mod_timer(&rdp_gp->nocb_timer, jiffies + 1) and resetting the 10-second
lazy timer down to 1 jiffy. The same fallthrough also shortens a pending
2-jiffy RCU_NOCB_WAKE_BYPASS timer to 1 jiffy.

Commit 3cb278e73be5 ("rcu: Make call_rcu() lazy to save power") wrote
this check against rdp->nocb_defer_wakeup, and commit 463d46044f04
("rcu: Fix delayed execution of hurry callbacks") switched it to
rdp_gp->nocb_defer_wakeup, which exposed the fallthrough across all CPUs
sharing rdp_gp.

Give waketype == RCU_NOCB_WAKE_LAZY its own branch and only arm
nocb_timer when rdp_gp->nocb_defer_wakeup is RCU_NOCB_WAKE_NOT.

Fixes: 3cb278e73be5 ("rcu: Make call_rcu() lazy to save power")
Fixes: 463d46044f04 ("rcu: Fix delayed execution of hurry callbacks")
Cc: stable@vger.kernel.org
Signed-off-by: Chris Wiseman <chriswiseman@google.com>
---
 kernel/rcu/tree_nocb.h | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h
index b6cfee4e5039..347d718befd0 100644
--- a/kernel/rcu/tree_nocb.h
+++ b/kernel/rcu/tree_nocb.h
@@ -335,10 +335,12 @@ static void wake_nocb_gp_defer(struct rcu_data *rdp, int waketype,
 	 * Bypass wakeup overrides previous deferments. In case of
 	 * callback storms, no need to wake up too early.
 	 */
-	if (waketype == RCU_NOCB_WAKE_LAZY &&
-	    rdp_gp->nocb_defer_wakeup == RCU_NOCB_WAKE_NOT) {
-		mod_timer(&rdp_gp->nocb_timer, jiffies + rcu_get_jiffies_lazy_flush());
-		WRITE_ONCE(rdp_gp->nocb_defer_wakeup, waketype);
+	if (waketype == RCU_NOCB_WAKE_LAZY) {
+		if (rdp_gp->nocb_defer_wakeup == RCU_NOCB_WAKE_NOT) {
+			mod_timer(&rdp_gp->nocb_timer,
+				  jiffies + rcu_get_jiffies_lazy_flush());
+			WRITE_ONCE(rdp_gp->nocb_defer_wakeup, waketype);
+		}
 	} else if (waketype == RCU_NOCB_WAKE_BYPASS) {
 		mod_timer(&rdp_gp->nocb_timer, jiffies + 2);
 		WRITE_ONCE(rdp_gp->nocb_defer_wakeup, waketype);
-- 
2.52.0.rc1

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] rcu/nocb: Keep lazy timer intact on second lazy callback
  2026-11-15  2:07 [PATCH] rcu/nocb: Keep lazy timer intact on second lazy callback Chris Wiseman
@ 2026-11-15  2:31 ` jfern
  0 siblings, 0 replies; 2+ messages in thread
From: jfern @ 2026-11-15  2:31 UTC (permalink / raw)
  To: Chris Wiseman
  Cc: Frederic Weisbecker, Paul E. McKenney, Joel Fernandes,
	Joel Fernandes, Neeraj Upadhyay, Uladzislau Rezki, Boqun Feng,
	Josh Triplett, Tze-nan Wu, Cheng-jui Wang, Steven Rostedt,
	Mathieu Desnoyers, Lai Jiangshan, Zqiang, rcu, linux-kernel,
	stable

On chriswiseman@google.com wrote:
> wake_nocb_gp_defer() checks waketype == RCU_NOCB_WAKE_LAZY and
> rdp_gp->nocb_defer_wakeup == RCU_NOCB_WAKE_NOT in one if-statement.
> 
> When the first lazy call_rcu() in a NOCB group arms rdp_gp->nocb_timer
> for the 10-second lazy flush delay and sets rdp_gp->nocb_defer_wakeup to
> RCU_NOCB_WAKE_LAZY, the next CPU in the group that queues its first lazy
> callback calls wake_nocb_gp_defer(rdp, RCU_NOCB_WAKE_LAZY, ...). Because
> rdp_gp->nocb_defer_wakeup is no longer RCU_NOCB_WAKE_NOT, it misses the
> first branch and falls into the else block for RCU_NOCB_WAKE, calling
> mod_timer(&rdp_gp->nocb_timer, jiffies + 1) and resetting the 10-second
> lazy timer down to 1 jiffy. The same fallthrough also shortens a pending
> 2-jiffy RCU_NOCB_WAKE_BYPASS timer to 1 jiffy.
> 
> Commit 3cb278e73be5 ("rcu: Make call_rcu() lazy to save power") wrote
> this check against rdp->nocb_defer_wakeup, and commit 463d46044f04
> ("rcu: Fix delayed execution of hurry callbacks") switched it to
> rdp_gp->nocb_defer_wakeup, which exposed the fallthrough across all CPUs
> sharing rdp_gp.
> 
> Give waketype == RCU_NOCB_WAKE_LAZY its own branch and only arm
> nocb_timer when rdp_gp->nocb_defer_wakeup is RCU_NOCB_WAKE_NOT.
> 
> Fixes: 3cb278e73be5 ("rcu: Make call_rcu() lazy to save power")
> Fixes: 463d46044f04 ("rcu: Fix delayed execution of hurry callbacks")
> Cc: stable@vger.kernel.org
> Signed-off-by: Chris Wiseman <chriswiseman@google.com>

Looks reasonable to me. Is there a test case that you added to find this, or any
power savings that you found with this added patch?

thanks,

Joel Fernandes

> ---
>  kernel/rcu/tree_nocb.h | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h
> index b6cfee4e5039..347d718befd0 100644
> --- a/kernel/rcu/tree_nocb.h
> +++ b/kernel/rcu/tree_nocb.h
> @@ -335,10 +335,12 @@ static void wake_nocb_gp_defer(struct rcu_data *rdp, int waketype,
>  	 * Bypass wakeup overrides previous deferments. In case of
>  	 * callback storms, no need to wake up too early.
>  	 */
> -	if (waketype == RCU_NOCB_WAKE_LAZY &&
> -	    rdp_gp->nocb_defer_wakeup == RCU_NOCB_WAKE_NOT) {
> -		mod_timer(&rdp_gp->nocb_timer, jiffies + rcu_get_jiffies_lazy_flush());
> -		WRITE_ONCE(rdp_gp->nocb_defer_wakeup, waketype);
> +	if (waketype == RCU_NOCB_WAKE_LAZY) {
> +		if (rdp_gp->nocb_defer_wakeup == RCU_NOCB_WAKE_NOT) {
> +			mod_timer(&rdp_gp->nocb_timer,
> +				  jiffies + rcu_get_jiffies_lazy_flush());
> +			WRITE_ONCE(rdp_gp->nocb_defer_wakeup, waketype);
> +		}
>  	} else if (waketype == RCU_NOCB_WAKE_BYPASS) {
>  		mod_timer(&rdp_gp->nocb_timer, jiffies + 2);
>  		WRITE_ONCE(rdp_gp->nocb_defer_wakeup, waketype);
> -- 
> 2.52.0.rc1

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-15  2:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-15  2:07 [PATCH] rcu/nocb: Keep lazy timer intact on second lazy callback Chris Wiseman
2026-11-15  2:31 ` jfern

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®