优先级位图算法详解

1:OSRdyGrp、OSRdyTbl[]和OSMapTbl[]

这里要先介绍两个数据结构:OSRdyGrp、OSRdyTbl[]。这两个变量协同完成优先级的标定。

OSRdyGrp:优先级就绪组

这是一个8位的变量。每一个变量对应于OSRdyTbl[]中的一行(实际上是一个元素,但也可以理解为一行)。

OSRdyTbl[]优先级就绪表

这是一个数组,有8个成员,每个成员都是8位的变量,所以就可以构成了8*8的矩阵了。所以64个优先级都是标定在这个数组中的。

他们的关系如图:

优先级位图算法详解_第1张图片

       创建了一个任务,它的优先级为 prio=11.(这是用户指定的),此优先级用二进制表示(8位):最前面两位无用处,前面已说过

00 001 011。那么怎么在对应的OSRdyTbl[]优先级就绪表中进行标定呢?

       1. 把这个二进制数分为两个部分:高3 001)和低3位(011)。高三位负责找到数组中的行,低三位负责找到数组中的列(其实这里不是列,是一个变量的8个位,也可以按列理解),这样配合就可以寻址,对往相应数字标号里写1了。

       那从上面的思路来看,我们只要数组中的第几组,和第几列的值就可以了,所以又引进了一个映射数组:OSMapTbl[],其具体内容如下。下表0对应的就是0位为1,下表1对应的就是1位为1。

优先级位图算法详解_第2张图片

 

 

至此:这里涉及3个数据结构了,现在来总结一下:

1.OSRdyGrp:优先级就绪组  第几位置1的话,就说明就绪表中第几行有就绪任务。

2.OSRdyTbl[]:优先级就绪表: 行+列就能标定就绪任务的优先级

3. OSMapTbl[] 优先级映射表:用来方便生成第几行,第几列的一个转换而已。

 

2:单任务优先级的设置和查询

创建线程,设置优先级就绪组和就绪表的代码:

OSRdyGrp  |= OSMapTbl[prio>>3];           (1)

OSRdyTbl[prio>>3] |= OSMapTbl[prio&0x07];   (2)

查询线程的优先级的代码:

y     = OSUnMapTbl[OSRdyGrp];
x      = OSUnMapTbl[OSRdyTbl[y]];
prio = (y << 3) + x;

             

3 多个任务参与下 怎么选定最高的优先级任务

       此时又要加入一个表格:优先级判定表OSUnMapTbl[],。

优先级位图算法详解_第3张图片

1.先看最旁边的注释,说明的是该数组中对应的位置。

2.解释 这个数组中内容,这些数字怎么来的,

 举例:0x53 如上图所示的位置,为什么是0呢?我们把0x53变成二进制来看:

0101 0011,从右往左看,第一个出现1的位 就是0位所以为0.

为什么是从右往左看呢?因为高优先级的数字低,你应该懂的。

 

举例:多任务下的最高优先级的判定

有4个任务 ,优先级分别为6,10,11,17.。把上面就绪任务算法再贴一遍:前面2位不管。

6对应二进制:000 110 

高3位:000=0 通过OSMapTbl映射后,

OSMapTbl[prio>>3]= OSMapTbl[0]=0000 0001

低3位:110=6,通过OSMapTbl映射后

OSRdyTbl[prio>>3]= OSRdyTbl[0]=0100 0000

10对应二进制:001 010 

高3位:001=1 通过OSMapTbl映射后,

OSMapTbl[prio>>3]= OSMapTbl[1]=0000 0010.

低3位:010=2,通过OSMapTbl映射后

OSRdyTbl[prio>>3]= OSRdyTbl[1]=0000 0100

11对应二进制:001 011 

高3位:001=1 通过OSMapTbl映射后,

OSMapTbl[prio>>3]= OSMapTbl[1]=0000 0010.

低3位:011=3,通过OSMapTbl映射后

OSRdyTbl[prio>>3]= OSRdyTbl[1]=0000 1000

17对应二进制:010 001 

高3位:010=2 通过OSMapTbl映射后,

OSMapTbl[prio>>3]= OSMapTbl[2]=0000 0100.

低3位:001=1,通过OSMapTbl映射后

OSRdyTbl[prio>>3]= OSRdyTbl[2]=0000 0010

通过就绪任务算法:

OSRdyGrp  |= OSMapTbl[prio>>3];           (1)

OSRdyTbl[prio>>3] |= OSMapTbl[prio&0x07];   (2)

最后OSRdyGrp的值就是将所有的OSMapTbl[prio>>3]进行位或运算:

OSRdyGrp=0100 0000|0000 0010| 0000 0010|0000 0100= 0000 0111=0x07

OSRdyTbl[0]=0100 0000

OSRdyTbl[1]=0000 0100 |0000 1000=0000 1100 (相同的列 要或运算)

OSRdyTbl[2]=0000 0010

 

然后在查找优先级判定表OSUnMapTbl[]

 OSRdyGrp=0x07

Y=OSUnMapTbl[0x07]=0.说明是最高优先级在第0组。

OSRdyTbl[0]=0100 0000=0x40

X= OSUnMapTbl[0x40]=6

最高优先级为:prio= y*8+x=6

至此,最高优先级就选出来了。然后调度此任务运行就是了,另外,删除任务就是将对应就绪列表位的置的1清零就是。

if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0)    

OSRdyGrp &= ~OSMapTbl[prio >> 3];  

看到这里,这行代码理解应该没有问题,就是反操作而已。

你可能感兴趣的:(Rtthread)