ucos任务调度
就绪表及优先级相关计算
任务就绪表由2个变量表示
(
OS_EXT INT8U OSRdyGrp; /* Ready list group */
OS_EXT INT8U OSRdyTbl[OS_RDY_TBL_SIZE]; /* Table of tasks which are ready to run */
)
OSRdyGrp:共8bits,用于分组标志
OSRdyTbl[]:共8个字节,字节的每位表示任务的组内标志(每个字节表示一组)。
在OSRdyGrp中,任务按优先级分组,8个任务为一组。OSRdyGrp中的每一位表示8组任务中每一组中是否有进入就绪态的任务。任务进入就绪态时,就绪表OSRdyTbl[]中的相应元素的相应位也置位。就绪表OSRdyTbl[]数组的大小取决于OS_LOWEST_PR1O(见文件OS_CFG.H)。
任务优先级0-63,可用6bits表示。将其分为两部分:高3bits和低3bits。
其中,高3位用于表示该任务所在的组;低3位用于表示该任务组内的位置。
程序清单 L3.5 使任务进入就绪态 |
OSRdyGrp |= OSMapTbl[prio >> 3];//组标志置位 |
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];//组内标志置位 |
(prio>>3的值为任务所在的组,prio&0x07的值表示任务所在的位)
其中OSRdyGrp、OSRdyTbl和OSMapTbl的表示如下图。
uCOS-Ⅱ中的就绪列表使用bitmap的方式进行管理,就绪时对应的bit位置1。
优先级prio的高3位作为组号,低3位作为组内的编号。bitmap的形象如上图所示。
图3.3μC/OS-Ⅱ就绪表
表 T3.1 OSMapTbl[]={0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
|
|
Index |
Bit Mask (Binary) |
0 |
00000001 |
1 |
00000010 |
2 |
00000100 |
3 |
00001000 |
4 |
00010000 |
5 |
00100000 |
6 |
01000000 |
7 |
10000000 |
程序清单 L3.6 从就绪表中删除一个任务 |
if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0) |
OSRdyGrp &= ~OSMapTbl[prio >> 3]; |
以上代码将就绪任务表数组OSRdyTbl[]中相应元素的相应位清零,而对于OSRdyGrp,只有当被删除任务所在任务组中全组任务一个都没有进入就绪态时,才将相应位清零。也就是说OSRdyTbl[prio>>3]所有的位都是零时,OSRdyGrp的相应位才清零。
程序清单 L3.7 找出进入就绪态的优先级最高的任务 |
y = OSUnMapTbl[OSRdyGrp];//优先级最高的所在的组 |
x = OSUnMapTbl[OSRdyTbl[y]];//组内优先级最高的位 |
prio = (y << 3) + x;//还原成优先级 |
为了找到那个进入就绪态的优先级最高的任务,并不需要从OSRdyTbl[0]开始扫描整个就绪任务表,只需要查另外一张表,即优先级判定表OSUnMapTbl([256])(见文件OS_CORE.C)。OSRdyTbl[]中每个字节的8位代表这一组的8个任务哪些进入就绪态了,低位的优先级高于高位。利用这个字节为下标来查OSUnMapTbl这张表,返回的字节就是该组任务中就绪态任务中优先级最高的那个任务所在的位置。这个返回值在0到7之间。
OSUnMapTbl中的每个元素表示0x00~0xFF的每个数的二进制表示中最低位1出现的位置