3.0 就绪表(Ready List)
每个任务被赋予不同的优先级等级,从0级到最低优先级OS_LOWEST_PR1O,包括0和OS_LOWEST_PR1O在内(见文件OS_CFG.H)。当uCOS II初始化的时候,最低优先级OS_LOWEST_PR1O总是被赋给空闲任务idle task。注意,最多任务数目OS_MAX_TASKS和最低优先级数是没有关系的。用户应用程序可以只有10个任务,而仍然可以有32个优先级的级别(如果用户将最低优先级数设为31的话)。
每个任务的就绪态标志都放入就绪表中的,就绪表中有两个变量OSRedyGrp和OSRdyTbl[]。在OSRdyGrp中,任务按优先级分组,8个任务为一组。OSRdyGrp中的每一位表示8组任务中每一组中是否有进入就绪态的任务。任务进入就绪态时,就绪表OSRdyTbl[]中的相应元素的相应位也置位。就绪表OSRdyTbl[]数组的大小取决于OS_LOWEST_PR1O(见文件OS_CFG.H)。当用户的应用程序中任务数目比较少时,减少OS_LOWEST_PR1O的值可以降低uCOS II对RAM(数据空间)的需求量。
为确定下次该哪个优先级的任务运行了,内核调度器总是将OS_LOWEST_PR1O在就绪表中相应字节的相应位置1。OSRdyGrp和OSRdyTbl[]之间的关系见图3.3,
是按以下规则给出的:
当OSRdyTbl[0]中的任何一位是1时,OSRdyGrp的第0位置1,
当OSRdyTbl[1]中的任何一位是1时,OSRdyGrp的第1位置1,
当OSRdyTbl[2]中的任何一位是1时,OSRdyGrp的第2位置1,
当OSRdyTbl[3]中的任何一位是1时,OSRdyGrp的第3位置1,
当OSRdyTbl[4]中的任何一位是1时,OSRdyGrp的第4位置1,
当OSRdyTbl[5]中的任何一位是1时,OSRdyGrp的第5位置1,
当OSRdyTbl[6]中的任何一位是1时,OSRdyGrp的第6位置1,
当OSRdyTbl[7]中的任何一位是1时,OSRdyGrp的第7位置1,
一句话:OSRdyTbl[]这个数组的任何一个数非0时,OSRdyGrp相应(通过OSTblMap映射:0-7这八个数字和一个8位的8个位从低到高对应)的位置一。
程序清单3.5中的代码用于将任务放入就绪表。Prio是任务的优先级。
图3.3 uCOS II就绪表
程序清单 L3.5 使任务进入就绪态
代码
- OS_EXT INT8U OSRdyGrp; /* Ready list group */
- OS_EXT INT8U OSRdyTbl[OS_RDY_TBL_SIZE]; /* Table of tasks which are ready to run */
-
- OSRdyGrp |= OSMapTbl[prio >> 3];
- OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];
读者可以看出,任务优先级的低三位用于确定任务在总就绪表OSRdyTbl[]中的所在位。接下去的三位用于确定是在OSRdyTbl[]数组的第几个元素。OSMapTbl[]是在ROM中的(见文件OS_CORE.C)屏蔽字,用于限制OSRdyTbl[]数组的元素下标在0到7之间,见表3.1
表 T3.1
OSMapTbl[]的值
Index |
Bit Mask (Binary) |
0 |
00000001 |
1 |
00000010 |
2 |
00000100 |
3 |
00001000 |
4 |
00010000 |
5 |
00100000 |
6 |
01000000 |
7 |
10000000 |
一句话:
OSTblMap映射:0-7这八个数字和一个8位的8个位从低到高对应
如果一个任务被删除了,则用程序清单3.6中的代码做求反处理。
程序清单 L3.6 从就绪表中删除一个任务
代码
- if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0)
- OSRdyGrp &= ~OSMapTbl[prio >> 3];
以上代码将就绪任务表数组OSRdyTbl[]中相应元素的相应位清零,而对于OSRdyGrp,只有当被删除任务所在任务组中全组任务一个都没有进入就绪态时,才将相应位清零。也就是说OSRdyTbl[prio>>3]所有的位都是零时,OSRdyGrp的相应位才清零。
找到最高优先级任务
为了找到那个进入就绪态的优先级最高的任务,并不需要从OSRdyTbl[0]开始扫描整个就绪任务表,只需要查另外一张表,即优先级判定表OSUnMapTbl([256])(见文件OS_CORE.C)。
OSRdyTbl[]中每个字节的8位代表这一组的8个任务哪些进入就绪态了,低位的优先级高于高位。利用这个字节为下标来查OSUnMapTbl这张表,返回的字节就是该组任务中就绪态任务中优先级最高的那个任务所在的位置。这个返回值在0到7之间。确定进入就绪态的优先级最高的任务是用以下代码完成的,如程序清单L3.7所示。
程序清单 L3.7 找出进入就绪态的优先级最高的任务
代码
- y = OSUnMapTbl[OSRdyGrp];
- x = OSUnMapTbl[OSRdyTbl[y]];
- prio = (y << 3) + x;
例如,如果OSRdyGrp的值为二进制01101000,查OSUnMapTbl[OSRdyGrp]得到的值是3,它相应于OSRdyGrp中的第3位bit3,这里假设最右边的一位是第0位bit0。类似地,如果OSRdyTbl[3]的值是二进制11100100,则OSUnMapTbl[OSRdyTbc[3]]的值是2,即第2位。于是任务的优先级Prio就等于26(3*8+2)。利用这个优先级的值。查任务控制块优先级表OSTCBPrioTbl[],得到指向相应任务的任务控制块OS_TCB的工作就完成了。
INT8U const OSUnMapTbl[256] = {
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00 to 0x0F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x10 to 0x1F */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x20 to 0x2F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x30 to 0x3F */
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x40 to 0x4F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x50 to 0x5F */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x60 to 0x6F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x70 to 0x7F */
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x80 to 0x8F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x90 to 0x9F */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xA0 to 0xAF */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xB0 to 0xBF */
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xC0 to 0xCF */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xD0 to 0xDF */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xE0 to 0xEF */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 0xF0 to 0xFF */
};
Where does this fucking table comes from? How is it made ?!
考虑下:针对就绪表,我们先找到
OSRdyGrp中最小的被置为1的位,也就找到了找到了最高优先级所在的组;然后再在这个组里(
OSRdyTbl[i]的值对应每一位
),
最小的被置为1的位,也就找到了最高优先级任务在所在的位的位置;现在找到了位置如何得到最高优先级的值呢?OSRdyTb这个数组的每一个位对应一个优先级,看看就绪表
X与Y的值和每个小方格的优先级的值有什么关系呢:Priority=8*Y+X
正好对应:
- y = OSUnMapTbl[OSRdyGrp];
- x = OSUnMapTbl[OSRdyTbl[y]];
- prio = (y << 3) + x;
-
OSUnMapTbl数组中元素OSUnMapTbl[n]表示一个任意的8位无符号数n对应的最低位为1的那个最低位数,例如二进制数00000001B最低位为1的是bit0,如是OSUnMapTbl[00000001B] = 0, 又例如1000000B最低位为1的是bit7,所以OSUnMapTbl[10000000B] = 7,及OSUnMapTbl[128]也就是上面OSUnMapTbl第9行第一列为7.
INT8U const OSUnMapTbl[256] 就是个一维数组,也许书中应该这样写:
INT8U const OSUnMapTbl[256]={
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 。。。
}
其中的值对应于其索引最低位为1的那个最低位数。
小结下:上面谈论了四个对象:优先级(值)、就续表(包括OSRdyGrp和OSRdyTbl)、OSMapTbl和OSUnMapTbl。
优先级通过
OSMapTbl和OSUnMapTbl与就绪表进行map和unmap.