博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
主调度器schedule
阅读量:6681 次
发布时间:2019-06-25

本文共 3310 字,大约阅读时间需要 11 分钟。

中断处理完毕后,系统有三种执行流向:                                                                               

1)直接返回中断前的状态;
2)系统重新进行调度;
3)进行信号处理;
我们此处重点关注:在用户态下发生scheduler_tick,且已判定当前进程可被抢占的情形(此处以ARM为例)。

__irq_usr:#......b ret_to_user_from_irqENTRY(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 = 0;               |----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来返回值进而赋值是很好的选择。          

转载地址:http://kbnao.baihongyu.com/

你可能感兴趣的文章
Scramble String
查看>>
LeetCode:Binary Tree Level Order Traversal II (按层遍历)
查看>>
2 虚拟机Oracle11.2.0.4服务器端,第三方图形化界面安装步骤
查看>>
Python全栈开发-Day5-常用模块学习
查看>>
Mac OS下配置PHP Nginx PHP-FPM
查看>>
Linux基础:CentOS安装python3.7
查看>>
Daily Scrum: 2012/11/27
查看>>
vue学习中v-if和v-show一起使用的问题
查看>>
获取一个月前的当前时间
查看>>
第三期 预测——1.简介
查看>>
behavior planning——12.example cost funtion -lane change penalty
查看>>
基于 Spring + Atomikos + Mybatis的多数据源配置demo
查看>>
随笔-刚毕业找工作的点滴(程序员)
查看>>
利用poi3.8中SXSSFWorkbook实现大数据量导出excel
查看>>
day34-1 面向对象概述
查看>>
GCD之dispatch queue
查看>>
【Oracle】-初识PL/SQL
查看>>
黄聪:超实用的PHPExcel[导入][导出]实现方法总结
查看>>
模板变量,过滤器和静态文件引入
查看>>
Oracle 中的 Schema
查看>>