• μC/OS Ⅱ之任务就绪表的操作_2012.5.31


    任务的登记:        

    1               OSRdyGrp |= OSMapTbl[prio>>3];
    2               OSRdyTbl[prio>>3] |= OSMapTbl[prio&0x07];

    这两行代码就实现了在就绪表中添加给定优先级(prio)任务的作用;

    想要彻底明白这两行代码,我们首先要对prio有了解。优先级prio,范围从[0:63],用二进制数表示,就是000000B~111111B。其中只用到了8位字长的低6位。这低六位又可以分为低三位和高三位:

    1            eg: 63=111 111B
    2               prio>>3  //即取prio的高三位,(绿色的3位);表示的是任务所在的组,即任务就绪表的Y坐标;
    3               prio & 0x07  //即取prio的低三位(红色的三位);表示的是任务所在的位,即任务就绪表的X坐标。

                                           

           OSRdyGrp是位可操作的,它的每一位对应Y坐标从0~7,表示任务就绪表的行,如果这一行中有任何一个优先级的任务就绪,就将它的对应位置1

           同理,数组OSRdyTbl[ ] 表示的是就绪表的每一行的内容,它的每个元素,也都是位可操作的,每个数组下标,表示Y坐标,即所在行,每个数组元素的内容,对应所在行的8个元素,也就是就绪表中每一行的8列。至此,构成了uC/OS-II的8X8的任务就绪表,可以表示0~63共64个优先级,这也是μC/OS Ⅱ支持的最大任务数为64的由来。

           再来看OSMapTbl这个数组,该数组已经定义好,它的8个元素分别是:

    1 OSMapTbl[0]=00000001B
    2 OSMapTbl[1]=00000010B
    3 OSMapTbl[2]=00000100B
    4 OSMapTbl[3]=00001000B
    5 OSMapTbl[4]=00010000B
    6 OSMapTbl[5]=00100000B
    7 OSMapTbl[6]=01000000B
    8 OSMapTbl[7]=10000000B

    下面回来看最初的两行代码:

    (1):prio>>3,就是只取prio的高三位,即任务所在的行(即坐标Y=prio>>3),将Y坐标填入数组OSMapTbl[Y]的下标中,OSMapTbl[Y]的值与OSRdyGrp做位或,将新就绪的任务所在的行所对应的OSRdyGrp的位 置1,并且保持其他位不变,如此一来,就新登记了一条就绪任务,并且没有影响到之前已就绪任务的登记信息;

           例如,本例中,假设prio>>3 得到OSMapTbl[prio>>3]=OSMapTbl[7] = 10000000B,再与OSRdyGrp做位或,即将OSRdyGrp的第8位 置为了1,并且没有改变其他位,同时没有影响到之前的就绪任务的已登记信息。

    (2):prio&0x07,就是只取prio的低三位,即任务所在的位(即坐标X =prio&0x07),将X坐标填入数组OSMapTbl[X]下标中,OSMapTbl[X]与OSRdyTbl[Y]做位或,将OSRdyTbl[Y]对应位 置1,表示该行的第X位有任务进入就绪态,注意第X位要从低端算起,也就是表格的右端开始算起;

      例如:刚才已经算出Y坐标 = 7,本例中,prio & 0x07 = 坐标X = 7 ,OSMapTbl[ 7 ] = 10000000B,将10000000与OSMapTbl[7]做位或,即将OSMapTbl[7]的第8位置1,表示该位的任务进入就绪态;如此,新就绪的任务登记完成,也保证了不影响其他任务的就绪状态。

    任务的注销:

    注销,就是说,从任务就绪表中将待注销任务的对应位 置0。

    1 if ( ( OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07] )  == 0)
    2     OSRdyGrp &= ~OSMapTbl[prio >> 3];

    注意:

    1.OSRdyTbl[prio>>3]所有的位都是0时,OSRdyGrp 的相应位才清零(即对   

    应行一个就绪任务都没有时,OSRdyGrp才为0)。所以要进行判断。2.OSRdyTbl[prio >> 3] 里面可能还包含其他位为1,即在RdyTbl[prio >> 3]   还有其他就绪任务,这时候所对应的OSRdyGrp 的位还是1,直到RdyTbl[prio >> 3] =0,表示没有任务就绪时才应将相应的OSRdyGrp里面的位置0

    以上第一行代码将就绪任务表数组OSRdyTbl[]中相应元素的相应位清零;同时做一个判断,判断OSRdyTbl[prio>>3]是否已全部为0,若全部为0,则表示改组任务全都不处于就绪状态,此时可把OSRdyGrp置为0。

    任务的查找:

    根据X和Y倒推算任务优先级prio:

    只需将以上运算倒过来即可:prio = [Y<<3] + X;

    例如:刚才上面的例子里,Y = 7,X = 7,则:

    1  prio = [Y<<3] + X = [7<<3] + 7
    2                    =(111B<<3)+111B
    3                    =111000B+111B
    4                    =111111B
    5                    =63D

    因此,进入就绪态的任务优先级为63。

    OSRdyTbl[ ]的元素(共8个元素,每个元素为8位;由此可见,任务就绪表就是一个从结构上来看,二维数组)构成8X8的就绪表,OSRdyGrp只表示就绪表的Y轴(所在行),也就是OSRdyGrp 中的每一位表示 8 组(行)任务中每一组(所在行)中是否有进入就绪态的任务。

    注意OSRdyGrp和OSRdyTbl[ ]的元素都是按位进行运算的。

    最高优先级就绪任务的查找:

           系统调度器总是把CPU控制权交给优先级最高的就绪任务,因此调度器就必须具有从任务就绪表中找出最高优先级任务的能力。

           基本的查找的思路是在任务就绪表里,从上至下,从右至左,挨个来找,但这需要大量的判断,因此花费很长时间。

           快速方法:根据y=OSRdyGrp( 所在组(行) )和OSRdyTbl[y](所在位)在优先级判定表OSUnMapTbl[ ]中,进行查表计算操作,即可快速计算出优先级最高的那个就绪任务。

    OSUnMapTbl[ ]如下所示:

     1 INT8U const OSUnMapTbl[256] = {
     2    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     3     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     4     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     5     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     6     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     7     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     8     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     9     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    10     7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    11     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    12     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    13     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    14     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    15     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    16     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    17     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0       
    18 };

    计算代码如下:

    1 y = OSUnMapTbl[OSRdyGrp];         //最高优先级任务所在组(行)
    2 x = OSUnMapTbl[OSRdyTbl[y]];      //最高优先级任务所在的位
    3 prio = (y << 3) + x;              //还原为优先级

    注:

    1.OSUnMapTbl[]中的每个元素,表示的是从0x00—0xFF的每个数的二进制   数表示中,最低位1出现的位置。

    2.OSUnMapTbl[]中的每个元素,在0到7之间

  • 相关阅读:
    poj 3528 (三维几何求凸包+凸包表面积)
    dijkstra模板(好像是斐波那契额堆优化,但我为什么看起来像优先队列优化,和spfa一样)
    最大空凸包模板
    ICPC 2017–2018, NEERC, Northern Subregional Contest St Petersburg, November 4, 2017 I题
    hdu 5248 序列变换
    hdu 2063(二分图模板测试)
    组合数
    85. Maximal Rectangle 由1拼出的最大矩形
    750. Number Of Corner Rectangles四周是点的矩形个数
    801. Minimum Swaps To Make Sequences Increasing 为使两个数组严格递增,所需要的最小交换次数
  • 原文地址:https://www.cnblogs.com/gylei/p/2528776.html
Copyright © 2020-2023  润新知