【WALT】WALT入口 update_task_ravg() 代码详解
【WALT】WALT入口 update_task_ravg() 代码详解
代码版本:Linux4.9 android-msm-crosshatch-4.9-android12
代码展示
void update_task_ravg(struct task_struct *p, struct rq *rq, int event,
u64 wallclock, u64 irqtime) {
u64 old_window_start;
// ⑴ 判断是否进入 WALT 算法
if (!rq->window_start || sched_disable_window_stats ||
p->ravg.mark_start == wallclock)
return;
lockdep_assert_held(&rq->lock);
// ⑵ 获取 WALT 算法中上一个窗口的开始时间
old_window_start = update_window_start(rq, wallclock, event);
// ⑶ 如果任务刚初始化结束,不进入 WALT 算法,进入 `done`
if (!p->ravg.mark_start) {
update_task_cpu_cycles(p, cpu_of(rq), wallclock);
goto done;
}
// ⑷ 更新任务及 CPU 的 cycles
update_task_rq_cpu_cycles(p, rq, event, wallclock, irqtime);
// ⑸ 更新任务及 CPU 的 demand 及 pred_demand
update_task_demand(p, rq, event, wallclock);
// ⑹ 更新 CPU 的 busy time
update_cpu_busy_time(p, rq, event, wallclock, irqtime);
// ⑺ 更新任务的 pred_demand
update_task_pred_demand(rq, p, event);
// ⑻ 如果任务正在退出,进入 `done`
if (exiting_task(p))
goto done;
// 两个系统自带的 tracepoint
trace_sched_update_task_ravg(p, rq, event, wallclock, irqtime,
rq->cc.cycles, rq->cc.time, &rq->grp_time);
trace_sched_update_task_ravg_mini(p, rq, event, wallclock, irqtime,
rq->cc.cycles, rq->cc.time, &rq->grp_time);
done:
p->ravg.mark_start = wallclock;
run_walt_irq_work(old_window_start, rq);
}
代码逻辑
WALT 算法以任务为主,当任务被唤醒、任务开始执行、任务停止执行、任务退出、窗口滚动、频率变化、任务迁移、经过一个调度tick、在中断结束时会调用update_task_ravg()。
其中,窗口是 WALT 算法中的一个特殊的设定,将在 update_task_demand() 与 update_cpu_busy_time() 中详细解释。
⑴ 判断是否进入 WALT 算法
在进入 WALT 算法后首先会判断当前任务所在的运行队列(runqueue)是否进行初始化,以及是否禁用 CPU 的窗口统计:if(!rq->window_start || sched_disable_window_stats...)。如果没有初始化,就不会记录窗口的开始时间,任务负载就无法进行计算。有几点需要注意:
- 该处是指 rq,而非 cfs->rq 或 rt->rq,即该处不区分实时任务或普通任务;
- 任务/CPU 窗口(sched_ravg_window)是自定义的,不同版本代码或不同设备中设置的窗口大小是不一样的,调整的位置也不尽相同。
然后会判断窗口开始时间是否更新:if(...p->ravg.mark_start == wallclock)。如果运行队列没有初始化,或禁用了 CPU 的窗口统计,或窗口开始时间没有更新,就会直接结束 WALT 算法。
⑵ 获取 WALT 算法中上一个窗口的开始时间
然后通过函数update_window_start()获取上一个窗口的开始时间,存在变量old_window_start中。
点击此处查看 update_window_start() 代码详解。
⑶ 如果任务刚初始化结束
如果任务刚初始化结束:if(!p->ravg.mark_start),还没有标记过任务的开始时间,就先通过函数 update_task_cpu_cycles() 更新一下该任务的 cycles 值(p->cpu_cycles),然后进入 done。
点击此处查看 update_task_cpu_cycles() 代码详解。
⑷ 更新任务及 CPU 的 cycles
和 update_task_cpu_cycles() 相似,但比其多更新了 CPU 的 cycles 值(rq->cc.cycles)。
点击此处查看 update_task_rq_cpu_cycles() 代码详解。
⑸ 更新任务及 CPU 的 demand 及 pred_demand
在任务满足条件后,在不同情况下根据任务的开始时间、窗口的开始时间以及当前时间来计算任务在当前及之前M个窗口中的运行时间。在窗口结束时将运行时间进行归一化,并统计进任务的历史窗口中(sum_history[RAVG_HIST_SIZE])。
WALT 算法根据历史窗口中的值计算任务的 demand,根据桶算法计算任务的 pred_demand,并将 demand 与 pred_demand 统计进任务所在 CPU 的 rq(runqueue)中。
注意:以上说的 demand 与 pred_demand 都是预测值。
点击此处查看 update_task_demand() 代码详解。
⑹ 更新 CPU 的 busy time
在任务满足条件后,在不同情况下根据任务的开始时间、窗口的开始时间以及当前时间来计算任务在当前及上一个窗口中的运行时间,将不同窗口内的运行时间进行归一化,并根据任务的状态统计进任务的 curr_window 和 prev_window 中,以及任务所在 rq 的 curr_runnable_sum 和 prev_runnable_sum 中。
在窗口翻滚的时候更新任务的 window 值 以及 rq 的 runnable_sum 的值。
注意:以上说的 window 以及 runnable_sum 都是真实值。
点击此处查看 update_cpu_busy_time() 代码详解。
⑺ 更新任务的 pred_demand
如果符合条件的任务在当前窗口中预测出来的 demand 值小于 curr_window,则再次使用桶算法计算 pred_demand。
点击此处查看 update_task_pred_demand() 代码详解。
⑻ 如果任务正在退出
#define EXITING_TASK_MARKER 0xdeaddead
static inline int exiting_task(struct task_struct *p)
{
return (p->ravg.sum_history[0] == EXITING_TASK_MARKER);
}
当任务最近一个窗口的值为 0xdeaddead 时,意味着任务正在退出,进入 done。
done 结束部分:
- 更新一下任务的开始时间:
p->ravg.mark_start = wallclock。 - 通过函数
irq_work_queue()处理没有 tick 的情况,循环调用update_task_ravg()。
【WALT】WALT入口 update_task_ravg() 代码详解的更多相关文章
- ARM Cortex-M底层技术(2)—启动代码详解
杂谈 工作了一天,脑袋比较乱.一直想把底层的知识写成一个系列,希望可以坚持下去.为什么要写底层的东西呢?首先,工作用到了这部分内容,最近和内部Flash打交道比较多,自然而然会接触到一些底层的东西:第 ...
- BM算法 Boyer-Moore高质量实现代码详解与算法详解
Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...
- ASP.NET MVC 5 学习教程:生成的代码详解
原文 ASP.NET MVC 5 学习教程:生成的代码详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 ...
- Github-karpathy/char-rnn代码详解
Github-karpathy/char-rnn代码详解 zoerywzhou@gmail.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2016-1-10 ...
- 代码详解:TensorFlow Core带你探索深度神经网络“黑匣子”
来源商业新知网,原标题:代码详解:TensorFlow Core带你探索深度神经网络“黑匣子” 想学TensorFlow?先从低阶API开始吧~某种程度而言,它能够帮助我们更好地理解Tensorflo ...
- JAVA类与类之间的全部关系简述+代码详解
本文转自: https://blog.csdn.net/wq6ylg08/article/details/81092056类和类之间关系包括了 is a,has a, use a三种关系(1)is a ...
- Java中String的intern方法,javap&cfr.jar反编译,javap反编译后二进制指令代码详解,Java8常量池的位置
一个例子 public class TestString{ public static void main(String[] args){ String a = "a"; Stri ...
- Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测
Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测 2017年12月13日 17:39:11 机器之心V 阅读数:5931 近日,Artur Suilin 等人发布了 Kaggl ...
- 基础 | batchnorm原理及代码详解
https://blog.csdn.net/qq_25737169/article/details/79048516 https://www.cnblogs.com/bonelee/p/8528722 ...
- 非极大值抑制(NMS,Non-Maximum Suppression)的原理与代码详解
1.NMS的原理 NMS(Non-Maximum Suppression)算法本质是搜索局部极大值,抑制非极大值元素.NMS就是需要根据score矩阵和region的坐标信息,从中找到置信度比较高的b ...
随机推荐
- idea 热部署插件JRebel
idea 热部署插件JRebel 当开始开发web项目的时候,需要频繁的修改web页面,此时如果频繁的重启变得很麻烦,因此,可以在idea中集成JRebel插件,改动代码之后不需要重新启动应用程序 ...
- [Linux]CentOS7:创建OS用户+授予sudo权限
1 创建OS用户+授予sudo权限 Step1 下载安装Xshell.Xftp工具 Step2 通过Xshell,远程登陆服务器root用户 Step3 使用检查用户的命令查询当前linux环境是否存 ...
- 让代码变得优雅简洁的神器:Java8 Stream流式编程
原创/朱季谦 本文主要基于实际项目常用的Stream Api流式处理总结. 因笔者主要从事风控反欺诈相关工作,故而此文使用比较熟悉的三要素之一的[手机号]黑名单作代码案例说明. 我在项目当中,很早就开 ...
- Java设计模式 —— 工厂模式
3 简单工厂模式 3.1 创建型模式 Creational Pattern 关注对象的创建过程,对类的实例化过程进行了抽象,将软件模块中对象的创建和对象的使用分离,对用户隐藏了类的实例的创建细节.创建 ...
- day64:Linux:nginx模块之限制连接&状态监控&Location/用nginx+php跑项目/扩展应用节点
目录 1.nginx模块:限制连接 limit_conn 2.nginx模块:状态监控 stub_status 3.nginx模块:Location 4.用nginx+php跑wordpress项目 ...
- 这样也行,在lambda表达式中优雅的处理checked exception
目录 简介 lambda表达式中的checked exception lambda中的unchecked exception 对lambda的最终改造 总结 简介 最近发现很多小伙伴还不知道如何在la ...
- django restframework的简单使用
django restframework的简单使用 1.快速上手 配置: (pip install djangorestframework==3.12.4) # settings.py INSTALL ...
- VUE3企业级项目基础框架搭建流程(3)
VUE-Router npm install vue-router@4 安装完成后,在项目目录里新建一个router文件,我这里的用的是typeScript,所以建立的是router.ts, 该文件是 ...
- 开心档之MySQL ALTER命令
MySQL ALTER命令 当我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQL ALTER命令. 开始本章教程前让我们先创建一张表,表名为:testalter_tbl. root@ho ...
- 浅谈php GC(垃圾回收)机制及其与CTF的一点缘分
0x00 侠客日常(一):CTF江湖试剑 众所周知,在php中,当对象被销毁时会自动调用__destruct()方法,同时也要知道,如果程序报错或者抛出异常,则就不会触发该魔术方法. 看题: < ...