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

Commit 19247f6f authored by Patrick Bellasi's avatar Patrick Bellasi Committed by Chris Redpath
Browse files

ANDROID: sched/fair: consider task utilization in group_norm/max_util()



was previously:
ANDROID: sched/fair: consider task utilization in group_norm_util()

The group_norm_util() function is used to compute the normalized
utilization of a SG given a certain energy_env configuration.
The main client of this function is the energy_diff function when it
comes to compute the SG energy for one of the before/after scheduling
candidates.

Currently, the energy_diff function sets util_delta = 0 when it wants to
compute the energy corresponding to the scheduling candidate where the
task runs in the previous CPU. This implies that, for the task waking up
in the previous CPU we consider only its blocked load tracked by the CPU
RQ. However, in case of a medium-big task which is waking up on a long
time idle CPU, this blocked load can be already completely decayed.

More in general, the current approach is biased towards under-estimating
the energy consumption for the "before" scheduling candidate.

This patch fixes this by:
- always use the cpu_util_wake() to properly get the utilization of a CPU
  without any (partially decayed) contribution of the waking up task
- adding the task utilization to the cpu_util_wake just for the
  target cpu

The "target CPU" is defined by the energy_env to be either the src_cpu
or the dst_cpu, depending on which scheduling candidate we are
considering.

This patch update also the definition of __cpu_norm_util(), which is
currently called just by the group_norm_util() function. This allows to
simplify the code by using this function just to normalize a specified
utilization with respect to a given capacity.

This update allows to completely remove any dependency of
group_norm_util() from calc_util_delta().

Change-Id: I3b6ec50ce8decb1521faae660e326ab3319d3c82
Signed-off-by: default avatarPatrick Bellasi <patrick.bellasi@arm.com>
Signed-off-by: default avatarChris Redpath <chris.redpath@arm.com>

and:

ANDROID: sched/fair: consider task utilization in group_max_util()

The group_max_util() function is used to compute the maximum utilization
across the CPUs of a certain energy_env configuration.
Its main client is the energy_diff function when it needs to compute the
SG capacity for one of the before/after scheduling candidates.

Currently, the energy_diff function sets util_delta = 0 when it wants to
compute the energy corresponding to the scheduling candidate where the
task runs in the previous CPU. This implies that, for the task waking up
in the previous CPU we consider only its blocked load tracked by the CPU
RQ. However, in case of a medium-big task which is waking up on a long
time idle CPU, this blocked load can be already completely decayed.

More in general, the current approach is biased towards under-estimating
the capacity requirements for the "before" scheduling candidate.

This patch fixes this by:
- always use the cpu_util_wake() to properly get the utilization of a CPU
  without any (partially decayed) contribution of the waking up task
- adding the task utilization to the cpu_util_wake just for the target
  cpu

The "target CPU" is defined by the energy_env to be either the src_cpu or
the dst_cpu, depending on which scheduling candidate we are considering.

Finally, since this update removes the last usage of calc_util_delta()
this function is now safely removed.

Change-Id: I20ee1bcf40cee6bf6e265fb2d32ef79061ad6ced
Signed-off-by: default avatarPatrick Bellasi <patrick.bellasi@arm.com>
Signed-off-by: default avatarChris Redpath <chris.redpath@arm.com>

Change-Id: Id4aec875be0c808460763a03d392678e946f51d4
Signed-off-by: default avatarPatrick Bellasi <patrick.bellasi@arm.com>
Signed-off-by: default avatarChris Redpath <chris.redpath@arm.com>
parent 83717be3
Loading
Loading
Loading
Loading
+39 −26
Original line number Diff line number Diff line
@@ -5511,6 +5511,7 @@ struct energy_env {
	int			util_delta;
	int			src_cpu;
	int			dst_cpu;
	int			trg_cpu;
	int			energy;
	int			payoff;
	struct task_struct	*task;
@@ -5526,6 +5527,9 @@ struct energy_env {
		int delta;
	} cap;
};

static int cpu_util_wake(int cpu, struct task_struct *p);

/*
 * __cpu_norm_util() returns the cpu util relative to a specific capacity,
 * i.e. it's busy ratio, in the range [0..SCHED_CAPACITY_SCALE] which is useful
@@ -5540,34 +5544,32 @@ struct energy_env {
 *
 *   norm_util = running_time/time ~ util/capacity
 */
