1、任务的优先级
|<--- 在OSRdyGrp中的位置 ---->|<--- 在OSRdyTbl 中的位置 --->|
2、任务就绪表( ready list )
任务就绪表由两个变量说明:OSRdyGrp 和 OSRdyTbl[] 。其中 OSRdyGrp 是一个一字节的变量,OSRdyTbl[]是一个元素为单字节的数组。所以,在 OSRdyTbl[] 数组中,每一个字节就代表有 8 个任务,即 8 个任务为一个任务组---这体现在OSRdyGrp 的位中。所以:
当 OSRdyTbl[x] 中的任何一位是 1 时,OSRdyGrp 的第 x 位置 1。 如定义最低优先级的任务为 OS_LOWEST_PRIO,那么OSRdyTbl[] 中就有 OS_LOWEST_PRIO/8+1 个元素。
( 当组织 8 个任务为一组时,当 XXX 为 111 再向 Y 位进 1 时,就是移到第二组,所以 YYY 为组号,最多7组 )
3、OSMapTbl[] 的值
OSMapTbl[] 的值如下表:
下标 | 位掩码(二进制) | 0 | 00000001 | 1 | 00000010 | 2 | 00000100 | 3 | 00001000 | 4 | 00010000 | 5 | 00100000 | 6 | 01000000 | 7 | 10000000 |
4、使任务进入就绪态
OSRdyGrp |= OSMapTbl[ prio >> 3 ]; // 取得组号
OSRdyTbl |= OSMapTbl[ prio & 0x07]; // 取得所在组中的位置
5、使任务脱离就绪态
要使一个任务脱离就绪态,则做求反处理:
if ( ( OSRdyTbl[ prio >> 3 ] &= ~OSMapTbl[ prio & 0x07 ) == 0 )
OSRdyGrp &= ~OSMapTbl[ prio >> 3]; 说明:OSRdyTbl[ prio >> 3 ] &= ~OSMapTbl[ prio & 0x07 把OSRdyTbl 中的相应组中的已就绪任务位取反为0,任务就此脱离就绪态。if语句判断取消了这个就绪任务后,这个任务组是否还有就绪的任务,假如没有,则任务组位置 0,也就是说劝阻任务一个都没有进入就绪态时,才将相应位清0 。
6、迅速找出就绪态优先级最高的任务
利用 OSUnMapTbl[] 表即可迅速的查出优先级最高的任务:INT8U const OSUnMapTbl[] = {
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 */
}; 查表算法:
y = OSUnMapTbl[ OSRdyGrp ];
x = OSUnMapTbl[ OSRdyTbl[y] ];
piro = ( y << 3 ) + x;
说明:
OSRdyTbl[] 中每个字节的 8 位代表了这一组的 8 个任务哪些进入了就绪态,低位的优先级高于高位的优先级。利用这个字节的下标来查 OSUnMapTbl 这张表,返回的字节就是该组任务中就绪态任务中优先级最高的任务所在的位置。
在上面的查表算法中,
假设 OSRdyGrp 的二进制值为 01101000,即 0x68,也就是说,第3,第5,第6 任务组中有就绪的任务。那么最高优先级的任务必定在第 3 组中。那么按照 OSUnMapTbl[ OSRdyGrp ] 去查表所得的值必定为 3 (表就是这样定制下来的)。所以,所得的 y = 3 。
接着,
OSRdyTbl[y] 所得的值为第 y 组的任务状态描述值(所谓状态描述值,就是其值包含着 就绪态任务 和未就绪态任务两种任务态的总值)。假设这个值的二进制形式为:11100100。这个值表示,第三组任务中,第2,第5,第6,第7个任务处于就绪态,那么第 2个任务就是最高优先的任务了!所以在表中所查到的值必定也要为2,故 x=2。
综上所得,最高优先级的任务是第 3 任务组中的第 2 个任务。那么它的优先级就为:
y * 8 + 2 or y << 3 + 2
( 原算法用移位做乘法是因为移位的乘法比直接MUL指令成有更快的执行速度 ) |