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

Commit cf80de5a authored by Vikram Mulukutla's avatar Vikram Mulukutla Committed by Joonwoo Park
Browse files

sched: Introduce an irq_work to report WALT load



Since WALT stats relevant to the cpufreq governor are updated after the
completion of a window, and the governor needs to base its decisions
after having a complete picture of all the CPUs in a policy, introduce
an irq_work callback that's scheduled in the tick. This irq_work callback
will (for all CPUS) update WALT stats to ensure we have the latest for the
most recently completed window, and report those stats to the govneror
as well. This should get us as close as possible to the previous
solution of sched_get_cpus_busy without having to create a new interface.

Change-Id: Ica79396fc5dfc132b62764b3d01f8a507a2b63aa
Signed-off-by: default avatarVikram Mulukutla <markivx@codeaurora.org>
parent 44c971bb
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -3325,6 +3325,33 @@ static void sched_freq_tick(int cpu)
static inline void sched_freq_tick(int cpu) { }
#endif /* CONFIG_CPU_FREQ_GOV_SCHED */

#ifdef CONFIG_SCHED_WALT
static atomic64_t walt_irq_work_lastq_ws;

static inline u64 walt_window_start_of(struct rq *rq)
{
	return rq->window_start;
}

static inline void run_walt_irq_work(u64 window_start, struct rq *rq)
{
	/* No HMP since that uses sched_get_cpus_busy */
	if (rq->window_start != window_start &&
		atomic_cmpxchg(&walt_irq_work_lastq_ws, window_start,
			   rq->window_start) == window_start)
		irq_work_queue(&rq->irq_work);
}
#else
static inline u64 walt_window_start_of(struct rq *rq)
{
	return 0;
}

static inline void run_walt_irq_work(u64 window_start, struct rq *rq)
{
}
#endif

/*
 * This function gets called by the timer code, with HZ frequency.
 * We call it with interrupts disabled.
@@ -3338,11 +3365,18 @@ void scheduler_tick(void)
	bool early_notif;
	u32 old_load;
	struct related_thread_group *grp;
	u64 window_start;

	sched_clock_tick();

	raw_spin_lock(&rq->lock);

	/*
	 * Record current window_start. If after utra() below the window
	 * has rolled over, schedule a load-reporting irq-work
	 */
	window_start = walt_window_start_of(rq);

	old_load = task_load(curr);
	set_window_start(rq);

@@ -3355,6 +3389,9 @@ void scheduler_tick(void)
	cpu_load_update_active(rq);
	calc_global_load_tick(rq);
	cpufreq_update_util(rq, 0);

	run_walt_irq_work(window_start, rq);

	early_notif = early_detection_notify(rq, wallclock);

	raw_spin_unlock(&rq->lock);
@@ -8362,6 +8399,7 @@ void __init sched_init(void)
		rq->push_task = NULL;
#ifdef CONFIG_SCHED_WALT
		cpumask_set_cpu(i, &rq->freq_domain_cpumask);
		init_irq_work(&rq->irq_work, walt_irq_work);
		rq->hmp_stats.cumulative_runnable_avg = 0;
		rq->window_start = 0;
		rq->cum_window_start = 0;
+1 −0
Original line number Diff line number Diff line
@@ -798,6 +798,7 @@ struct rq {
	u8 curr_table;
	int prev_top;
	int curr_top;
	struct irq_work irq_work;
#endif

#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+27 −0
Original line number Diff line number Diff line
@@ -2839,3 +2839,30 @@ static void transfer_busy_time(struct rq *rq, struct related_thread_group *grp,
	BUG_ON((s64)*src_nt_prev_runnable_sum < 0);
}

/*
 * Runs in hard-irq context. This should ideally run just after the latest
 * window roll-over.
 */
void walt_irq_work(struct irq_work *irq_work)
{
	struct rq *rq;
	int cpu;
	u64 wc;

	for_each_cpu(cpu, cpu_possible_mask)
		raw_spin_lock(&cpu_rq(cpu)->lock);

	wc = sched_ktime_clock();

	for_each_cpu(cpu, cpu_possible_mask) {
		if (cpu == smp_processor_id())
			continue;
		rq = cpu_rq(cpu);
		if (rq->curr)
			update_task_ravg(rq->curr, rq, TASK_UPDATE, wc, 0);
		cpufreq_update_util(rq, 0);
	}

	for_each_cpu(cpu, cpu_possible_mask)
		raw_spin_unlock(&cpu_rq(cpu)->lock);
}
+2 −0
Original line number Diff line number Diff line
@@ -251,6 +251,8 @@ static inline int same_cluster(int src_cpu, int dst_cpu)

void sort_clusters(void);

void walt_irq_work(struct irq_work *irq_work);

#else /* CONFIG_SCHED_WALT */

static inline void update_task_ravg(struct task_struct *p, struct rq *rq,