ucos 的调度算法设计的很巧妙,是一个很经典的位图算法。很简洁。
由OSRdyGrp 、 OSRdyTbl[]、OSMapTbl[]、OSUnMapTbl[] 这四个变量组成。都是8位无符号类型的。ucos的设计是支持64个优先级(0 – 63 ,0优先级最高)。假设优先级为 prio,运算过程如下:
映射: Y = prio >> 3;
BitY = OSMapTbl[Y];
X = prio & 0x07;
BitX = OSMapTbl[X];
OSRdyGrp |= BitY;
OSRdyTbl[Y] |= BitX;
求最高优先级: y = OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);
前一阵子,我以为把ucos扩展到256个优先级应该很容易。最近想了一下,不容易的,要改动的地方还不少。
第一步,就是把OSRdyGrp 、 OSRdyTbl[]、OSMapTbl[]都定义为INT16U类型的变量,这是必须的。
此时INT16U const OSMapTbl[]= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000};
第二步,这一步很关键,如果把OSUnMapTbl[]直接扩展到16位,那肯定行。。不过这样太那个了,65536个字节,这个玩笑开不得呢。
我想还是用现成的吧,可以先算低八位,然后根据情况算高八位。 这样的话,有一个棘手的问题,低八位的值为0就惨了(64个优先级时,不会出现)。 可以这样处理:当低八位为0时,OSUnMapTbl[0] = -1;
此时: INT8S const OSUnMapTbl[] = {
-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};
假设优先级为 prio,运算过程如下:
映射: Y = prio >> 4;
BitY = OSMapTbl[Y];
X = prio & 0x0f;
BitX = OSMapTbl[X];
OSRdyGrp |= BitY;
OSRdyTbl[Y] |= BitX;
求最高优先级: Y_L = OSRdyGrp &0XFF;
Y_H = OSRdyGrp >> 8 ;
if ((y = OSUnMapTbl[Y_L]) == -1)
y = OSUnMapTbl[Y_H] + 8 ;
X_L = OSRdyTbl[y] &0XFF ;
X_H = OSRdyTbl[y] >> 8 ;
if ((x = OSUnMapTbl[X_L]) == -1)
x = OSUnMapTbl[X_H] + 8 ;
OSPrioHighRdy = (INT8U)((y << 4) + x);
麻烦吧,哈哈! 不过原理还是清晰的。就是把16位分为高八位,低八位咯。根据特殊情况做一下特殊处理就可以了。
1、 记得前一段时间,有个人问我怎么快速计算出一个usigned char 类型的数据有几个位为1。 当时我是说弄一个256个数据的数组,做一个映射。 其实不用这么麻烦的。16个数据的数组足够了。
unsigned char const map_1_tbl[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
假设有数据 unsigned char类型的数据data
可以这样查:
size = map_1_arr[data>>4] + map_1_arr[data & 0x0f] ;
1、很自然会想到,怎么快速计算出一个usigned char 类型的数据第一个为1的位呢?(低位到高位。)
为了方便,如果有为1的位,则计算出第一个为1的位的位置(0 - 7),如果没有则为-1 ; 可以这么做.
映射表:
char const map_frist_1_tbl[16] = {
-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
};
计算:
if ((result = map_frist_1_tbl[data &0x0f]) == -1)
if((result = map_frist_1_tbl[data >> 4]) != -1)
result = result + 4 ;