主调度器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, ...
随机推荐
- JAVA-数据库之更新记录
相关资料:<21天学通Java Web开发> 更新记录 StatementUpdate.jsp <%@ page language="java" contentT ...
- [转]使用Navicat导入导出数据库表
原文地址:https://blog.csdn.net/anselandevil/article/details/81667199 步骤1:数据中原始数据如下: 点击表,右键选择导出向导,选择导出为sq ...
- [转]oracle存储过程中update不成功的一个原因
原文地址:http://lin49940.iteye.com/blog/466626 今天一个同事写oracle 的存储过程遇到了一个问题, 他在里面update 操作不能完成更新的操作, 但是又不会 ...
- ResponderChain note
http://ww3.sinaimg.cn/large/6b288462gw1evl4h40tfxj20sg0lc77k.jpg
- LInux 文件系统 tmpfs 分区不显示解决
因为不小心把 kernel 的 tmpfs 的选项去掉,导致 文件系统内的 tmpfs 分区不显示. kernel 打开如下选项即可 在文件系统内就会有相关显示
- Badboy+Jmeter进行性能测试
摸索了两天,终于搞定! 目的:使用Badboy和Jmeter添加5000个系统用户 一开始用Badboy进行批量添加,想先在excel中准备好5000个用户名,再导入到Badboy中.但是一直不成功, ...
- android——官方下拉刷新组件SwipeRefreshLayout(转)
一.问题描述 在android开发中,使用最多的数据刷新方式就是下拉刷新了,而完成此功能我们使用最多的就是第三方的开源库PullToRefresh.现如今,google也忍不住推出了自己的下拉组件Sw ...
- xcode从8升级到9出现的问题
为了使用iOS11,升级了xcode结果,TensorStorage.h里面报错,修改如下: https://stackoverflow.com/questions/46356153/xcode-9- ...
- 网页QQ弹出
<script language="javascript"> function cdyht(){ window.location.href='tencent://Mes ...
- Spring Cloud / Spring Boot There was an unexpected error (type=Unauthorized, status=401). Full authentication is required to access this resource.
访问EndPoint时会出现没有权限 There was an unexpected error (type=Unauthorized, status=401). Full authenticat ...