aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcu/tree.c
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@kernel.org>2017-06-20 17:45:47 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2017-08-17 10:26:15 -0400
commitd5374226c3e444239e063f005dfb59cae4390db4 (patch)
tree7be03444d3973d1c42ad144704612b1bfbcafd98 /kernel/rcu/tree.c
parent352eee1242ef62e18a475ef9278697dbd865969b (diff)
rcu: Use idle versions of swait to make idle-hack clear
These RCU waits were set to use interruptible waits to avoid the kthreads contributing to system load average, even though they are not interruptible as they are spawned from a kthread. Use the new TASK_IDLE swaits which makes our goal clear, and removes confusion about these paths possibly being interruptible -- they are not. When the system is idle the RCU grace-period kthread will spend all its time blocked inside the swait_event_interruptible(). If the interruptible() was not used, then this kthread would contribute to the load average. This means that an idle system would have a load average of 2 (or 3 if PREEMPT=y), rather than the load average of 0 that almost fifty years of UNIX has conditioned sysadmins to expect. The same argument applies to swait_event_interruptible_timeout() use. The RCU grace-period kthread spends its time blocked inside this call while waiting for grace periods to complete. In particular, if there was only one busy CPU, but that CPU was frequently invoking call_rcu(), then the RCU grace-period kthread would spend almost all its time blocked inside the swait_event_interruptible_timeout(). This would mean that the load average would be 2 rather than the expected 1 for the single busy CPU. Acked-by: "Eric W. Biederman" <ebiederm@xmission.com> Tested-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcu/tree.c')
-rw-r--r--kernel/rcu/tree.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 51d4c3acf32d..2b13d9679f57 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -2067,8 +2067,8 @@ static bool rcu_gp_init(struct rcu_state *rsp)
2067} 2067}
2068 2068
2069/* 2069/*
2070 * Helper function for wait_event_interruptible_timeout() wakeup 2070 * Helper function for swait_event_idle() wakeup at force-quiescent-state
2071 * at force-quiescent-state time. 2071 * time.
2072 */ 2072 */
2073static bool rcu_gp_fqs_check_wake(struct rcu_state *rsp, int *gfp) 2073static bool rcu_gp_fqs_check_wake(struct rcu_state *rsp, int *gfp)
2074{ 2074{
@@ -2206,9 +2206,8 @@ static int __noreturn rcu_gp_kthread(void *arg)
2206 READ_ONCE(rsp->gpnum), 2206 READ_ONCE(rsp->gpnum),
2207 TPS("reqwait")); 2207 TPS("reqwait"));
2208 rsp->gp_state = RCU_GP_WAIT_GPS; 2208 rsp->gp_state = RCU_GP_WAIT_GPS;
2209 swait_event_interruptible(rsp->gp_wq, 2209 swait_event_idle(rsp->gp_wq, READ_ONCE(rsp->gp_flags) &
2210 READ_ONCE(rsp->gp_flags) & 2210 RCU_GP_FLAG_INIT);
2211 RCU_GP_FLAG_INIT);
2212 rsp->gp_state = RCU_GP_DONE_GPS; 2211 rsp->gp_state = RCU_GP_DONE_GPS;
2213 /* Locking provides needed memory barrier. */ 2212 /* Locking provides needed memory barrier. */
2214 if (rcu_gp_init(rsp)) 2213 if (rcu_gp_init(rsp))
@@ -2239,7 +2238,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
2239 READ_ONCE(rsp->gpnum), 2238 READ_ONCE(rsp->gpnum),
2240 TPS("fqswait")); 2239 TPS("fqswait"));
2241 rsp->gp_state = RCU_GP_WAIT_FQS; 2240 rsp->gp_state = RCU_GP_WAIT_FQS;
2242 ret = swait_event_interruptible_timeout(rsp->gp_wq, 2241 ret = swait_event_idle_timeout(rsp->gp_wq,
2243 rcu_gp_fqs_check_wake(rsp, &gf), j); 2242 rcu_gp_fqs_check_wake(rsp, &gf), j);
2244 rsp->gp_state = RCU_GP_DOING_FQS; 2243 rsp->gp_state = RCU_GP_DOING_FQS;
2245 /* Locking provides needed memory barriers. */ 2244 /* Locking provides needed memory barriers. */