aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcu/tree.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2016-11-30 09:24:30 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2017-10-09 17:25:17 -0400
commitf79c3ad6189624c3de0ad5521610c9e22a1c33cf (patch)
tree82bfe610ef11d2dbaf120f7ddbbc250ec4f917fb /kernel/rcu/tree.c
parent8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (diff)
sched,rcu: Make cond_resched() provide RCU quiescent state
There is some confusion as to which of cond_resched() or cond_resched_rcu_qs() should be added to long in-kernel loops. This commit therefore eliminates the decision by adding RCU quiescent states to cond_resched(). This commit also simplifies the code that used to interact with cond_resched_rcu_qs(), and that now interacts with cond_resched(), to reduce its overhead. This reduction is necessary to allow the heavier-weight cond_resched_rcu_qs() mechanism to be invoked everywhere that cond_resched() is invoked. Part of that reduction in overhead converts the jiffies_till_sched_qs kernel parameter to read-only at runtime, thus eliminating the need for bounds checking. Reported-by: Michal Hocko <mhocko@kernel.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> [ paulmck: Keep PREEMPT=n cond_resched a no-op, per Peter Zijlstra. ]
Diffstat (limited to 'kernel/rcu/tree.c')
-rw-r--r--kernel/rcu/tree.c25
1 files changed, 5 insertions, 20 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index b0ad62b0e7b8..0dda57a28276 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -534,8 +534,8 @@ module_param(rcu_kick_kthreads, bool, 0644);
534 * How long the grace period must be before we start recruiting 534 * How long the grace period must be before we start recruiting
535 * quiescent-state help from rcu_note_context_switch(). 535 * quiescent-state help from rcu_note_context_switch().
536 */ 536 */
537static ulong jiffies_till_sched_qs = HZ / 20; 537static ulong jiffies_till_sched_qs = HZ / 10;
538module_param(jiffies_till_sched_qs, ulong, 0644); 538module_param(jiffies_till_sched_qs, ulong, 0444);
539 539
540static bool rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp, 540static bool rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp,
541 struct rcu_data *rdp); 541 struct rcu_data *rdp);
@@ -1235,7 +1235,6 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
1235 unsigned long jtsq; 1235 unsigned long jtsq;
1236 bool *rnhqp; 1236 bool *rnhqp;
1237 bool *ruqp; 1237 bool *ruqp;
1238 unsigned long rjtsc;
1239 struct rcu_node *rnp; 1238 struct rcu_node *rnp;
1240 1239
1241 /* 1240 /*
@@ -1252,23 +1251,13 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
1252 return 1; 1251 return 1;
1253 } 1252 }
1254 1253
1255 /* Compute and saturate jiffies_till_sched_qs. */
1256 jtsq = jiffies_till_sched_qs;
1257 rjtsc = rcu_jiffies_till_stall_check();
1258 if (jtsq > rjtsc / 2) {
1259 WRITE_ONCE(jiffies_till_sched_qs, rjtsc);
1260 jtsq = rjtsc / 2;
1261 } else if (jtsq < 1) {
1262 WRITE_ONCE(jiffies_till_sched_qs, 1);
1263 jtsq = 1;
1264 }
1265
1266 /* 1254 /*
1267 * Has this CPU encountered a cond_resched_rcu_qs() since the 1255 * Has this CPU encountered a cond_resched_rcu_qs() since the
1268 * beginning of the grace period? For this to be the case, 1256 * beginning of the grace period? For this to be the case,
1269 * the CPU has to have noticed the current grace period. This 1257 * the CPU has to have noticed the current grace period. This
1270 * might not be the case for nohz_full CPUs looping in the kernel. 1258 * might not be the case for nohz_full CPUs looping in the kernel.
1271 */ 1259 */
1260 jtsq = jiffies_till_sched_qs;
1272 rnp = rdp->mynode; 1261 rnp = rdp->mynode;
1273 ruqp = per_cpu_ptr(&rcu_dynticks.rcu_urgent_qs, rdp->cpu); 1262 ruqp = per_cpu_ptr(&rcu_dynticks.rcu_urgent_qs, rdp->cpu);
1274 if (time_after(jiffies, rdp->rsp->gp_start + jtsq) && 1263 if (time_after(jiffies, rdp->rsp->gp_start + jtsq) &&
@@ -1276,7 +1265,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
1276 READ_ONCE(rdp->gpnum) == rnp->gpnum && !rdp->gpwrap) { 1265 READ_ONCE(rdp->gpnum) == rnp->gpnum && !rdp->gpwrap) {
1277 trace_rcu_fqs(rdp->rsp->name, rdp->gpnum, rdp->cpu, TPS("rqc")); 1266 trace_rcu_fqs(rdp->rsp->name, rdp->gpnum, rdp->cpu, TPS("rqc"));
1278 return 1; 1267 return 1;
1279 } else { 1268 } else if (time_after(jiffies, rdp->rsp->gp_start + jtsq)) {
1280 /* Load rcu_qs_ctr before store to rcu_urgent_qs. */ 1269 /* Load rcu_qs_ctr before store to rcu_urgent_qs. */
1281 smp_store_release(ruqp, true); 1270 smp_store_release(ruqp, true);
1282 } 1271 }
@@ -1304,10 +1293,6 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
1304 * updates are only once every few jiffies, the probability of 1293 * updates are only once every few jiffies, the probability of
1305 * lossage (and thus of slight grace-period extension) is 1294 * lossage (and thus of slight grace-period extension) is
1306 * quite low. 1295 * quite low.
1307 *
1308 * Note that if the jiffies_till_sched_qs boot/sysfs parameter
1309 * is set too high, we override with half of the RCU CPU stall
1310 * warning delay.
1311 */ 1296 */
1312 rnhqp = &per_cpu(rcu_dynticks.rcu_need_heavy_qs, rdp->cpu); 1297 rnhqp = &per_cpu(rcu_dynticks.rcu_need_heavy_qs, rdp->cpu);
1313 if (!READ_ONCE(*rnhqp) && 1298 if (!READ_ONCE(*rnhqp) &&
@@ -1316,7 +1301,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
1316 WRITE_ONCE(*rnhqp, true); 1301 WRITE_ONCE(*rnhqp, true);
1317 /* Store rcu_need_heavy_qs before rcu_urgent_qs. */ 1302 /* Store rcu_need_heavy_qs before rcu_urgent_qs. */
1318 smp_store_release(ruqp, true); 1303 smp_store_release(ruqp, true);
1319 rdp->rsp->jiffies_resched += 5; /* Re-enable beating. */ 1304 rdp->rsp->jiffies_resched += jtsq; /* Re-enable beating. */
1320 } 1305 }
1321 1306
1322 /* 1307 /*