【WALT】任务负载 util 的计算路径代码片段

本文介绍了Linux内核中WaltGov算法中的两个关键函数:waltgov_get_util用于获取CPU利用率,而cpu_util_freq_walt则根据异步能力调整siblingsCPU的频率利用,同时考虑了OPLUS特性的调度因素。
摘要由CSDN通过智能技术生成
wg_cpu->util = waltgov_get_util(wg_cpu);
static unsigned long waltgov_get_util(struct waltgov_cpu *wg_cpu)
{
	struct rq *rq = cpu_rq(wg_cpu->cpu);
	unsigned long max = arch_scale_cpu_capacity(wg_cpu->cpu);
	unsigned long util;

	wg_cpu->max = max;
	wg_cpu->reasons = 0;
	util = cpu_util_freq_walt(wg_cpu->cpu, &wg_cpu->walt_load, &wg_cpu->reasons);
	return uclamp_rq_util_with(rq, util, NULL);
}
#define ADJUSTED_ASYM_CAP_CPU_UTIL(orig, other, x)	\
			(max(orig, mult_frac(other, x, 100)))

unsigned long
cpu_util_freq_walt(int cpu, struct walt_cpu_load *walt_load, unsigned int *reason)
{
	struct walt_cpu_load wl_other = {0};
	unsigned long util = 0, util_other = 0;
	unsigned long capacity = capacity_orig_of(cpu);
	int i, mpct = sysctl_sched_asym_cap_sibling_freq_match_pct;

	if (!cpumask_test_cpu(cpu, &asym_cap_sibling_cpus))
		return __cpu_util_freq_walt(cpu, walt_load, reason);

	for_each_cpu(i, &asym_cap_sibling_cpus) {
		if (i == cpu)
			util = __cpu_util_freq_walt(cpu, walt_load, reason);
		else
			util_other = __cpu_util_freq_walt(i, &wl_other, reason);
	}

	if (cpu == cpumask_last(&asym_cap_sibling_cpus))
		mpct = 100;

	util = ADJUSTED_ASYM_CAP_CPU_UTIL(util, util_other, mpct);

	walt_load->nl = ADJUSTED_ASYM_CAP_CPU_UTIL(walt_load->nl, wl_other.nl,
						   mpct);
	walt_load->pl = ADJUSTED_ASYM_CAP_CPU_UTIL(walt_load->pl, wl_other.pl,
						   mpct);

	return (util >= capacity) ? capacity : util;
}
EXPORT_SYMBOL(cpu_util_freq_walt);
static inline unsigned long
__cpu_util_freq_walt(int cpu, struct walt_cpu_load *walt_load, unsigned int *reason)
{
	u64 util;
	struct rq *rq = cpu_rq(cpu);
	unsigned long capacity = capacity_orig_of(cpu);
	struct walt_rq *wrq = (struct walt_rq *) rq->android_vendor_data1;

#if IS_ENABLED(CONFIG_OPLUS_FEATURE_OCH)
	int edtask_flag = 0;
	util = div64_u64(freq_policy_load(rq, reason, &edtask_flag),
				sched_ravg_window >> SCHED_CAPACITY_SHIFT);
	cpufreq_health_get_edtask_state(cpu, edtask_flag);
#else
	util = scale_time_to_util(freq_policy_load(rq, reason));
#endif
	/*
	 * util is on a scale of 0 to 1024.  this is the utilization
	 * of the cpu in the last window
	 */
	wrq->util = util;

	if (walt_load) {
		u64 nl = wrq->nt_prev_runnable_sum +
				wrq->grp_time.nt_prev_runnable_sum;
		u64 pl = wrq->walt_stats.pred_demands_sum_scaled;

		wrq->old_busy_time = util;
		wrq->old_estimated_time = pl;

		nl = scale_time_to_util(nl);
		walt_load->nl = nl;
		walt_load->pl = pl;
		walt_load->ws = walt_load_reported_window;
		walt_load->rtgb_active = rtgb_active;
		walt_load->big_task_rotation = walt_rotation_enabled;
		if (wrq->ed_task)
			walt_load->ed_active = true;
		else
			walt_load->ed_active = false;
	}

	return (util >= capacity) ? capacity : util;
}
static inline u64 scale_time_to_util(u64 d)
{
	/*
	 * The denominator at most could be (8 * tick_size) >> SCHED_CAPACITY_SHIFT,
	 * a value that easily fits a 32bit integer.
	 */
	do_div(d, walt_scale_demand_divisor);
	return d;
}
#if IS_ENABLED(CONFIG_OPLUS_FEATURE_OCH)
static inline u64 freq_policy_load(struct rq *rq, unsigned int *reason, int *edtask_flag)
#else
static inline u64 freq_policy_load(struct rq *rq, unsigned int *reason)
#endif
{
	struct walt_rq *wrq = (struct walt_rq *) rq->android_vendor_data1;
	struct walt_sched_cluster *cluster = wrq->cluster;
	u64 aggr_grp_load = cluster->aggr_grp_load;
	u64 load, tt_load = 0, kload = 0;
	struct task_struct *cpu_ksoftirqd = per_cpu(ksoftirqd, cpu_of(rq));

#if IS_ENABLED(CONFIG_OPLUS_FEATURE_OCH)
	if (wrq->ed_task != NULL) {
		*edtask_flag = 1;
	}
#endif
	if (sched_freq_aggr_en) {
		load = wrq->prev_runnable_sum + aggr_grp_load;
		*reason = CPUFREQ_REASON_FREQ_AGR;
	}
	else
		load = wrq->prev_runnable_sum +
					wrq->grp_time.prev_runnable_sum;

	if (cpu_ksoftirqd && READ_ONCE(cpu_ksoftirqd->__state) == TASK_RUNNING) {
		kload = task_load(cpu_ksoftirqd);
		if (kload > load) {
			load = kload;
			*reason = CPUFREQ_REASON_KSOFTIRQD;
		}
	}

	tt_load = top_task_load(rq);
	if (tt_load > load) {
		load = tt_load;
		*reason = CPUFREQ_REASON_TT_LOAD;
	}

	if (should_apply_suh_freq_boost(cluster)) {
		if (is_suh_max())
			load = sched_ravg_window;
		else
			load = div64_u64(load * sysctl_sched_user_hint,
					 (u64)100);
		*reason = CPUFREQ_REASON_SUH;
	}

	trace_sched_load_to_gov(rq, aggr_grp_load, tt_load, sched_freq_aggr_en,
				load, 0, walt_rotation_enabled,
				sysctl_sched_user_hint, wrq, *reason);
	return load;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿知

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值