aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched/fair.c
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2013-08-28 06:40:38 -0400
committerIngo Molnar <mingo@kernel.org>2013-09-12 13:14:45 -0400
commitc61037e905a5cb74c7d786c35ee2cdbab9ed63af (patch)
treeadb3eeb373d200bf18de15687692afc82f117747 /kernel/sched/fair.c
parentb37d931685b519cd61a67fbdfe5b04707eb76e32 (diff)
sched/fair: Fix the group_capacity computation
Do away with 'phantom' cores due to N*frac(smt_power) >= 1 by limiting the capacity to the actual number of cores. The assumption of 1 < smt_power < 2 is an actual requirement because of what SMT is so this should work regardless of the SMT implementation. It can still be defeated by creative use of cpu hotplug, but if you're one of those freaks, you get to live with it. Signed-off-by: Peter Zijlstra <peterz@infradead.org> Acked-by: Vincent Guittot <vincent.guitto@linaro.org> Link: http://lkml.kernel.org/n/tip-dczmbi8tfgixacg1ji2av1un@git.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched/fair.c')
-rw-r--r--kernel/sched/fair.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 218f9c5b08ce..51c5c3ee77e3 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4556,18 +4556,24 @@ static inline int sg_imbalanced(struct sched_group *group)
4556/* 4556/*
4557 * Compute the group capacity. 4557 * Compute the group capacity.
4558 * 4558 *
4559 * For now the capacity is simply the number of power units in the group_power. 4559 * Avoid the issue where N*frac(smt_power) >= 1 creates 'phantom' cores by
4560 * A power unit represents a full core. 4560 * first dividing out the smt factor and computing the actual number of cores
4561 * 4561 * and limit power unit capacity with that.
4562 * This has an issue where N*frac(smt_power) >= 1, in that case we'll see extra
4563 * 'cores' that aren't actually there.
4564 */ 4562 */
4565static inline int sg_capacity(struct lb_env *env, struct sched_group *group) 4563static inline int sg_capacity(struct lb_env *env, struct sched_group *group)
4566{ 4564{
4565 unsigned int capacity, smt, cpus;
4566 unsigned int power, power_orig;
4567
4568 power = group->sgp->power;
4569 power_orig = group->sgp->power_orig;
4570 cpus = group->group_weight;
4567 4571
4568 unsigned int power = group->sgp->power; 4572 /* smt := ceil(cpus / power), assumes: 1 < smt_power < 2 */
4569 unsigned int capacity = DIV_ROUND_CLOSEST(power, SCHED_POWER_SCALE); 4573 smt = DIV_ROUND_UP(SCHED_POWER_SCALE * cpus, power_orig);
4574 capacity = cpus / smt; /* cores */
4570 4575
4576 capacity = min_t(unsigned, capacity, DIV_ROUND_CLOSEST(power, SCHED_POWER_SCALE));
4571 if (!capacity) 4577 if (!capacity)
4572 capacity = fix_small_capacity(env->sd, group); 4578 capacity = fix_small_capacity(env->sd, group);
4573 4579