diff options
| author | Ingo Molnar <mingo@kernel.org> | 2012-09-25 03:30:58 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2012-09-26 03:46:10 -0400 |
| commit | a9b86fab4b0a36fc4cd2712a07259c2c0e769742 (patch) | |
| tree | e4db58440018a52089e8d6b39160f753ab10df99 /kernel/rcutiny.c | |
| parent | 9b20aa63b8fc9a6a3b6831f4eae3621755e51211 (diff) | |
| parent | 593d1006cdf710ab3469c0c37c184fea0bc3da97 (diff) | |
Merge branch 'rcu/next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu into core/rcu
Pull v3.7 RCU commits from Paul E. McKenney:
"
0. A fix for a latent bug that has been in RCU ever since the
addition of CPU stall warnings. This bug results in
false-positive stall warnings, but thus far only on embedded
systems with severely cut-down userspace configurations.
This fix is located on an rcu/urgent branch, with the rest
of the commits based on top of it. This commit CCs stable.
Given that the merge window is coming quite soon and given
the small number of affected users, I do -not- recommend
pushing it to 3.6, but the separate branch makes it easy to
find if someone needs it.
1. Further reductions in latency spikes for huge systems, along
with additional boot-time adaptation to the actual hardware.
This is a large change, as it moves RCU grace-period
initialization and cleanup, along with quiescent-state forcing,
from softirq to a kthread. However, it appears to be in
quite good shape (famous last words). Posted to LKML at
https://lkml.org/lkml/2012/9/20/427.
2. Updates to documentation and rcutorture, the latter category
including keeping statistics on CPU-hotplug latencies and
fixing some initialization-time races. Posted to LKML at
https://lkml.org/lkml/2012/8/30/193.
3. Miscellaneous fixes and improvements, posted to LKML at
https://lkml.org/lkml/2012/8/30/199.
4. CPU-hotplug fixes and improvements, posted to LKML at
https://lkml.org/lkml/2012/8/30/292 for first three and at
https://lkml.org/lkml/2012/8/3/416.
5. Idle-loop fixes that were omitted on an earlier submission,
posted to LKML at https://lkml.org/lkml/2012/8/30/251.
"
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/rcutiny.c')
| -rw-r--r-- | kernel/rcutiny.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index 547b1fe5b052..e4c6a598d6f7 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c | |||
| @@ -56,25 +56,28 @@ static void __call_rcu(struct rcu_head *head, | |||
| 56 | static long long rcu_dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; | 56 | static long long rcu_dynticks_nesting = DYNTICK_TASK_EXIT_IDLE; |
| 57 | 57 | ||
| 58 | /* Common code for rcu_idle_enter() and rcu_irq_exit(), see kernel/rcutree.c. */ | 58 | /* Common code for rcu_idle_enter() and rcu_irq_exit(), see kernel/rcutree.c. */ |
| 59 | static void rcu_idle_enter_common(long long oldval) | 59 | static void rcu_idle_enter_common(long long newval) |
| 60 | { | 60 | { |
| 61 | if (rcu_dynticks_nesting) { | 61 | if (newval) { |
| 62 | RCU_TRACE(trace_rcu_dyntick("--=", | 62 | RCU_TRACE(trace_rcu_dyntick("--=", |
| 63 | oldval, rcu_dynticks_nesting)); | 63 | rcu_dynticks_nesting, newval)); |
| 64 | rcu_dynticks_nesting = newval; | ||
| 64 | return; | 65 | return; |
| 65 | } | 66 | } |
| 66 | RCU_TRACE(trace_rcu_dyntick("Start", oldval, rcu_dynticks_nesting)); | 67 | RCU_TRACE(trace_rcu_dyntick("Start", rcu_dynticks_nesting, newval)); |
| 67 | if (!is_idle_task(current)) { | 68 | if (!is_idle_task(current)) { |
| 68 | struct task_struct *idle = idle_task(smp_processor_id()); | 69 | struct task_struct *idle = idle_task(smp_processor_id()); |
| 69 | 70 | ||
| 70 | RCU_TRACE(trace_rcu_dyntick("Error on entry: not idle task", | 71 | RCU_TRACE(trace_rcu_dyntick("Error on entry: not idle task", |
| 71 | oldval, rcu_dynticks_nesting)); | 72 | rcu_dynticks_nesting, newval)); |
| 72 | ftrace_dump(DUMP_ALL); | 73 | ftrace_dump(DUMP_ALL); |
| 73 | WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s", | 74 | WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s", |
| 74 | current->pid, current->comm, | 75 | current->pid, current->comm, |
| 75 | idle->pid, idle->comm); /* must be idle task! */ | 76 | idle->pid, idle->comm); /* must be idle task! */ |
| 76 | } | 77 | } |
| 77 | rcu_sched_qs(0); /* implies rcu_bh_qsctr_inc(0) */ | 78 | rcu_sched_qs(0); /* implies rcu_bh_qsctr_inc(0) */ |
| 79 | barrier(); | ||
| 80 | rcu_dynticks_nesting = newval; | ||
| 78 | } | 81 | } |
| 79 | 82 | ||
| 80 | /* | 83 | /* |
| @@ -84,17 +87,16 @@ static void rcu_idle_enter_common(long long oldval) | |||
| 84 | void rcu_idle_enter(void) | 87 | void rcu_idle_enter(void) |
| 85 | { | 88 | { |
| 86 | unsigned long flags; | 89 | unsigned long flags; |
| 87 | long long oldval; | 90 | long long newval; |
| 88 | 91 | ||
| 89 | local_irq_save(flags); | 92 | local_irq_save(flags); |
| 90 | oldval = rcu_dynticks_nesting; | ||
| 91 | WARN_ON_ONCE((rcu_dynticks_nesting & DYNTICK_TASK_NEST_MASK) == 0); | 93 | WARN_ON_ONCE((rcu_dynticks_nesting & DYNTICK_TASK_NEST_MASK) == 0); |
| 92 | if ((rcu_dynticks_nesting & DYNTICK_TASK_NEST_MASK) == | 94 | if ((rcu_dynticks_nesting & DYNTICK_TASK_NEST_MASK) == |
| 93 | DYNTICK_TASK_NEST_VALUE) | 95 | DYNTICK_TASK_NEST_VALUE) |
| 94 | rcu_dynticks_nesting = 0; | 96 | newval = 0; |
| 95 | else | 97 | else |
| 96 | rcu_dynticks_nesting -= DYNTICK_TASK_NEST_VALUE; | 98 | newval = rcu_dynticks_nesting - DYNTICK_TASK_NEST_VALUE; |
| 97 | rcu_idle_enter_common(oldval); | 99 | rcu_idle_enter_common(newval); |
| 98 | local_irq_restore(flags); | 100 | local_irq_restore(flags); |
| 99 | } | 101 | } |
| 100 | EXPORT_SYMBOL_GPL(rcu_idle_enter); | 102 | EXPORT_SYMBOL_GPL(rcu_idle_enter); |
| @@ -105,15 +107,15 @@ EXPORT_SYMBOL_GPL(rcu_idle_enter); | |||
| 105 | void rcu_irq_exit(void) | 107 | void rcu_irq_exit(void) |
| 106 | { | 108 | { |
| 107 | unsigned long flags; | 109 | unsigned long flags; |
| 108 | long long oldval; | 110 | long long newval; |
| 109 | 111 | ||
| 110 | local_irq_save(flags); | 112 | local_irq_save(flags); |
| 111 | oldval = rcu_dynticks_nesting; | 113 | newval = rcu_dynticks_nesting - 1; |
| 112 | rcu_dynticks_nesting--; | 114 | WARN_ON_ONCE(newval < 0); |
| 113 | WARN_ON_ONCE(rcu_dynticks_nesting < 0); | 115 | rcu_idle_enter_common(newval); |
| 114 | rcu_idle_enter_common(oldval); | ||
| 115 | local_irq_restore(flags); | 116 | local_irq_restore(flags); |
| 116 | } | 117 | } |
| 118 | EXPORT_SYMBOL_GPL(rcu_irq_exit); | ||
| 117 | 119 | ||
| 118 | /* Common code for rcu_idle_exit() and rcu_irq_enter(), see kernel/rcutree.c. */ | 120 | /* Common code for rcu_idle_exit() and rcu_irq_enter(), see kernel/rcutree.c. */ |
| 119 | static void rcu_idle_exit_common(long long oldval) | 121 | static void rcu_idle_exit_common(long long oldval) |
| @@ -171,6 +173,7 @@ void rcu_irq_enter(void) | |||
| 171 | rcu_idle_exit_common(oldval); | 173 | rcu_idle_exit_common(oldval); |
| 172 | local_irq_restore(flags); | 174 | local_irq_restore(flags); |
| 173 | } | 175 | } |
| 176 | EXPORT_SYMBOL_GPL(rcu_irq_enter); | ||
| 174 | 177 | ||
| 175 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 178 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 176 | 179 | ||
