boosted_task_util實際上包含兩個部分,當前task的util加上margin值,margin就是將util的值給他擴大或者縮小一定的倍數
boosted_task_util
static inline unsigned long
boosted_task_util(struct task_struct *task)
{
unsigned long util = task_util_est(task);//這裏我們假設walt機制是open的
long margin = schedtune_task_margin(task);//margin就是sign除以100
trace_sched_boost_task(task, util, margin);//添加到內核trace log裏面
return util + margin;
}
task_util & task_util_est
task util = demand *1024 / window_size ---其中demand爲WALT機制中sum_history數組得到的max(latest值,平均值),window_size則是WALT機制中window的大小(默認爲20ms)
未開啓boost = (delta / window_size) * (cur_freq / max_freq) * cpu_max_capacity ---delta是task在一個window中運行的真實時間;cur_freq爲cpu當前頻率;max_freq爲cpu最大頻率;
開啓boost task util也會進行變化。公式如下:
boosted task util = task_util +(1024 - task_util)* boost_percent ---boost_percent是schedtune中配置的boost百分比
static inline unsigned long task_util(struct task_struct *p)
{
#ifdef CONFIG_SCHED_WALT
if (likely(!walt_disabled && sysctl_sched_use_walt_task_util))
return (p->ravg.demand /
(walt_ravg_window >> SCHED_CAPACITY_SHIFT));
#endif
return READ_ONCE(p->se.avg.util_avg);
}
Task utilization 的估算也是依賴walt進行窗口的統計
static inline unsigned long task_util_est(struct task_struct *p)
{
#ifdef CONFIG_SCHED_WALT
if (likely(!walt_disabled && sysctl_sched_use_walt_task_util))
return (p->ravg.demand /
(walt_ravg_window >> SCHED_CAPACITY_SHIFT));
#endif
return max(task_util(p), _task_util_est(p));
}
_task_util_est
task util是用來表示一個task大小,它會佔用cpu多少算力,或者說是給cpu造成多少負載的體現
static inline unsigned long _task_util_est(struct task_struct *p)
{
struct util_est ue = READ_ONCE(p->se.avg.util_est);//這裏應該是讀取一次一個數據結構的宏
return max(ue.ewma, ue.enqueued);
}
關於struct util_est,可以看https://blog.csdn.net/feifei_csdn/article/details/107106149
struct util_est {
unsigned int enqueued;入隊列時估算的task的效力
unsigned int ewma;指數加權動態的平均task的效力
schedtune_task_margin
static inline long
schedtune_task_margin(struct task_struct *task)
{
int boost = schedtune_task_boost(task);//返回的應該是我們設置的值-100到100
unsigned long util;
long margin;
if (boost == 0)
return 0;
util = task_util_est(task);
margin = schedtune_margin(util, boost);//對util進行一定的縮放
return margin;
}
schedtune_margin
對uti進行成比例的縮放
unsigned int spc_threshold = 100;
struct reciprocal_value schedtune_spc_rdiv;
static long
schedtune_margin(unsigned long signal, long boost)
{
long long margin = 0;
/*
* Signal proportional(成比例的) compensation(補償)(SPC)
*
* The Boost (B) value is used to compute a Margin (M) which is
* proportional to the complement of the original Signal (S):
* M = B * (SCHED_CAPACITY_SCALE - S)
* The obtained M could be used by the caller to "boost" S.
*/
if (boost >= 0) {
if (signal < spc_threshold)
margin = signal * boost;
else {
margin = SCHED_CAPACITY_SCALE - signal;
margin *= boost;
}
} else
margin = -signal * boost;
margin = reciprocal_divide(margin, schedtune_spc_rdiv);
// reciprocal_divide是計算A/B的優化函數
if (boost < 0)
margin *= -1;
return margin;
}