Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92ba1d55 authored by Srivatsa Vaddagiri's avatar Srivatsa Vaddagiri
Browse files

sched: Consider PF_WAKE_UP_IDLE in select_best_cpu()



sysctl_sched_prefer_idle controls selection of idle cpus for waking
tasks. In some cases, waking to idle cpus help performance while in
other cases it hurts (as tasks incur latency associated with C-state
wakeup). Its ideal if scheduler can adapt prefer_idle behavior based
on the task that is waking up, but that's hard for scheduler to
figure by itself. PF_WAKE_UP_IDLE hint can be provided by external
module/driver in such case to guide scheduler in preferring an idle
cpu for select tasks irrespective of sysctl_sched_prefer_idle flag.

This patch enhances select_best_cpu() to consider PF_WAKE_UP_IDLE
hint. Wakeup posted from any task that has PF_WAKE_UP_IDLE set is a
hint for scheduler to prefer idle cpu for waking tasks. Similarly
scheduler will attempt to place any task with PF_WAKE_UP_IDLE set on
idle cpu when they wakeup.

CRs-Fixed: 773101
Change-Id: Ia8bf334d98fd9fd2ff9eda875430497d55d64ce6
Signed-off-by: default avatarSrivatsa Vaddagiri <vatsa@codeaurora.org>
parent 5df890cc
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -819,9 +819,14 @@ in Sec 5.

This is a per-cpu parameter. If non-zero for a cpu which is part of a cluster
and cluster current frequency is less than this threshold, then scheduler will
poack all tasks on a single cpu in cluster. The cpu chosen is the first most
pack all tasks on a single cpu in cluster. The cpu chosen is the first most
power-efficient cpu found while scanning cluster's online cpus.

- PF_WAKE_UP_IDLE
	Any task that has this flag set in its 'task_struct.flags' field will be
always woken to idle cpu. Further any task woken by such tasks will be also
placed on idle cpu.

For some low band of frequency, spread of task on all available cpus can be
groslly power-inefficient. As an example, consider two tasks that each need
500MHz. Packing them on one cpu could lead to 1GHz. In spread case, we incur
+22 −1
Original line number Diff line number Diff line
@@ -1900,6 +1900,20 @@ static int select_packing_target(struct task_struct *p, int best_cpu)
	return target;
}

/*
 * Should task be woken to any available idle cpu?
 *
 * Waking tasks to idle cpu has mixed implications on both performance and
 * power. In many cases, scheduler can't estimate correctly impact of using idle
 * cpus on either performance or power. PF_WAKE_UP_IDLE allows external kernel
 * module to pass a strong hint to scheduler that the task in question should be
 * woken to idle cpu, generally to improve performance.
 */
static inline int wake_to_idle(struct task_struct *p)
{
	return (current->flags & PF_WAKE_UP_IDLE) ||
			 (p->flags & PF_WAKE_UP_IDLE);
}

/* return cheapest cpu that can fit this task */
static int select_best_cpu(struct task_struct *p, int target, int reason,
@@ -1915,6 +1929,13 @@ static int select_best_cpu(struct task_struct *p, int target, int reason,
	int cstate, min_cstate = INT_MAX;
	int prefer_idle = reason ? 1 : sysctl_sched_prefer_idle;
	int curr_cpu = smp_processor_id();
	int prefer_idle_override = 0;

	if (wake_to_idle(p)) {
		prefer_idle = 1;
		prefer_idle_override = 1;
		small_task = 0;
	}

	trace_sched_task_load(p, small_task, boost, reason, sync, prefer_idle);

@@ -2046,7 +2067,7 @@ done:
			best_cpu = fallback_idle_cpu;
	}

	if (cpu_rq(best_cpu)->mostly_idle_freq)
	if (cpu_rq(best_cpu)->mostly_idle_freq && !prefer_idle_override)
		best_cpu = select_packing_target(p, best_cpu);

	return best_cpu;