昨天講到了利用兩個查表的方式來計算,會比直接計算來的節省運算資源,今天就來看看到底要vruntime到底要怎麼計算。
vruntime 的公式如下
將2^32 / weight 用 inv_weight取代,就變成以下的式子
這部分的計算出現在 kernel/sched/fair.c
內的cal_delta_fair()
static inline u64 calc_delta_fair(u64 delta, struct sched_entity *se)
{
if (unlikely(se->load.weight != NICE_0_LOAD))
delta = __calc_delta(delta, NICE_0_LOAD, &se->load);
return delta;
}
static u64 __calc_delta(u64 delta_exec, unsigned long weight, struct load_weight *lw) /// calculate delta
{
u64 fact = scale_load_down(weight);
u32 fact_hi = (u32)(fact >> 32);
int shift = WMULT_SHIFT;
int fs;
__update_inv_weight(lw);
if (unlikely(fact_hi)) {
fs = fls(fact_hi);
shift -= fs;
fact >>= fs;
}
fact = mul_u32_u32(fact, lw->inv_weight);
fact_hi = (u32)(fact >> 32);
if (fact_hi) {
fs = fls(fact_hi);
shift -= fs;
fact >>= fs;
}
return mul_u64_u32_shr(delta_exec, fact, shift);
}
以上的部分就是就是vruntime的計算方式,以及其相關的函數。
以上的部分就是就是vruntime的計算方式,以及其相關的函數。
最後提一下在 task_struct
裡面關於排程的重要數據結構 sched_entity
,在這個結構裡面包含了所有排程所需要的資訊。
struct sched_entity {
/* For load-balancing: */
struct load_weight load; //排程的權重
struct rb_node run_node;
struct list_head group_node;
unsigned int on_rq;
u64 exec_start;
u64 sum_exec_runtime;
u64 vruntime;
u64 prev_sum_exec_runtime;
u64 nr_migrations;
struct sched_statistics statistics;
#ifdef CONFIG_FAIR_GROUP_SCHED
int depth;
struct sched_entity *parent;
/* rq on which this entity is (to be) queued: */
struct cfs_rq *cfs_rq;
/* rq "owned" by this entity/group: */
struct cfs_rq *my_q;
/* cached value of my_q->h_nr_running */
unsigned long runnable_weight;
#endif
#ifdef CONFIG_SMP
/*
* Per entity load average tracking.
*
* Put into separate cache line so it does not
* collide with read-mostly values above.
*/
struct sched_avg avg;
#endif
};