中断处理完毕后,系统有三种执行流向:                                                                               
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的更多相关文章

  1. Linux进程核心调度器之主调度器schedule--Linux进程的管理与调度(十九)

    主调度器 在内核中的许多地方, 如果要将CPU分配给与当前活动进程不同的另一个进程, 都会直接调用主调度器函数schedule, 从系统调用返回后, 内核也会检查当前进程是否设置了重调度标志TLF_N ...

  2. 一个简单的Python调度器Schedule

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  3. 调度器的实现、schedule、switch_context、switch_to

    根据<深入Linux内核架构>和Linux-3.10.1内核源码,记一些调度过程的主体工作. 调度器任务:CPU数目比要运行的进程数目少,需要程序之间共享CPU时间,创造并行执行的错觉.分 ...

  4. linux cfs调度器_理论模型

    参考资料:<调度器笔记>Kevin.Liu <Linux kernel development> <深入Linux内核架构> version: 2.6.32.9 下 ...

  5. Linux核心调度器之周期性调度器scheduler_tick--Linux进程的管理与调度(十八)

    我们前面提到linux有两种方法激活调度器:核心调度器和 周期调度器 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测是否有必要 因 ...

  6. cocos2d调度器(定时执行某函数)

    调度器(scheduler) 继承关系 原理介绍 Cocos2d-x调度器为游戏提供定时事件和定时调用服务.所有Node对象都知道如何调度和取消调度事件,使用调度器有几个好处: 每当Node不再可见或 ...

  7. (5)调度器(scheduler)

    继承关系 原理介绍 Cocos2d-x调度器为游戏提供定时事件和定时调用服务.所有Node对象都知道如何调度和取消调度事件,使用调度器有几个好处: 每当Node不再可见或已从场景中移除时,调度器会停止 ...

  8. Erlang/OTP 17.0-rc1 新引入的"脏调度器"浅析

    最近在做一些和 NIF 有关的事情,看到 OTP 团队发布的 17 rc1 引入了一个新的特性“脏调度器”,为的是解决 NIF 运行时间过长耗死调度器的问题.本文首先简单介绍脏调度器机制的用法,然后简 ...

  9. 【Cocos2d-x 3.x】 调度器Scheduler类源码分析

    非个人的全部理解,部分摘自cocos官网教程,感谢cocos官网. 在<CCScheduler.h>头文件中,定义了关于调度器的五个类:Timer,TimerTargetSelector, ...

随机推荐

  1. JAVA-数据库之更新记录

    相关资料:<21天学通Java Web开发> 更新记录 StatementUpdate.jsp <%@ page language="java" contentT ...

  2. [转]使用Navicat导入导出数据库表

    原文地址:https://blog.csdn.net/anselandevil/article/details/81667199 步骤1:数据中原始数据如下: 点击表,右键选择导出向导,选择导出为sq ...

  3. [转]oracle存储过程中update不成功的一个原因

    原文地址:http://lin49940.iteye.com/blog/466626 今天一个同事写oracle 的存储过程遇到了一个问题, 他在里面update 操作不能完成更新的操作, 但是又不会 ...

  4. ResponderChain note

    http://ww3.sinaimg.cn/large/6b288462gw1evl4h40tfxj20sg0lc77k.jpg

  5. LInux 文件系统 tmpfs 分区不显示解决

    因为不小心把 kernel 的 tmpfs 的选项去掉,导致 文件系统内的 tmpfs 分区不显示. kernel 打开如下选项即可 在文件系统内就会有相关显示

  6. Badboy+Jmeter进行性能测试

    摸索了两天,终于搞定! 目的:使用Badboy和Jmeter添加5000个系统用户 一开始用Badboy进行批量添加,想先在excel中准备好5000个用户名,再导入到Badboy中.但是一直不成功, ...

  7. android——官方下拉刷新组件SwipeRefreshLayout(转)

    一.问题描述 在android开发中,使用最多的数据刷新方式就是下拉刷新了,而完成此功能我们使用最多的就是第三方的开源库PullToRefresh.现如今,google也忍不住推出了自己的下拉组件Sw ...

  8. xcode从8升级到9出现的问题

    为了使用iOS11,升级了xcode结果,TensorStorage.h里面报错,修改如下: https://stackoverflow.com/questions/46356153/xcode-9- ...

  9. 网页QQ弹出

    <script language="javascript"> function cdyht(){ window.location.href='tencent://Mes ...

  10. 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 ...