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

Commit 2bd47d3f authored by Patrick Bellasi's avatar Patrick Bellasi
Browse files

ANDROID: sched/fair: Cleanup cpu_util{_wake}()



The current implementation of cpu_util and cpu_util_wake makes more
difficult the backporting of mainline patches and it also has some
features not longer required by the current EAS code, e.g. delta
utilization in __cpu_util().

Let's clean up these functions definitions to:
1. get rid of the not longer required __cpu_util(cpu, delta)
   This function is now only called with delta=0 and thus we can refold
   its implementation into the original wrapper function cpu_util(cpu)
2. optimize for the WALT path on CONFIG_SCHED_WALT builds
   Currently indeed we execute some not necessary PELT related code even
   when WALT signals are required.
   Let's change this by assuming that on CONFIG_SCHED_WALT build we are
   likely using WALT signals. While on !CONFIG_SCHED_WALT we still have
   just the PELT signals with a code structure which matches mainline
3. move the definitions from sched/sched.h into sched/fair.c
   This is the only module using these functions and it also better
   align with the mainline location for these functions
4. get rid of the walt_util macro
   That macro has a function-like signature but it's modifying a
   parameter (passed by value) which makes it a bit confusing.
   Moreover, the usage of the min_t() macro to cap signals with
   capacity_orig_of() it makes not more required the explicit type cast
   used by that macro to support both 32 and 63 bits targets.
5. remove forward declarations
   Which are not required once the definition is moved at the top of
   fair.c, since they don't have other local dependencies.

Signed-off-by: default avatarPatrick Bellasi <patrick.bellasi@arm.com>
Change-Id: I61c9b7b8a0a34b494527c5aa76218c64543c16d2
parent 2cc3df5e
Loading
Loading
Loading
Loading
+104 −33
Original line number Diff line number Diff line
@@ -4953,8 +4953,6 @@ static inline void hrtick_update(struct rq *rq)
#ifdef CONFIG_SMP
static bool cpu_overutilized(int cpu);

static unsigned long cpu_util(int cpu);

static bool sd_overutilized(struct sched_domain *sd)
{
	return sd->shared->overutilized;
@@ -5495,8 +5493,6 @@ static inline bool energy_aware(void)
	return sched_feat(ENERGY_AWARE);
}

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
@@ -5650,7 +5646,110 @@ struct energy_env {
	struct sched_group	*sg;
};

static int cpu_util_wake(int cpu, struct task_struct *p);
/*
 * cpu_util returns the amount of capacity of a CPU that is used by CFS
 * tasks. The unit of the return value must be the one of capacity so we can
 * compare the utilization with the capacity of the CPU that is available for
 * CFS task (ie cpu_capacity).
 *
 * cfs_rq.avg.util_avg is the sum of running time of runnable tasks plus the
 * recent utilization of currently non-runnable tasks on a CPU. It represents
 * the amount of utilization of a CPU in the range [0..capacity_orig] where
 * capacity_orig is the cpu_capacity available at the highest frequency,
 * i.e. arch_scale_cpu_capacity().
 * The utilization of a CPU converges towards a sum equal to or less than the
 * current capacity (capacity_curr <= capacity_orig) of the CPU because it is
 * the running time on this CPU scaled by capacity_curr.
 *
 * Nevertheless, cfs_rq.avg.util_avg can be higher than capacity_curr or even
 * higher than capacity_orig because of unfortunate rounding in
 * cfs.avg.util_avg or just after migrating tasks and new task wakeups until
 * the average stabilizes with the new running time. We need to check that the
 * utilization stays within the range of [0..capacity_orig] and cap it if
 * necessary. Without utilization capping, a group could be seen as overloaded
 * (CPU0 utilization at 121% + CPU1 utilization at 80%) whereas CPU1 has 20% of
 * available capacity. We allow utilization to overshoot capacity_curr (but not
 * capacity_orig) as it useful for predicting the capacity required after task
 * migrations (scheduler-driven DVFS).
 */
static inline unsigned long cpu_util(int cpu)
{
	struct cfs_rq *cfs_rq;
	unsigned int util;

#ifdef CONFIG_SCHED_WALT
	if (likely(!walt_disabled && sysctl_sched_use_walt_cpu_util)) {
		u64 walt_cpu_util = cpu_rq(cpu)->cumulative_runnable_avg;

		walt_cpu_util <<= SCHED_CAPACITY_SHIFT;
		do_div(walt_cpu_util, walt_ravg_window);

		return min_t(unsigned long, walt_cpu_util,
			     capacity_orig_of(cpu));
	}
#endif

	cfs_rq = &cpu_rq(cpu)->cfs;
	util = READ_ONCE(cfs_rq->avg.util_avg);

	return min_t(unsigned long, util, capacity_orig_of(cpu));
}

static inline unsigned long cpu_util_freq(int cpu)
{
#ifdef CONFIG_SCHED_WALT
	u64 walt_cpu_util;

	if (unlikely(walt_disabled || !sysctl_sched_use_walt_cpu_util))
		return cpu_util(cpu);

	walt_cpu_util = cpu_rq(cpu)->prev_runnable_sum;
	walt_cpu_util <<= SCHED_CAPACITY_SHIFT;
	do_div(walt_cpu_util, walt_ravg_window);

	return min_t(unsigned long, walt_cpu_util, capacity_orig_of(cpu));
#else
	return cpu_util(cpu);
#endif
}

/*
 * cpu_util_wake: Compute CPU utilization with any contributions from
 * the waking task p removed.
 */
static unsigned long cpu_util_wake(int cpu, struct task_struct *p)
{
	struct cfs_rq *cfs_rq;
	unsigned int util;

#ifdef CONFIG_SCHED_WALT
	/*
	 * WALT does not decay idle tasks in the same manner
	 * as PELT, so it makes little sense to subtract task
	 * utilization from cpu utilization. Instead just use
	 * cpu_util for this case.
	 */
	if (likely(!walt_disabled && sysctl_sched_use_walt_cpu_util))
		return cpu_util(cpu);
#endif

	/* Task has no contribution or is new */
	if (cpu != task_cpu(p) || !READ_ONCE(p->se.avg.last_update_time))
		return cpu_util(cpu);

	cfs_rq = &cpu_rq(cpu)->cfs;
	util = READ_ONCE(cfs_rq->avg.util_avg);

	/* Discount task's blocked util from CPU's util */
	util -= min_t(unsigned int, util, task_util(p));

	/*
	 * Utilization (estimated) can exceed the CPU capacity, thus let's
	 * clamp to the maximum CPU capacity to ensure consistency with
	 * the cpu_util call.
	 */
	return min_t(unsigned long, util, capacity_orig_of(cpu));
}

static unsigned long group_max_util(struct energy_env *eenv, int cpu_idx)
{
@@ -6862,34 +6961,6 @@ static inline unsigned long task_util(struct task_struct *p)
	return p->se.avg.util_avg;
}

/*
 * cpu_util_wake: Compute cpu utilization with any contributions from
 * the waking task p removed.
 */
static int cpu_util_wake(int cpu, struct task_struct *p)
{
	unsigned long util, capacity;

#ifdef CONFIG_SCHED_WALT
	/*
	 * WALT does not decay idle tasks in the same manner
	 * as PELT, so it makes little sense to subtract task
	 * utilization from cpu utilization. Instead just use
	 * cpu_util for this case.
	 */
	if (!walt_disabled && sysctl_sched_use_walt_cpu_util)
		return cpu_util(cpu);
#endif
	/* Task has no contribution or is new */
	if (cpu != task_cpu(p) || !p->se.avg.last_update_time)
		return cpu_util(cpu);

	capacity = capacity_orig_of(cpu);
	util = max_t(long, cpu_rq(cpu)->cfs.avg.util_avg - task_util(p), 0);

	return (util >= capacity) ? capacity : util;
}

static inline int task_fits_capacity(struct task_struct *p, long capacity)
{
	return capacity * 1024 > boosted_task_util(p) * capacity_margin;
+1 −69
Original line number Diff line number Diff line
@@ -1777,75 +1777,7 @@ extern unsigned int sysctl_sched_use_walt_cpu_util;
extern unsigned int walt_ravg_window;
extern bool walt_disabled;

#ifdef CONFIG_SCHED_WALT
#define walt_util(util_var, demand_sum) {\
	u64 sum = demand_sum << SCHED_CAPACITY_SHIFT;\
	do_div(sum, walt_ravg_window);\
	util_var = (typeof(util_var))sum;\
	}
#endif
/*
 * cpu_util returns the amount of capacity of a CPU that is used by CFS
 * tasks. The unit of the return value must be the one of capacity so we can
 * compare the utilization with the capacity of the CPU that is available for
 * CFS task (ie cpu_capacity).
 *
 * cfs_rq.avg.util_avg is the sum of running time of runnable tasks plus the
 * recent utilization of currently non-runnable tasks on a CPU. It represents
 * the amount of utilization of a CPU in the range [0..capacity_orig] where
 * capacity_orig is the cpu_capacity available at the highest frequency
 * (arch_scale_freq_capacity()).
 * The utilization of a CPU converges towards a sum equal to or less than the
 * current capacity (capacity_curr <= capacity_orig) of the CPU because it is
 * the running time on this CPU scaled by capacity_curr.
 *
 * Nevertheless, cfs_rq.avg.util_avg can be higher than capacity_curr or even
 * higher than capacity_orig because of unfortunate rounding in
 * cfs.avg.util_avg or just after migrating tasks and new task wakeups until
 * the average stabilizes with the new running time. We need to check that the
 * utilization stays within the range of [0..capacity_orig] and cap it if
 * necessary. Without utilization capping, a group could be seen as overloaded
 * (CPU0 utilization at 121% + CPU1 utilization at 80%) whereas CPU1 has 20% of
 * available capacity. We allow utilization to overshoot capacity_curr (but not
 * capacity_orig) as it useful for predicting the capacity required after task
 * migrations (scheduler-driven DVFS).
 */
static inline unsigned long __cpu_util(int cpu, int delta)
{
	unsigned long util = cpu_rq(cpu)->cfs.avg.util_avg;
	unsigned long capacity = capacity_orig_of(cpu);

#ifdef CONFIG_SCHED_WALT
	if (!walt_disabled && sysctl_sched_use_walt_cpu_util) {
		walt_util(util, cpu_rq(cpu)->cumulative_runnable_avg);
	}
#endif
	delta += util;
	if (delta < 0)
		return 0;

	return (delta >= capacity) ? capacity : delta;
}

static inline unsigned long cpu_util(int cpu)
{
	return __cpu_util(cpu, 0);
}

static inline unsigned long cpu_util_freq(int cpu)
{
	unsigned long util = cpu_rq(cpu)->cfs.avg.util_avg;
	unsigned long capacity = capacity_orig_of(cpu);

#ifdef CONFIG_SCHED_WALT
	if (!walt_disabled && sysctl_sched_use_walt_cpu_util) {
		walt_util(util, cpu_rq(cpu)->prev_runnable_sum);
	}
#endif
	return (util >= capacity) ? capacity : util;
}

#endif
#endif /* CONFIG_SMP */

static inline void sched_rt_avg_update(struct rq *rq, u64 rt_delta)
{