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

Commit 666f0ee7 authored by Pavankumar Kondeti's avatar Pavankumar Kondeti Committed by Lingutla Chandrasekhar
Browse files

sched/fair: reduce no-hz idle balance for energy aware systems



We are kicking no-hz idle balance when the CPU has two tasks.
It should be done only when the CPU is overutilized on
energy aware systems. This approach seems to be causing more
number of wakeups on HZ=250 systems compared to HZ=100.

Revisit the no-hz idle scheme and only send the IPI if and
when it is necessary.

Change-Id: I82e58a2aa3b6508c86d05c93c9fb7fe6dfbde500
Signed-off-by: default avatarPavankumar Kondeti <pkondeti@codeaurora.org>
parent c4e0df05
Loading
Loading
Loading
Loading
+80 −27
Original line number Diff line number Diff line
@@ -11093,6 +11093,71 @@ static inline int on_null_domain(struct rq *rq)
}

#ifdef CONFIG_NO_HZ_COMMON
static inline int find_energy_aware_new_ilb(void)
{
	int ilb = nr_cpu_ids;
	struct sched_domain *sd;
	int cpu = raw_smp_processor_id();
	cpumask_t idle_cpus, tmp_cpus;
	struct sched_group *sg;
	unsigned long ref_cap = capacity_orig_of(cpu);
	unsigned long best_cap = 0, best_cap_cpu = -1;

	rcu_read_lock();
	sd = rcu_dereference(per_cpu(sd_asym_cpucapacity, cpu));
	if (!sd)
		goto out;

	cpumask_and(&idle_cpus, nohz.idle_cpus_mask,
			housekeeping_cpumask(HK_FLAG_MISC));
	cpumask_andnot(&idle_cpus, &idle_cpus, cpu_isolated_mask);

	sg = sd->groups;
	do {
		int i;
		unsigned long cap;

		cpumask_and(&tmp_cpus, &idle_cpus, sched_group_span(sg));
		i = cpumask_first(&tmp_cpus);

		/* This sg did not have any idle CPUs */
		if (i >= nr_cpu_ids)
			continue;

		cap = capacity_orig_of(i);

		/* The first preference is for the same capacity CPU */
		if (cap == ref_cap) {
			ilb = i;
			break;
		}

		/*
		 * When there are no idle CPUs in the same capacity group,
		 * we find the next best capacity CPU.
		 */
		if (best_cap > ref_cap) {
			if (cap > ref_cap && cap < best_cap) {
				best_cap = cap;
				best_cap_cpu = i;
			}
			continue;
		}

		if (cap > best_cap) {
			best_cap = cap;
			best_cap_cpu = i;
		}

	} while (sg = sg->next, sg != sd->groups);

	if (best_cap_cpu != -1)
		ilb = best_cap_cpu;
out:
	rcu_read_unlock();
	return ilb;
}

/*
 * idle load balancing details
 * - When one of the busy CPUs notice that there may be an idle rebalancing
@@ -11104,33 +11169,10 @@ static inline int on_null_domain(struct rq *rq)

static inline int find_new_ilb(void)
{
	int ilb = nr_cpu_ids;
	struct sched_domain *sd;
	int cpu = raw_smp_processor_id();
	struct rq *rq = cpu_rq(cpu);
	cpumask_t cpumask;
	int ilb;

	rcu_read_lock();
	sd = rcu_dereference_check_sched_domain(rq->sd);
	if (sd) {
		cpumask_and(&cpumask, nohz.idle_cpus_mask,
				sched_domain_span(sd));
		cpumask_andnot(&cpumask, &cpumask,
				cpu_isolated_mask);
		ilb = cpumask_first(&cpumask);
	}
	rcu_read_unlock();

	if (sd && (ilb >= nr_cpu_ids || !idle_cpu(ilb))) {
		if (!static_branch_unlikely(&sched_energy_present) ||
				(capacity_orig_of(cpu) ==
				cpu_rq(cpu)->rd->max_cpu_capacity.val ||
				cpu_overutilized(cpu))) {
			cpumask_andnot(&cpumask, nohz.idle_cpus_mask,
					cpu_isolated_mask);
			ilb = cpumask_first(&cpumask);
		}
	}
	if (static_branch_likely(&sched_energy_present))
		return find_energy_aware_new_ilb();

	for_each_cpu_and(ilb, nohz.idle_cpus_mask,
			      housekeeping_cpumask(HK_FLAG_MISC)) {
@@ -11214,7 +11256,18 @@ static void nohz_balancer_kick(struct rq *rq)
	if (time_before(now, nohz.next_balance))
		goto out;

	if (rq->nr_running >= 2 || rq->misfit_task_load) {
	/*
	 * With EAS, no-hz idle balance is allowed only when the CPU
	 * is overutilized and has 2 tasks. The misfit task migration
	 * happens from the tickpath.
	 */
	if (static_branch_likely(&sched_energy_present)) {
		if (rq->nr_running >= 2 && cpu_overutilized(cpu))
			flags = NOHZ_KICK_MASK;
		goto out;
	}

	if (rq->nr_running >= 2) {
		flags = NOHZ_KICK_MASK;
		goto out;
	}