summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.ibm.com>2019-07-16 05:17:00 -0400
committerPaul E. McKenney <paulmck@linux.ibm.com>2019-08-13 17:38:24 -0400
commitf48fe4c586604c3a09938c6a6e9fd3356dfe8f3c (patch)
tree011d5815d8de824c08a4d9aade25b9e01e6f78bc
parent296181d78df9892e08e794f2a9a4d2c38f9acedb (diff)
rcu/nocb: Don't wake no-CBs GP kthread if timer posted under overload
When under overload conditions, __call_rcu_nocb_wake() will wake the no-CBs GP kthread any time the no-CBs CB kthread is asleep or there are no ready-to-invoke callbacks, but only after a timer delay. If the no-CBs GP kthread has a ->nocb_bypass_timer pending, the deferred wakeup from __call_rcu_nocb_wake() is redundant. This commit therefore makes __call_rcu_nocb_wake() avoid posting the redundant deferred wakeup if ->nocb_bypass_timer is pending. This requires adding a bit of ordering of timer actions. Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>
-rw-r--r--kernel/rcu/tree_plugin.h7
1 files changed, 5 insertions, 2 deletions
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index f56fb4e97a8e..2defc7fe74c3 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -1909,8 +1909,10 @@ static void __call_rcu_nocb_wake(struct rcu_data *rdp, bool was_alldone,
1909 rcu_advance_cbs_nowake(rdp->mynode, rdp); 1909 rcu_advance_cbs_nowake(rdp->mynode, rdp);
1910 rdp->nocb_gp_adv_time = j; 1910 rdp->nocb_gp_adv_time = j;
1911 } 1911 }
1912 if (rdp->nocb_cb_sleep || 1912 smp_mb(); /* Enqueue before timer_pending(). */
1913 !rcu_segcblist_ready_cbs(&rdp->cblist)) 1913 if ((rdp->nocb_cb_sleep ||
1914 !rcu_segcblist_ready_cbs(&rdp->cblist)) &&
1915 !timer_pending(&rdp->nocb_bypass_timer))
1914 wake_nocb_gp_defer(rdp, RCU_NOCB_WAKE_FORCE, 1916 wake_nocb_gp_defer(rdp, RCU_NOCB_WAKE_FORCE,
1915 TPS("WakeOvfIsDeferred")); 1917 TPS("WakeOvfIsDeferred"));
1916 rcu_nocb_unlock_irqrestore(rdp, flags); 1918 rcu_nocb_unlock_irqrestore(rdp, flags);
@@ -1929,6 +1931,7 @@ static void do_nocb_bypass_wakeup_timer(struct timer_list *t)
1929 1931
1930 trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("Timer")); 1932 trace_rcu_nocb_wake(rcu_state.name, rdp->cpu, TPS("Timer"));
1931 rcu_nocb_lock_irqsave(rdp, flags); 1933 rcu_nocb_lock_irqsave(rdp, flags);
1934 smp_mb__after_spinlock(); /* Timer expire before wakeup. */
1932 __call_rcu_nocb_wake(rdp, true, flags); 1935 __call_rcu_nocb_wake(rdp, true, flags);
1933} 1936}
1934 1937