On 18/03/14 12:48, Jon Medhurst (Tixy) wrote:
On Tue, 2014-03-18 at 11:29 +0000, Chris Redpath wrote:
When looking for a task to be idle-pulled, don't consider tasks where the affinity does not allow that task to be placed on the target CPU. Also ensure that tasks with restricted affinity do not block selecting other unrestricted busy tasks.
Use the knowledge of target CPU more effectively in idle pull by passing to hmp_get_heaviest_task when we know it, otherwise only checking for general affinity matches with any of the CPUs in the bigger HMP domain.
We still need to explicitly check affinity is allowed in idle pull since if we find no match in hmp_get_heaviest_task we will return the current one, which may not be affine to the new CPU despite having high enough load. In this case, there is nothing to move.
Signed-off-by: Chris Redpath chris.redpath@arm.com
kernel/sched/fair.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index b22906c..431c3c9 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3679,30 +3679,30 @@ static inline struct hmp_domain *hmp_faster_domain(int cpu);
/* must hold runqueue lock for queue se is currently on */ static struct sched_entity *hmp_get_heaviest_task(
struct sched_entity *se, int migrate_up)
{ int num_tasks = hmp_max_tasks; struct sched_entity *max_se = se; unsigned long int max_ratio = se->avg.load_avg_ratio; const struct cpumask *hmp_target_mask = NULL;struct sched_entity *se, int target_cpu)
- struct hmp_domain *hmp;
- if (migrate_up) {
struct hmp_domain *hmp;
if (hmp_cpu_is_fastest(cpu_of(se->cfs_rq->rq)))
return max_se;
- if (hmp_cpu_is_fastest(cpu_of(se->cfs_rq->rq)))
return max_se;
- hmp = hmp_faster_domain(cpu_of(se->cfs_rq->rq));
- hmp_target_mask = &hmp->cpus;
hmp = hmp_faster_domain(cpu_of(se->cfs_rq->rq));
hmp_target_mask = &hmp->cpus;
} /* The currently running task is not on the runqueue */ se = __pick_first_entity(cfs_rq_of(se));
while (num_tasks && se) { if (entity_is_task(se) &&
(se->avg.load_avg_ratio > max_ratio &&
hmp_target_mask &&
cpumask_intersects(hmp_target_mask,
tsk_cpus_allowed(task_of(se))))) {
se->avg.load_avg_ratio > max_ratio &&
cpumask_intersects(hmp_target_mask,
tsk_cpus_allowed(task_of(se))) &&
target_cpu > -1 ? cpumask_test_cpu(target_cpu,
tsk_cpus_allowed(task_of(se))) : 1) {
Instead of adding those two rather messy lines above, could we not instead just change the earlier setup of hmp_target_mask to only be the CPUs we want? E.g.
if (target_cpu >= 0) { hmp_target_mask = cpumask_of(target_cpu); } else { hmp = hmp_faster_domain(cpu_of(se->cfs_rq->rq)); hmp_target_mask = &hmp->cpus; }
Or, if you want to do some sanity checking that target_cpu is in the right domain...
hmp = hmp_faster_domain(cpu_of(se->cfs_rq->rq)); hmp_target_mask = &hmp->cpus; if (target_cpu >= 0) { BUG_ON(!cpumask_test_cpu(target_cpu, hmp_target_mask)); hmp_target_mask = cpumask_of(target_cpu); }
I much prefer the second option, thanks :)