diff options
author | Paul E. McKenney <paulmck@linux.ibm.com> | 2019-07-16 05:17:00 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.ibm.com> | 2019-08-13 17:38:24 -0400 |
commit | f48fe4c586604c3a09938c6a6e9fd3356dfe8f3c (patch) | |
tree | 011d5815d8de824c08a4d9aade25b9e01e6f78bc | |
parent | 296181d78df9892e08e794f2a9a4d2c38f9acedb (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.h | 7 |
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 | ||