主调度器schedule
中断处理完毕后,系统有三种执行流向:
1)直接返回中断前的状态;
2)系统重新进行调度;
3)进行信号处理;
我们此处重点关注:在用户态下发生scheduler_tick,且已判定当前进程可被抢占的情形(此处以ARM为例)。
__irq_usr:
#......
b ret_to_user_from_irq ENTRY(ret_to_user_from_irq)
ldr r1, [tsk, #TI_FLAGS]
#define _TIF_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
tst r1, #_TIF_WORK_MASK ;判定是否有信号需要处理,或者被抢占
bne work_pending
#......
ENDPROC(ret_to_user_from_irq) work_pending:
mov r0, sp @ 'regs'
mov r2, why @ 'syscall'
bl do_work_pending
#......
当do_work_pending中检查thread_info的flags知道当前进程可被抢占时,则启动主调度器schedule
schedule()----prev = rq->curr 但前运行进程
|----next = pick_next_task(rq) 选择下一运行进程
|---->context_switch(rq, prev, next)
context_switch()---->prepare_task_switch(rq, prev, next)
| 更新prev,next的进程信息统计量
|----mm = next->mm; 取得即将被调度进入的进程的内存描述符
|----oldmm = prev->active_mm;
| 取得即将被调度出去的进程的运行时内存描述符。
| 此时需要区分即将被调入的进程是普通进程还是内核线程;
| 被调出的进程是普通进程还是内核线程;
| 引入active_mm的目的在于实现 lazy TLB
| (当我们把运行的进程个数限于2个,一个是普通进程
| 另一个是内核线程时就容易明白了)。
|
| 我们讨论普通情形:即将被调入调出的进程都为普通进程,
| 且oldmm与mm不同,需要切换内存页表。
|----switch_mm(oldmm, mm, next);
| 切换页表,刷TLB (注意假设oldmm与mm不同)
| 对于vivt型cache需要注意对cache的操作
|----switch_to(prev, next, prev);
| cpu_context_save切换(运行到next进程)
| 对于unicore保存r4-r15,r16-r26,
| r27(fp),r29(sp),r30(lr)
| 不需保存r0-r3,r31(pc),r28(ip)
|----finish_task_switch(this_rq(), prev);
| 对被调度出的进程进行相关处理
|---->mmdrop(mm);
更新prev,next的进程信息统计量(注意exec_start,prev_sum_exec_runtime)
prepare_task_switch(rq, prev, next)
|---->sched_info_switch(prev, next)
#ifdef CONFIG_SCHEDSTATS
|----__sched_info_switch(prev, next)
|---->sched_info_depart(prev)
|----prev->sched_info.last_queued = task_rq(t)->clock;
|---->sched_info_arrive(next)
|----t->sched_info.run_delay +=
now - t->sched_info.last_queued;
|----t->sched_info.last_queued = ;
|----t->sched_info.last_arrival = now;
#endif
pick_next_task()---->p = fair_sched_class.pick_next_task(rq);
| 即pick_next_task_fair()
|---->se = pick_next_entity(cfs_rq);
|---- set_next_entity(cfs_rq, se);
|---->update_stats_curr_start(cfs_rq, se);
| 即se->exec_start =
rq_of(cfs_rq)->clock_task;
|---- cfs_rq->curr = se;
|---- se->prev_sum_exec_runtime =
se->sum_exec_runtime;
关于switch_to(prev, next, prev)
《深入Linux架构》p_83-84,83页上的图看懂了,但是84页第三段“因此……”没看明白,和同学讨论了一下:
A->B->C->A,第二次调度进A运行时,确实需要知道上次运行的是C,以便调用finish_task_switch(),其实自己理解错误的原因很低级(只顾着看汇编,自己想多了):
函数UP中有变量a、b,函数UP调用LOW(a,b),很明显UP中的a值没有被改变,如果要改变,则需要a = LOW(a,b);
当然我们也可以用传地址的方式来完成啊,当我尝试用传地址的方式来修改UP中的变量a时,发现我们需要保存即将恢复的进程中a的地址才能在下次运行时通过地址来修改a的值,这并不明智,因此对于unicore或ARM来说通过r0来返回值进而赋值是很好的选择。
主调度器schedule的更多相关文章
- Linux进程核心调度器之主调度器schedule--Linux进程的管理与调度(十九)
主调度器 在内核中的许多地方, 如果要将CPU分配给与当前活动进程不同的另一个进程, 都会直接调用主调度器函数schedule, 从系统调用返回后, 内核也会检查当前进程是否设置了重调度标志TLF_N ...
- 一个简单的Python调度器Schedule
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...
- 调度器的实现、schedule、switch_context、switch_to
根据<深入Linux内核架构>和Linux-3.10.1内核源码,记一些调度过程的主体工作. 调度器任务:CPU数目比要运行的进程数目少,需要程序之间共享CPU时间,创造并行执行的错觉.分 ...
- linux cfs调度器_理论模型
参考资料:<调度器笔记>Kevin.Liu <Linux kernel development> <深入Linux内核架构> version: 2.6.32.9 下 ...
- Linux核心调度器之周期性调度器scheduler_tick--Linux进程的管理与调度(十八)
我们前面提到linux有两种方法激活调度器:核心调度器和 周期调度器 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测是否有必要 因 ...
- cocos2d调度器(定时执行某函数)
调度器(scheduler) 继承关系 原理介绍 Cocos2d-x调度器为游戏提供定时事件和定时调用服务.所有Node对象都知道如何调度和取消调度事件,使用调度器有几个好处: 每当Node不再可见或 ...
- (5)调度器(scheduler)
继承关系 原理介绍 Cocos2d-x调度器为游戏提供定时事件和定时调用服务.所有Node对象都知道如何调度和取消调度事件,使用调度器有几个好处: 每当Node不再可见或已从场景中移除时,调度器会停止 ...
- Erlang/OTP 17.0-rc1 新引入的"脏调度器"浅析
最近在做一些和 NIF 有关的事情,看到 OTP 团队发布的 17 rc1 引入了一个新的特性“脏调度器”,为的是解决 NIF 运行时间过长耗死调度器的问题.本文首先简单介绍脏调度器机制的用法,然后简 ...
- 【Cocos2d-x 3.x】 调度器Scheduler类源码分析
非个人的全部理解,部分摘自cocos官网教程,感谢cocos官网. 在<CCScheduler.h>头文件中,定义了关于调度器的五个类:Timer,TimerTargetSelector, ...
随机推荐
- iOS App中第一次运行添加半透明新手指引
实现方式: 在当前View上一个蒙层,然后找出需要标记的地方圈为白色,那些箭头和提示文字都是UI做出来的图上自带的. 代码: 判断是第一次运行APP后进入页面调用 -(void)newGuide { ...
- iOS - UITableView加载网络图片 cell适应图片高度
使用xib创建自定制cell 显示图片 创建一个继承UITableViewCell的类 勾选xib 如下是xib创建图 xib 向.h拖拽一个关联线 .h .m 2.代码创建(使用三方适配 ...
- python matplotlib 画图
import numpy as np import matplotlib.pyplot as plt from pylab import * numpy 常用来组织源数据: 使用 plot 函数直接绘 ...
- Android 开发自己的网络收音机4——读取XML文件的电台数据
国内外的电台数据很多,起码有好几百,所以把这些数据都写到代码里面是不实际的.只能写成一个数据文件,程序启动的时候再去加载.保存这些简单数据,我们肯定会优先使用XML文件,今天讲讲如何读取XML里面的数 ...
- 【Java】使用BigDecimal类进行精确小数计算
在商业计算中(尤其是计算价格)需要使用BigDecimal类来进行精确小数计算,因为用其他类型计算(如double)得到的结果不是精确的! 写个测试类. import org.junit.Test; ...
- C语言 · 十进制数转八进制数
算法训练 十进制数转八进制数 时间限制:1.0s 内存限制:512.0MB 编写函数把一个十进制数输出其对应的八进制数. 样例输入 9274 样例输出 22072 #includ ...
- Spring WebSocket教程(一)
学习背景 很久以前就知道WebSocket,但那时不论是浏览器还是开发技术对它的支持都还很少.但是,Spring4突然发布,让我眼前一亮,Spring4直接支持WebSocket. 对于Spring我 ...
- Android——关于PagerAdapter的使用方法的总结(转)
PagerAdapter简介 PagerAdapter是android.support.v4包中的类,它的子类有FragmentPagerAdapter, FragmentStatePagerAdap ...
- MVC源码学习之AuthorizeAttribute
常见的Controller定义方式: public class HomeController : Controller { public ActionResult Index() { return V ...
- ashx session 赋值 获取
ashx想获取session值 需要继承 IRequiresSessionState接口 ExcelHelper : IHttpHandler, IRequiresSessionState publi ...