2.4 任务就绪表及任务调度
多任务操作系统核心是任务调度。
当某个任务处于就绪状态时,系统将该任务登记在就绪表中,在就绪表对应位置置1.
2.4.1 任务就绪表结构
2.4.2 对任务就绪表的操作
1. 将优先级别为prio的任务置为就绪状态
OSRdyGrp |= OSMapTbl[prio >> 3];
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];
其中,OSMapTbl[]是加速运算速度定义的一个数组,其各元素值为:
1. 使优先级别为prio的任务脱离就绪状态:
if((OSRdyTbl[prio >> 3] & -OSMapTbl[prio & 0x07])== 0)
OSRdyGrp &=-OSMapTbl[prio >> 3];
3. 从任务就绪表中获取优先级别高的就绪任务:
y = OSUnMapTal[OSRdyGrp];//获取优先级别的D5、D4、D3位
x = OSUnMapTal[OSRdyTbl[y]];//获取优先级别的D2、D1、D0位
prio = (y << 3) + x;//获取就绪任务的优先级别
或
y = OSUnMapTbl[OSRdyGrp];
prio = (INTBU) ((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
其中,OSUnMapTbl[]同样是提高查找速度的一个数组,共有256个元素。
1.4.3 任务调度
任务切换:令CPU中止当前正在运行的任务转而去运行另一个任务
任务的调度:按某种规则进行任务切换
任务调度器:在就绪表中查找优先级别最高的就绪任务;
实现任务的切换:获取待运行任务的TCB指针、进行断点数据切换
任务级调度器:OSSched()
中断级调度器:OSIntExt()
1. 获得待运行就绪任务控制块的指针
操作系统通过任务控制块TCB来管理任务,被中止任务的任务控制块指针存放在全局变量OSTCBCur中,所以调度器主要获取待运行就绪任务控制块的指针。
通过OSSchedLock()和OSSchedUnlock()函数给调度器上锁和解锁,上锁一次,变量OSLockNexting加1;解锁一次,变量OSLockNexting减1。
2. 任务切换宏OS_TASK_SW()
断点:任务被中止运行时的位置
断点数据:当时存放在CPU的PC、PSW和通用寄存器等各寄存器中的数据
一个被中止的任务能否正确地在断点处恢复运行,关键在于能否正确地在CPU各寄存器中恢复断点数据;能否正确恢复断点数据的关键在于CPU的堆栈指针SP是否有正确的指向。
任务的切换就是断点数据的切换,断点数据的切换也就是CPU堆栈指针的切换。
OSCtxSW()的7项工作:
1. 断点指针保存到任务堆栈
2. CPU通用寄存器的内容保存到任务堆栈
3. 被中止任务的任务堆栈指针当前值保存到该任务的任务控制块的OSTCBStkPtr中
4. 获得待运行任务的任务控制
5. CPU获得待运行任务的任务堆栈指针
6. 将待运行任务堆栈中通用寄存器的内容恢复到CPU通用寄存器中
7. 使CPU获得待运行任务的断点指针
对于被中止任务:把任务的断点指针压入任务堆栈
对于待运行任务:把任务堆栈里上次任务被中止时存放在堆栈中的中断指针推入PC寄存器。
通过改变PC值的指令实现出栈和入栈。