static unsigned long __cpu_norm_util(int cpu, unsigned long capacity, int delta)
static unsigned long __cpu_norm_util(unsigned long util, unsigned long capacity)
{
	int util = __cpu_util(cpu, delta);

	if (util >= capacity)
		return SCHED_CAPACITY_SCALE;

	return (util << SCHED_CAPACITY_SHIFT)/capacity;
}

static int calc_util_delta(struct energy_env *eenv, int cpu)
{
	if (cpu == eenv->src_cpu)
		return -eenv->util_delta;
	if (cpu == eenv->dst_cpu)
		return eenv->util_delta;
	return 0;
}

static
unsigned long group_max_util(struct energy_env *eenv)
static unsigned long group_max_util(struct energy_env *eenv)
{
	int i, delta;
	unsigned long max_util = 0;
	unsigned long util;
	int cpu;

	for_each_cpu(cpu, sched_group_span(eenv->sg_cap)) {
		util = cpu_util_wake(cpu, eenv->task);

	for_each_cpu(i, sched_group_span(eenv->sg_cap)) {
		delta = calc_util_delta(eenv, i);
		max_util = max(max_util, __cpu_util(i, delta));
		/*
		 * If we are looking at the target CPU specified by the eenv,
		 * then we should add the (estimated) utilization of the task
		 * assuming we will wake it up on that CPU.
		 */
		if (unlikely(cpu == eenv->trg_cpu))
			util += eenv->util_delta;

		max_util = max(max_util, util);
	}

	return max_util;
@@ -5585,13 +5587,22 @@ unsigned long group_max_util(struct energy_env *eenv)
static unsigned
long group_norm_util(struct energy_env *eenv, struct sched_group *sg)
{
	int i, delta;
	unsigned long util_sum = 0;
	unsigned long capacity = sg->sge->cap_states[eenv->cap_idx].cap;
	unsigned long util, util_sum = 0;
	int cpu;

	for_each_cpu(cpu, sched_group_span(sg)) {
		util = cpu_util_wake(cpu, eenv->task);

	for_each_cpu(i, sched_group_span(sg)) {
		delta = calc_util_delta(eenv, i);
		util_sum += __cpu_norm_util(i, capacity, delta);
		/*
		 * If we are looking at the target CPU specified by the eenv,
		 * then we should add the (estimated) utilization of the task
		 * assuming we will wake it up on that CPU.
		 */
		if (unlikely(cpu == eenv->trg_cpu))
			util += eenv->util_delta;

		util_sum += __cpu_norm_util(util, capacity);
	}

	if (util_sum > SCHED_CAPACITY_SCALE)
@@ -5777,6 +5788,8 @@ static inline bool cpu_in_sg(struct sched_group *sg, int cpu)
	return cpu != -1 && cpumask_test_cpu(cpu, sched_group_span(sg));
}

static inline unsigned long task_util(struct task_struct *p);

/*
 * __energy_diff(): Estimate the energy impact of changing the utilization
 * distribution. eenv specifies the change: utilisation amount, source, and
@@ -5792,11 +5805,12 @@ static int energy_diff(struct energy_env *eenv)
	int margin;

	struct energy_env eenv_before = {
		.util_delta	= 0,
		.util_delta	= task_util(eenv->task),
		.src_cpu	= eenv->src_cpu,
		.dst_cpu	= eenv->dst_cpu,
		.nrg		= { 0, 0, 0, 0},
		.cap		= { 0, 0, 0 },
		.trg_cpu	= eenv->src_cpu,
		.task		= eenv->task,
	};

@@ -6052,8 +6066,6 @@ boosted_task_util(struct task_struct *task)
	return util + margin;
}

static int cpu_util_wake(int cpu, struct task_struct *p);

static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
{
	return capacity_orig_of(cpu) - cpu_util_wake(cpu, p);
@@ -6667,6 +6679,7 @@ static int find_energy_efficient_cpu(struct sched_domain *sd,
			.src_cpu	= prev_cpu,
			.dst_cpu	= i,
			.task		= p,
			.trg_cpu	= i,
		};

		spare = capacity_spare_wake(i, p);