UCOSII学习笔记——任务调度机制
任务堆栈初始化和OS_TCB初始化完成后,需要将新创建的任务挂载到就绪队列,以便供OS_Sched调度。
那么如何完成任务挂载到就绪队列中?
为描述就绪队列,作者没有使用传统的双向链表,而是采用优先级位图的方式。何为优先级位图?上述代码段中的两个变量OSRdyGrp
和OSRdyTbl
实现了优先级位图。也就是利用这两个变量构成了一个8*8的表格,一个64个,代表64个任务的优先级。就绪队列的每个任务优先级由OSRdyGrp
和OSRdyTbl
组成。在OSRdyGrp
中,任务按照优先级分组,每8个优先级为1组,一共8组,OSRdyGrp
的每一位对应了8个组中的某一组。OSRdyTbl[x]
表示每组中的8个优先级。另外,下标x
与OSRdyGrp
的第x
组对应。因此由这两个变量映射出优先级表如下图。
举例说明:
加入创建某个任务优先级prio = 11,从上图中可以看出11位于第一行第三列,根据前述,OSRdyGrp
的第1位置1,OSRdyTbl[1]
的第3位置1。
挂载任务
为能将任务快速的挂至就绪表,引入了数组OsMapTbl[8]
,每个元素取值如下表。任务挂载就绪表,其实就是上述举例的过程:优先级为11的任务,OSRdyGrp
的第1位置1,OSRdyTbl[1]
的第3位置1。将11写为二进制数00 001 011,最高两位去掉为001 011,其中高三位001,用来表示行,这里表示第1行,也就是OSRdyGrp
的第1位;低三位011,用来表示列,即是第三列,也就是OSRdyTbl[1]
的第3位。
挂载的实现代码
OSRdyGrp|= OSMapTbl[prio>>3]; //挂载任务到就绪队列
OSRdyTbl[prio>>3] |= OSMapTbl[prio&0x07];
如何从优先级就绪表中选取优先级最高的就绪任务?
UCOSII是多任务实时系统,当系统中有多个就绪任务时,需要从优先级就绪表中选定优先级最高的任务运行。有任务被创建时,OSRdyGrp
和OSRdyTbl
中某位会被置一,优先级越高OSRdyGrp
被置1的位数越小。例如,有优先级11和17两个任务,优先级11的任务对应OSRdyGrp
的第1位被置1,优先级为17的任务对应OSRdyGrp
的第2位被置1。完成此过程用到了另外一个数组OsUnMapTbl[256]
,它的作用是将0x00~0xff中的每一个数的最低位为1的位数列出来。
通过上述描述,可以通过以下代码找到最高优先级的任务;
y = OSUnMapTbl[OSRdyGrp];
x = OSUnMapTbl[OSRdyTbl[y]];
prio = y<<3 + x;