OSMapTbl[]的下標 |
OSMapTbl[](即位掩碼) |
0 |
00000001 |
1 |
00000010 |
2 |
00000100 |
3 |
00001000 |
4 |
00010000 |
5 |
00100000 |
6 |
01000000 |
7 |
10000000 |
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
};
先把就緒表的結構圖貼出來看看:
至於這個就緒表是怎麼構成的,爲什麼是8x8表格,這裏就不浪費寶貴的網絡資源了,任何一本書上都說得我比清楚。
這裏主要是說明一下OSMapTbl[]和OSUnMapTbl[]這兩個數組的值是怎麼得來的,以及對進入、脫離就緒態代碼和找出最高優先級任務代碼的理解。
一、OSMapTbl[]數組。
這個數組出現的目的是爲了更方便的置位。說白點,使用OSMapTbl[index]的作用是更方便的把某個數值的第index位置1。比如:使任務進入就緒態的代碼是:
OSRdyGrp |= OSMapTbl[prio>>3]; (1)
OSRdyTbl[prio>>3] |= OSMapTbl[prio&0x07]; (2)
先取prio(任務優先級)的“高三位”(這裏的高三位是指不考慮prio的最高兩位,剩下的六位中的高三位),“高三位”是OSRdyGrp的索引,就是說:“高三位”的值(0到7)指定OSRdyGrp(8位)中某一位置位,比如,“高三位”是111,即7,這樣就把OSRdyGrp的第7位置1。再看代碼(1),先通過prio>>3確定OSRdyGrp的哪一位應該置1(比如第7位),然後通過OSMapTbl[]表把這一位置1,其他位爲0(比如OSMapTbl[7]=10000000),再通過位或操作就可以把OSRdyGrp的相應位(第7位)置1了。代碼(2)是同樣的道理。這裏就說明了OSMapTbl[]數組的用處了。
使任務脫離就緒態要對某些位進行清0操作,這裏也要用到OSMapTbl[]數組,原理是一樣的。代碼如下:
-
if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0)
- OSRdyGrp &= ~OSMapTbl[prio >> 3];
第一行先對OSRdyTbl[]中某數據的某一位清0,然後進行判斷,如果OSRdyTbl[]中這個數據爲0(也主相當於這個數據的所有8位都已經清0了),再對OSRdyGrp的某位清0。
二、OSUnMapTbl[]數組
OSUnMapTbl[]數組主要是用於找出進入就緒態的優先級最高的任務。而這個地方也是我一開始沒搞明白的,不明白OSUnMapTbl[]中的數值是怎麼來的。
先脫離所有上下文關係來說說OSUnMapTbl[]的一般意義。這裏用二進制比較方便說明問題。OSUnMapTbl[]共0xFF個元素,0x00~0xFF爲索引,而OSUnMapTbl[]裏的值就是通過分析索引得到的。比如說,索引0x50, 二進制表示爲0101 0000,然後從右邊數,看第幾位首先爲1,則OSUnMapTbl[0x50]的值就爲幾。易知,0101 0000從右起,第4位首先爲1,所以有OSUnMapTbl[0x50]=4。再比如0x51,二進制爲0101 0001,右起第0位爲1,所以OSUnMapTbl[0x51]=0。
那爲什麼要從右數起呢?這個和優先級表有關係,優先級的值越小,優先級就越高。再看上面那幅優先級的結構圖,可見,優先級是從右至左,從上至下越來越低的,最低優先級給了空閒任務。
結合代碼分析一下:
-
y = OSUnMapTbl[OSRdyGrp];
-
x = OSUnMapTbl[OSRdyTbl[y]];
- prio = (y << 3) + x;
x、y的含義看上面的圖就知道了:y是“高三位”,x是“低三位”。
找最高優先級任務的過程是這樣的:首先,查OSRdyGrp,看OSRdyGrp中右起的第幾位首先爲1,比如OSRdyGrp=0x56,0x56的二進制爲0101 0110,可見右起第1位首先爲1,所以y=OSUnMapTbl[0x56]=1,然後再去OSRdyTbl[y]即OSRdyTbl[1]中查找(爲什麼是OSRdyTbl[y],這個書上說得很明確,這個得清楚得了解OSRdyGrp和OSRdyTbl[]之間的關係),這裏假設OSRdyTbl[1]=0xD4,即1101 0100,同樣找到OSRdyTbl[1]中右起的第2位首先爲1,這樣得到x=2,再通過第3行的移位運算就可以得到最高優先級的任務的優先級了。
轉自:http://blog.sina.com.cn/s/blog_9f14969901011t53.html