diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-06-20 19:49:01 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-06-23 14:19:32 -0400 |
commit | 4a81e8328d3791a4f99bf5b436d050f6dc5ffea3 (patch) | |
tree | 9ffd05b47ffd38639ec904d3329eba1060d3acae /kernel/sched | |
parent | 546a9d8519ed137b2804a3f5a3659003039dd49c (diff) |
rcu: Reduce overhead of cond_resched() checks for RCU
Commit ac1bea85781e (Make cond_resched() report RCU quiescent states)
fixed a problem where a CPU looping in the kernel with but one runnable
task would give RCU CPU stall warnings, even if the in-kernel loop
contained cond_resched() calls. Unfortunately, in so doing, it introduced
performance regressions in Anton Blanchard's will-it-scale "open1" test.
The problem appears to be not so much the increased cond_resched() path
length as an increase in the rate at which grace periods complete, which
increased per-update grace-period overhead.
This commit takes a different approach to fixing this bug, mainly by
moving the RCU-visible quiescent state from cond_resched() to
rcu_note_context_switch(), and by further reducing the check to a
simple non-zero test of a single per-CPU variable. However, this
approach requires that the force-quiescent-state processing send
resched IPIs to the offending CPUs. These will be sent only once
the grace period has reached an age specified by the boot/sysfs
parameter rcutree.jiffies_till_sched_qs, or once the grace period
reaches an age halfway to the point at which RCU CPU stall warnings
will be emitted, whichever comes first.
Reported-by: Dave Hansen <dave.hansen@intel.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Christoph Lameter <cl@gentwo.org>
Cc: Mike Galbraith <umgwanakikbuti@gmail.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
[ paulmck: Made rcu_momentary_dyntick_idle() as suggested by the
ktest build robot. Also fixed smp_mb() comment as noted by
Oleg Nesterov. ]
Merge with e552592e (Reduce overhead of cond_resched() checks for RCU)
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/sched')
-rw-r--r-- | kernel/sched/core.c | 7 |
1 files changed, 1 insertions, 6 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 3bdf01b494fe..bc1638b33449 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -4147,7 +4147,6 @@ static void __cond_resched(void) | |||
4147 | 4147 | ||
4148 | int __sched _cond_resched(void) | 4148 | int __sched _cond_resched(void) |
4149 | { | 4149 | { |
4150 | rcu_cond_resched(); | ||
4151 | if (should_resched()) { | 4150 | if (should_resched()) { |
4152 | __cond_resched(); | 4151 | __cond_resched(); |
4153 | return 1; | 4152 | return 1; |
@@ -4166,18 +4165,15 @@ EXPORT_SYMBOL(_cond_resched); | |||
4166 | */ | 4165 | */ |
4167 | int __cond_resched_lock(spinlock_t *lock) | 4166 | int __cond_resched_lock(spinlock_t *lock) |
4168 | { | 4167 | { |
4169 | bool need_rcu_resched = rcu_should_resched(); | ||
4170 | int resched = should_resched(); | 4168 | int resched = should_resched(); |
4171 | int ret = 0; | 4169 | int ret = 0; |
4172 | 4170 | ||
4173 | lockdep_assert_held(lock); | 4171 | lockdep_assert_held(lock); |
4174 | 4172 | ||
4175 | if (spin_needbreak(lock) || resched || need_rcu_resched) { | 4173 | if (spin_needbreak(lock) || resched) { |
4176 | spin_unlock(lock); | 4174 | spin_unlock(lock); |
4177 | if (resched) | 4175 | if (resched) |
4178 | __cond_resched(); | 4176 | __cond_resched(); |
4179 | else if (unlikely(need_rcu_resched)) | ||
4180 | rcu_resched(); | ||
4181 | else | 4177 | else |
4182 | cpu_relax(); | 4178 | cpu_relax(); |
4183 | ret = 1; | 4179 | ret = 1; |
@@ -4191,7 +4187,6 @@ int __sched __cond_resched_softirq(void) | |||
4191 | { | 4187 | { |
4192 | BUG_ON(!in_softirq()); | 4188 | BUG_ON(!in_softirq()); |
4193 | 4189 | ||
4194 | rcu_cond_resched(); /* BH disabled OK, just recording QSes. */ | ||
4195 | if (should_resched()) { | 4190 | if (should_resched()) { |
4196 | local_bh_enable(); | 4191 | local_bh_enable(); |
4197 | __cond_resched(); | 4192 | __cond_resched(); |