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

Commit 8fc0529a authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

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

parents ef8df9cf 666f0ee7
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;
	}