代码展示
static u64
update_window_start(struct rq *rq, u64 wallclock, int event)
{
s64 delta;
int nr_windows;
u64 old_window_start = rq->window_start;
// 计算当前时间与窗口开始时间的差值
delta = wallclock - rq->window_start;
/* If the MPM global timer is cleared, set delta as 0 to avoid kernel BUG happening */
// 处理时间回退或重置的情况
if (delta < 0) {
delta = 0;
WARN_ONCE(1, "WALT wallclock appears to have gone backwards or reset\n");
}
// 如果仍在当前窗口内,不需要更新
if (delta < sched_ravg_window)
return old_window_start;
// 计算跨越了多少个完整窗口
nr_windows = div64_u64(delta, sched_ravg_window);
// 更新窗口开始时间
rq->window_start += (u64)nr_windows * (u64)sched_ravg_window;
// 重置累计需求统计
rq->cum_window_demand = rq->walt_stats.cumulative_runnable_avg;
return old_window_start;
}
该函数的主要功能是:
检查并更新运行队列(rq)的时间窗口起始点
处理时间窗口跨越的情况
维护窗口统计数据的连续性
代码逻辑
delta = wallclock - rq->window_start;
wallclock 是进入 WALT 算法时的时间,rq->window_start 是运行队列当前所在窗口的开始时间。
通过 wallclock - rq->window_start ,得到从窗口开始到现在所经过的时间。if (delta < sched_ravg_window) return old_window_start;
sched_ravg_window 是自定义的 WALT 算法的窗口的大小。
如果从窗口开始到现在所经过的时间不到一个窗口的大小,说明窗口还未翻滚,还没有得到新的窗口开始时间,就直接返回久的窗口开始时间。nr_windows = div64_u64(delta, sched_ravg_window);
如果执行到此处,说明窗口已经翻滚,计算从 rq 当前所在窗口的开始时间到现在一共经过了 nr_windows 个完整窗口。rq->window_start += (u64)nr_windows * (u64)sched_ravg_window;
rq 新窗口的开始时间就是旧窗口开始时间加上 nr_windows 个完整窗口的时间。rq->cum_window_demand = rq->walt_stats.cumulative_runnable_avg;
更新 rq 的累积的 demand,rq->walt_stats.cumulative_runnable_avg
详细计算将在详解 update_task_demand() 中介绍。return old_window_start;
就算更新了 rq 的窗口开始时间,也先返回旧的窗口开始时间。