diff options
| author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2018-03-02 19:35:27 -0500 |
|---|---|---|
| committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2018-05-15 13:27:29 -0400 |
| commit | cee4393989333795ae04dc9f3b83a578afe3fca6 (patch) | |
| tree | 9b3afa8f132956c603f83a1fb098f8d30a81d7c1 /kernel | |
| parent | 6fba2b3767ea6e3e1204855031492415cc4dce4f (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.c | 2 | ||||
| -rw-r--r-- | kernel/rcu/tree.c | 20 | ||||
| -rw-r--r-- | kernel/rcu/tree_plugin.h | 4 | ||||
| -rw-r--r-- | kernel/rcu/update.c | 2 | ||||
| -rw-r--r-- | kernel/torture.c | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_benchmark.c | 4 |
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 | */ |
| 370 | static void rcu_perf_wait_shutdown(void) | 370 | static 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; |
