aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2018-03-02 19:35:27 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2018-05-15 13:27:29 -0400
commitcee4393989333795ae04dc9f3b83a578afe3fca6 (patch)
tree9b3afa8f132956c603f83a1fb098f8d30a81d7c1 /kernel
parent6fba2b3767ea6e3e1204855031492415cc4dce4f (diff)
rcu: Rename cond_resched_rcu_qs() to cond_resched_tasks_rcu_qs()
Commit e31d28b6ab8f ("trace: Eliminate cond_resched_rcu_qs() in favor of cond_resched()") substituted cond_resched() for the earlier call to cond_resched_rcu_qs(). However, the new-age cond_resched() does not do anything to help RCU-tasks grace periods because (1) RCU-tasks is only enabled when CONFIG_PREEMPT=y and (2) cond_resched() is a complete no-op when preemption is enabled. This situation results in hangs when running the trace benchmarks. A number of potential fixes were discussed on LKML (https://lkml.kernel.org/r/20180224151240.0d63a059@vmware.local.home), including making cond_resched() not be a no-op; making cond_resched() not be a no-op, but only when running tracing benchmarks; reverting the aforementioned commit (which works because cond_resched_rcu_qs() does provide an RCU-tasks quiescent state; and adding a call to the scheduler/RCU rcu_note_voluntary_context_switch() function. All were deemed unsatisfactory, either due to added cond_resched() overhead or due to magic functions inviting cargo culting. This commit renames cond_resched_rcu_qs() to cond_resched_tasks_rcu_qs(), which provides a clear hint as to what this function is doing and why and where it should be used, and then replaces the call to cond_resched() with cond_resched_tasks_rcu_qs() in the trace benchmark's benchmark_event_kthread() function. Reported-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Tested-by: Nicholas Piggin <npiggin@gmail.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/rcu/rcuperf.c2
-rw-r--r--kernel/rcu/tree.c20
-rw-r--r--kernel/rcu/tree_plugin.h4
-rw-r--r--kernel/rcu/update.c2
-rw-r--r--kernel/torture.c2
-rw-r--r--kernel/trace/trace_benchmark.c4
6 files changed, 17 insertions, 17 deletions
diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c
index 777e7a6a0292..e232846516b3 100644
--- a/kernel/rcu/rcuperf.c
+++ b/kernel/rcu/rcuperf.c
@@ -369,7 +369,7 @@ static bool __maybe_unused torturing_tasks(void)
369 */ 369 */
370static void rcu_perf_wait_shutdown(void) 370static void rcu_perf_wait_shutdown(void)
371{ 371{
372 cond_resched_rcu_qs(); 372 cond_resched_tasks_rcu_qs();
373 if (atomic_read(&n_rcu_perf_writer_finished) < nrealwriters) 373 if (atomic_read(&n_rcu_perf_writer_finished) < nrealwriters)
374 return; 374 return;
375 while (!torture_must_stop()) 375 while (!torture_must_stop())
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 2a734692a581..c4db0e20b035 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -1234,10 +1234,10 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
1234 } 1234 }
1235 1235
1236 /* 1236 /*
1237 * Has this CPU encountered a cond_resched_rcu_qs() since the 1237 * Has this CPU encountered a cond_resched() since the beginning
1238 * beginning of the grace period? For this to be the case, 1238 * of the grace period? For this to be the case, the CPU has to
1239 * the CPU has to have noticed the current grace period. This 1239 * have noticed the current grace period. This might not be the
1240 * might not be the case for nohz_full CPUs looping in the kernel. 1240 * case for nohz_full CPUs looping in the kernel.
1241 */ 1241 */
1242 jtsq = jiffies_till_sched_qs; 1242 jtsq = jiffies_till_sched_qs;
1243 ruqp = per_cpu_ptr(&rcu_dynticks.rcu_urgent_qs, rdp->cpu); 1243 ruqp = per_cpu_ptr(&rcu_dynticks.rcu_urgent_qs, rdp->cpu);
@@ -2049,7 +2049,7 @@ static bool rcu_gp_init(struct rcu_state *rsp)
2049 rnp->level, rnp->grplo, 2049 rnp->level, rnp->grplo,
2050 rnp->grphi, rnp->qsmask); 2050 rnp->grphi, rnp->qsmask);
2051 raw_spin_unlock_irq_rcu_node(rnp); 2051 raw_spin_unlock_irq_rcu_node(rnp);
2052 cond_resched_rcu_qs(); 2052 cond_resched_tasks_rcu_qs();
2053 WRITE_ONCE(rsp->gp_activity, jiffies); 2053 WRITE_ONCE(rsp->gp_activity, jiffies);
2054 } 2054 }
2055 2055
@@ -2151,7 +2151,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
2151 sq = rcu_nocb_gp_get(rnp); 2151 sq = rcu_nocb_gp_get(rnp);
2152 raw_spin_unlock_irq_rcu_node(rnp); 2152 raw_spin_unlock_irq_rcu_node(rnp);
2153 rcu_nocb_gp_cleanup(sq); 2153 rcu_nocb_gp_cleanup(sq);
2154 cond_resched_rcu_qs(); 2154 cond_resched_tasks_rcu_qs();
2155 WRITE_ONCE(rsp->gp_activity, jiffies); 2155 WRITE_ONCE(rsp->gp_activity, jiffies);
2156 rcu_gp_slow(rsp, gp_cleanup_delay); 2156 rcu_gp_slow(rsp, gp_cleanup_delay);
2157 } 2157 }
@@ -2202,7 +2202,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
2202 /* Locking provides needed memory barrier. */ 2202 /* Locking provides needed memory barrier. */
2203 if (rcu_gp_init(rsp)) 2203 if (rcu_gp_init(rsp))
2204 break; 2204 break;
2205 cond_resched_rcu_qs(); 2205 cond_resched_tasks_rcu_qs();
2206 WRITE_ONCE(rsp->gp_activity, jiffies); 2206 WRITE_ONCE(rsp->gp_activity, jiffies);
2207 WARN_ON(signal_pending(current)); 2207 WARN_ON(signal_pending(current));
2208 trace_rcu_grace_period(rsp->name, 2208 trace_rcu_grace_period(rsp->name,
@@ -2247,7 +2247,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
2247 trace_rcu_grace_period(rsp->name, 2247 trace_rcu_grace_period(rsp->name,
2248 READ_ONCE(rsp->gpnum), 2248 READ_ONCE(rsp->gpnum),
2249 TPS("fqsend")); 2249 TPS("fqsend"));
2250 cond_resched_rcu_qs(); 2250 cond_resched_tasks_rcu_qs();
2251 WRITE_ONCE(rsp->gp_activity, jiffies); 2251 WRITE_ONCE(rsp->gp_activity, jiffies);
2252 ret = 0; /* Force full wait till next FQS. */ 2252 ret = 0; /* Force full wait till next FQS. */
2253 j = jiffies_till_next_fqs; 2253 j = jiffies_till_next_fqs;
@@ -2260,7 +2260,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
2260 } 2260 }
2261 } else { 2261 } else {
2262 /* Deal with stray signal. */ 2262 /* Deal with stray signal. */
2263 cond_resched_rcu_qs(); 2263 cond_resched_tasks_rcu_qs();
2264 WRITE_ONCE(rsp->gp_activity, jiffies); 2264 WRITE_ONCE(rsp->gp_activity, jiffies);
2265 WARN_ON(signal_pending(current)); 2265 WARN_ON(signal_pending(current));
2266 trace_rcu_grace_period(rsp->name, 2266 trace_rcu_grace_period(rsp->name,
@@ -2782,7 +2782,7 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *rsp))
2782 struct rcu_node *rnp; 2782 struct rcu_node *rnp;
2783 2783
2784 rcu_for_each_leaf_node(rsp, rnp) { 2784 rcu_for_each_leaf_node(rsp, rnp) {
2785 cond_resched_rcu_qs(); 2785 cond_resched_tasks_rcu_qs();
2786 mask = 0; 2786 mask = 0;
2787 raw_spin_lock_irqsave_rcu_node(rnp, flags); 2787 raw_spin_lock_irqsave_rcu_node(rnp, flags);
2788 if (rnp->qsmask == 0) { 2788 if (rnp->qsmask == 0) {
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 12774c4fb546..dfc42c3d52d4 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -1598,7 +1598,7 @@ static int rcu_oom_notify(struct notifier_block *self,
1598 1598
1599 for_each_online_cpu(cpu) { 1599 for_each_online_cpu(cpu) {
1600 smp_call_function_single(cpu, rcu_oom_notify_cpu, NULL, 1); 1600 smp_call_function_single(cpu, rcu_oom_notify_cpu, NULL, 1);
1601 cond_resched_rcu_qs(); 1601 cond_resched_tasks_rcu_qs();
1602 } 1602 }
1603 1603
1604 /* Unconditionally decrement: no need to wake ourselves up. */ 1604 /* Unconditionally decrement: no need to wake ourselves up. */
@@ -2227,7 +2227,7 @@ static int rcu_nocb_kthread(void *arg)
2227 cl++; 2227 cl++;
2228 c++; 2228 c++;
2229 local_bh_enable(); 2229 local_bh_enable();
2230 cond_resched_rcu_qs(); 2230 cond_resched_tasks_rcu_qs();
2231 list = next; 2231 list = next;
2232 } 2232 }
2233 trace_rcu_batch_end(rdp->rsp->name, c, !!list, 0, 0, 1); 2233 trace_rcu_batch_end(rdp->rsp->name, c, !!list, 0, 0, 1);
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
index 68fa19a5e7bd..e401960c7f51 100644
--- a/kernel/rcu/update.c
+++ b/kernel/rcu/update.c
@@ -624,7 +624,7 @@ EXPORT_SYMBOL_GPL(call_rcu_tasks);
624 * grace period has elapsed, in other words after all currently 624 * grace period has elapsed, in other words after all currently
625 * executing rcu-tasks read-side critical sections have elapsed. These 625 * executing rcu-tasks read-side critical sections have elapsed. These
626 * read-side critical sections are delimited by calls to schedule(), 626 * read-side critical sections are delimited by calls to schedule(),
627 * cond_resched_rcu_qs(), idle execution, userspace execution, calls 627 * cond_resched_tasks_rcu_qs(), idle execution, userspace execution, calls
628 * to synchronize_rcu_tasks(), and (in theory, anyway) cond_resched(). 628 * to synchronize_rcu_tasks(), and (in theory, anyway) cond_resched().
629 * 629 *
630 * This is a very specialized primitive, intended only for a few uses in 630 * This is a very specialized primitive, intended only for a few uses in
diff --git a/kernel/torture.c b/kernel/torture.c
index 37b94012a3f8..3de1efbecd6a 100644
--- a/kernel/torture.c
+++ b/kernel/torture.c
@@ -574,7 +574,7 @@ void stutter_wait(const char *title)
574{ 574{
575 int spt; 575 int spt;
576 576
577 cond_resched_rcu_qs(); 577 cond_resched_tasks_rcu_qs();
578 spt = READ_ONCE(stutter_pause_test); 578 spt = READ_ONCE(stutter_pause_test);
579 for (; spt; spt = READ_ONCE(stutter_pause_test)) { 579 for (; spt; spt = READ_ONCE(stutter_pause_test)) {
580 if (spt == 1) { 580 if (spt == 1) {
diff --git a/kernel/trace/trace_benchmark.c b/kernel/trace/trace_benchmark.c
index 22fee766081b..80e0b2aca703 100644
--- a/kernel/trace/trace_benchmark.c
+++ b/kernel/trace/trace_benchmark.c
@@ -159,13 +159,13 @@ static int benchmark_event_kthread(void *arg)
159 * wants to run, schedule in, but if the CPU is idle, 159 * wants to run, schedule in, but if the CPU is idle,
160 * we'll keep burning cycles. 160 * we'll keep burning cycles.
161 * 161 *
162 * Note the _rcu_qs() version of cond_resched() will 162 * Note the tasks_rcu_qs() version of cond_resched() will
163 * notify synchronize_rcu_tasks() that this thread has 163 * notify synchronize_rcu_tasks() that this thread has
164 * passed a quiescent state for rcu_tasks. Otherwise 164 * passed a quiescent state for rcu_tasks. Otherwise
165 * this thread will never voluntarily schedule which would 165 * this thread will never voluntarily schedule which would
166 * block synchronize_rcu_tasks() indefinitely. 166 * block synchronize_rcu_tasks() indefinitely.
167 */ 167 */
168 cond_resched(); 168 cond_resched_tasks_rcu_qs();
169 } 169 }
170 170
171 return 0; 171 return 0;