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

Commit 9378697a authored by Quentin Perret's avatar Quentin Perret
Browse files

ANDROID: sched/fair: Factor out CPU selection from find_energy_efficient_cpu



find_energy_efficient_cpu() is composed of two steps; we first look for
the CPU with the max spare capacity in each frequency domain, and then
the impact on energy of each candidate is estimated. In order to make it
easier to implement other CPU selection policies, let's factor the
candidate selection algorithm out of find_energy_efficient_cpu(), and
mark the candidates in a mask. This should result in no functional
difference.

Signed-off-by: default avatarQuentin Perret <quentin.perret@arm.com>
Change-Id: I85a28880f01fcd11d7af28f9fbc1fe0cf4f197cf
parent 2e88529c
Loading
Loading
Loading
Loading
+62 −40
Original line number Diff line number Diff line
@@ -6555,6 +6555,44 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd)
	return energy;
}

static void select_max_spare_cap_cpus(struct sched_domain *sd, cpumask_t *cpus,
		struct perf_domain *pd, struct task_struct *p)
{
	unsigned long spare_cap, max_spare_cap, util, cpu_cap;
	int cpu, max_spare_cap_cpu;

	for (; pd; pd = pd->next) {
		max_spare_cap_cpu = -1;
		max_spare_cap = 0;

		for_each_cpu_and(cpu, perf_domain_span(pd), sched_domain_span(sd)) {
			if (!cpumask_test_cpu(cpu, &p->cpus_allowed))
				continue;

			/* Skip CPUs that will be overutilized. */
			util = cpu_util_next(cpu, p, cpu);
			cpu_cap = capacity_of(cpu);
			if (cpu_cap * 1024 < util * capacity_margin)
				continue;

			/*
			 * Find the CPU with the maximum spare capacity in
			 * the performance domain
			 */
			spare_cap = cpu_cap - util;
			if (spare_cap > max_spare_cap) {
				max_spare_cap = spare_cap;
				max_spare_cap_cpu = cpu;
			}
		}

		if (max_spare_cap_cpu >= 0)
			cpumask_set_cpu(max_spare_cap_cpu, cpus);
	}
}

static DEFINE_PER_CPU(cpumask_t, energy_cpus);

/*
 * find_energy_efficient_cpu(): Find most energy-efficient target CPU for the
 * waking task. find_energy_efficient_cpu() looks for the CPU with maximum
@@ -6599,16 +6637,16 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
{
	unsigned long prev_energy = ULONG_MAX, best_energy = ULONG_MAX;
	struct root_domain *rd = cpu_rq(smp_processor_id())->rd;
	int cpu, best_energy_cpu = prev_cpu;
	struct perf_domain *head, *pd;
	unsigned long cpu_cap, util;
	int weight, cpu, best_energy_cpu = prev_cpu;
	unsigned long cur_energy;
	struct perf_domain *pd;
	struct sched_domain *sd;
	cpumask_t *candidates;

	rcu_read_lock();
	pd = rcu_dereference(rd->pd);
	if (!pd || READ_ONCE(rd->overutilized))
		goto fail;
	head = pd;

	/*
	 * Energy-aware wake-up happens on the lowest sched_domain starting
@@ -6624,45 +6662,29 @@ static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu)
	if (!task_util_est(p))
		goto unlock;

	for (; pd; pd = pd->next) {
		unsigned long cur_energy, spare_cap, max_spare_cap = 0;
		int max_spare_cap_cpu = -1;
	/* Pre-select a set of candidate CPUs. */
	candidates = this_cpu_ptr(&energy_cpus);
	cpumask_clear(candidates);
	select_max_spare_cap_cpus(sd, candidates, pd, p);

		for_each_cpu_and(cpu, perf_domain_span(pd), sched_domain_span(sd)) {
			if (!cpumask_test_cpu(cpu, &p->cpus_allowed))
				continue;
	/* Bail out if there is no candidate, or if the only one is prev_cpu */
	weight = cpumask_weight(candidates);
	if (!weight || (weight == 1 && cpumask_first(candidates) == prev_cpu))
		goto unlock;

			/* Skip CPUs that will be overutilized. */
			util = cpu_util_next(cpu, p, cpu);
			cpu_cap = capacity_of(cpu);
			if (cpu_cap * 1024 < util * capacity_margin)
				continue;
	if (cpumask_test_cpu(prev_cpu, &p->cpus_allowed))
		prev_energy = best_energy = compute_energy(p, prev_cpu, pd);
	else
		prev_energy = best_energy = ULONG_MAX;

			/* Always use prev_cpu as a candidate. */
			if (cpu == prev_cpu) {
				prev_energy = compute_energy(p, prev_cpu, head);
				best_energy = min(best_energy, prev_energy);
	/* Select the best candidate energy-wise. */
	for_each_cpu(cpu, candidates) {
		if (cpu == prev_cpu)
			continue;
			}

			/*
			 * Find the CPU with the maximum spare capacity in
			 * the performance domain
			 */
			spare_cap = cpu_cap - util;
			if (spare_cap > max_spare_cap) {
				max_spare_cap = spare_cap;
				max_spare_cap_cpu = cpu;
			}
		}

		/* Evaluate the energy impact of using this CPU. */
		if (max_spare_cap_cpu >= 0) {
			cur_energy = compute_energy(p, max_spare_cap_cpu, head);
		cur_energy = compute_energy(p, cpu, pd);
		if (cur_energy < best_energy) {
			best_energy = cur_energy;
				best_energy_cpu = max_spare_cap_cpu;
			}
			best_energy_cpu = cpu;
		}
	}
unlock: