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

Commit 8c79738a authored by Lingutla Chandrasekhar's avatar Lingutla Chandrasekhar
Browse files

sched/fair: fix imbalance calculations in misfit balancing



For misfit group type, load balancer tries to help independent of
group's avg load by pulling misfit task from the busy group, but it
calculates average load base imbalance between domains and consider
that in its decision. And it boosts the imbalance with maximum of
above calculated imbalance and busiest misfit task load for newly
idle balancing.

For Big.Little systems, local(Big) avg load can be greater than
domain's avg load and busiest (Little) avg load can be less than domain's
avg load. Which makes imbalance calculations go wrong and leads to
incorrect load balance decisions.

Make sure average load based imbalance calculations are performed only if
busiest avg load is greater than domain avg load or local avg load less
than domain avg load.

Change-Id: I40fc5b011455612d0e9cd99595e2fc8e60db4626
Signed-off-by: default avatarLingutla Chandrasekhar <clingutla@codeaurora.org>
parent 0aa9aa46
Loading
Loading
Loading
Loading
+34 −15
Original line number Diff line number Diff line
@@ -10373,6 +10373,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
{
	unsigned long max_pull, load_above_capacity = ~0UL;
	struct sg_lb_stats *local, *busiest;
	bool no_imbalance = false;

	local = &sds->local_stat;
	busiest = &sds->busiest_stat;
@@ -10392,9 +10393,11 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
	 * factors in sg capacity and sgs with smaller group_type are
	 * skipped when updating the busiest sg:
	 */
	if (busiest->group_type != group_misfit_task &&
	    (busiest->avg_load <= sds->avg_load ||
	     local->avg_load >= sds->avg_load)) {
	if (busiest->avg_load <= sds->avg_load ||
	    local->avg_load >= sds->avg_load)
		no_imbalance = true;

	if (busiest->group_type != group_misfit_task && no_imbalance) {
		env->imbalance = 0;
		if (busiest->group_type == group_overloaded &&
				local->group_type <= group_misfit_task) {
@@ -10419,19 +10422,35 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
	}

	/*
	 * We're trying to get all the cpus to the average_load, so we don't
	 * want to push ourselves above the average load, nor do we wish to
	 * reduce the max loaded cpu below the average load. At the same time,
	 * we also don't want to reduce the group load below the group
	 * capacity. Thus we look for the minimum possible imbalance.
	 * In case of a misfit task, independent of avg loads we do load balance
	 * at the parent sched domain level for B.L systems, so it is possible
	 * that busiest group avg load can be less than sd avg load.
	 * So skip calculating load based imbalance between groups.
	 */
	if (!no_imbalance) {
		/*
		 * We're trying to get all the cpus to the average_load,
		 * so we don't want to push ourselves above the average load,
		 * nor do we wish to reduce the max loaded cpu below the average
		 * load. At the same time, we also don't want to reduce the
		 * group load below the group capacity.
		 * Thus we look for the minimum possible imbalance.
		 */
	max_pull = min(busiest->avg_load - sds->avg_load, load_above_capacity);
		max_pull = min(busiest->avg_load - sds->avg_load,
				load_above_capacity);

		/* How much load to actually move to equalise the imbalance */
	env->imbalance = min(
		max_pull * busiest->group_capacity,
		(sds->avg_load - local->avg_load) * local->group_capacity
	) / SCHED_CAPACITY_SCALE;
		env->imbalance = min(max_pull * busiest->group_capacity,
				     (sds->avg_load - local->avg_load) *
				     local->group_capacity) /
				     SCHED_CAPACITY_SCALE;
	} else {
		/*
		 * Skipped load based imbalance calculations, but let's find
		 * imbalance based on busiest group type or fix small imbalance.
		 */
		env->imbalance = 0;
	}

	/* Boost imbalance to allow misfit task to be balanced.
	 * Always do this if we are doing a NEWLY_IDLE balance