diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-09-04 05:49:25 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-09-04 05:52:52 -0400 |
commit | d7ea17a76916e456fcc78e45142c66f7fb875e3d (patch) | |
tree | be8422a0c60216991ccd98923fe13547738ab354 /kernel/sched.c | |
parent | 18a3885fc1ffa92c2212ff0afdf033403d5b0fa0 (diff) |
sched: Fix dynamic power-balancing crash
This crash:
[ 1774.088275] divide error: 0000 [#1] SMP
[ 1774.100355] CPU 13
[ 1774.102498] Modules linked in:
[ 1774.105631] Pid: 30881, comm: hackbench Not tainted 2.6.31-rc8-tip-01308-g484d664-dirty #1629 X8DTN
[ 1774.114807] RIP: 0010:[<ffffffff81041c38>] [<ffffffff81041c38>]
sched_balance_self+0x19b/0x2d4
Triggers because update_group_power() modifies the sd tree and does
temporary calculations there - not considering that other CPUs
could observe intermediate values, such as the zero initial value.
Calculate it in a temporary variable instead. (we need no memory
barrier as these are all statistical values anyway)
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20090904092742.GA11014@elte.hu>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index b53785346850..796baf731976 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -3765,19 +3765,22 @@ static void update_group_power(struct sched_domain *sd, int cpu) | |||
3765 | { | 3765 | { |
3766 | struct sched_domain *child = sd->child; | 3766 | struct sched_domain *child = sd->child; |
3767 | struct sched_group *group, *sdg = sd->groups; | 3767 | struct sched_group *group, *sdg = sd->groups; |
3768 | unsigned long power; | ||
3768 | 3769 | ||
3769 | if (!child) { | 3770 | if (!child) { |
3770 | update_cpu_power(sd, cpu); | 3771 | update_cpu_power(sd, cpu); |
3771 | return; | 3772 | return; |
3772 | } | 3773 | } |
3773 | 3774 | ||
3774 | sdg->cpu_power = 0; | 3775 | power = 0; |
3775 | 3776 | ||
3776 | group = child->groups; | 3777 | group = child->groups; |
3777 | do { | 3778 | do { |
3778 | sdg->cpu_power += group->cpu_power; | 3779 | power += group->cpu_power; |
3779 | group = group->next; | 3780 | group = group->next; |
3780 | } while (group != child->groups); | 3781 | } while (group != child->groups); |
3782 | |||
3783 | sdg->cpu_power = power; | ||
3781 | } | 3784 | } |
3782 | 3785 | ||
3783 | /** | 3786 | /** |