关于nucleus中的优先级查询表

类别:编程语言 点击:0 评论:0 推荐:

优先级是任务的重要属性,也是内核在调度时的依据。对于nucleus中的优先级管理,仔细看过代码的人应该都能够理得清楚。但其中使用的查询表,我想就不是每个人都清楚的了。而如果你不清楚查询表为什么是那个样子,我估计你对于优先级管理这一块也就不会十分透彻了。

下面先结合具体的代码简单介绍一下与优先级相关的操作。

/* 两个全局变量 */

extern UNSIGNED         TCD_Priority_Groups; /* unsigned long */
extern DATA_ELEMENT     TCD_Sub_Priority_Groups[TC_MAX_GROUPS]; /* unsigned char */

1. 创建一个task时

 /* 优先级值的低三位作为其在某一优先级组内的值 */
 task -> tc_sub_priority =           (DATA_ELEMENT) (1 << (priority & 7));
 /* 优先级值的高五位是优先级组的索引值 */
 priority =                          priority >> 3;
 /* 若某一优先级属于某一优先级组,则相应位置1 */
 task -> tc_priority_group =         ((UNSIGNED) 1) << priority;
 /* 保存指向优先级组的指针 */
 task -> tc_sub_priority_ptr =       &(TCD_Sub_Priority_Groups[priority]);

2. 运行一个task时

 /* 根据task的两个值置全局变量变量的相应位 */
 /* Update the priority group bit map to indicate that this
    priority now has a task ready.  */
 TCD_Priority_Groups = 
         TCD_Priority_Groups | (task -> tc_priority_group);
 /* Update the sub-priority bit map to show that this priority
    is ready.  */
 *(task -> tc_sub_priority_ptr) =
    (*(task -> tc_sub_priority_ptr)) | task -> tc_sub_priority;

3. 调度时查询当前最高优先级

#define         TC_HIGHEST_MASK         0x000000FFUL
#define         TC_NEXT_HIGHEST_MASK    0x0000FF00UL
#define         TC_NEXT_LOWEST_MASK     0x00FF0000UL
#define         TC_LOWEST_MASK          0xFF000000UL

 /* Find the next highest priority task.  */
 /* 分为两个过程:找最低的优先级组和优先级组中最低优先级
    优先级组又按八个一组来组织,查询时先判断属于哪一组,得出一个起始值。*/
 if (TCD_Priority_Groups & TC_HIGHEST_MASK)
  /* Base of sub-group is 0.  */
  index =  0;
 else if (TCD_Priority_Groups & TC_NEXT_HIGHEST_MASK)
  /* Base of sub-group is 8.  */
  index =  8;
 else if (TCD_Priority_Groups & TC_NEXT_LOWEST_MASK)
  /* Base of sub-group is 16.  */
  index =  16;
 else
  /* Base of sub-group is 24.  */
  index =  24;
 /* Calculate the highest available priority.  */
 /* 再将TCD_Priority_Groups值中与那一组相关的数据取出作为索引值在表中查询
    从而得到相对于起始值的偏移值,两者相加即是当前最高优先级task所在的优先级组的值。*/
 index =  index + TCD_Lowest_Set_Bit[(INT)(TCD_Priority_Groups >> index) & TC_HIGHEST_MASK)];
 /* Get the mask of the priority within the group of 8 priorities.  */
 temp =  TCD_Sub_Priority_Groups[index];
 /* Calculate the actual priority.  */
 /* 根据task对应的优先级组中的值查表得到在该优先组中最高的优先级,将优先级组
    的值乘以8再加上该值,即是当前最高优先级 */
 TCD_Highest_Priority = (index << 3) + TCD_Lowest_Set_Bit[temp];

/***************************************************************************************/
下面重点说说这个查询表。

     先举个例子来说明具体查询过程。假设TCD_Priority_Groups 值为 0x00208c00(0000 0000 0010 0000 1000 1100 0000 0000), 则index = 8, 然后再取出0x8c, 作为索引值在表中查询,得到2,两者相加得到10,此即最高优先级所在的优先级组的值。再假设TCD_Sub_Priority_Groups[10]= 2,去表中查询得到1,则最高优先级即为10*8+2=82。
     那么这个表中的数据是怎么的呢?其实根据这个表查出来的是某一给定八位二进制值中最低的1所处的位置。明白了这一点,也就可以理解这个表了。例如当最低的1位于第0位(从低位到高位依次为0,1,2...7)时,则不管高位是什么值,查出来的值始终应是0。也即不管给的值是从0000 0001B到1111 1111B中的哪一个值,查询该表得出的值都是0。因而在表的第1(0000 0001), 3(0000 0011), 5(0000 0101)...... 各位置处都应填零。当最低的1位于第1位时,则不管高位是什么值,查出来的值始终应是1。也即不管给的值是从0000 0010B到1111 1110B中的哪一个值,查询该表得出的值都是1。因而在表的第2(0000 0010), 6(0000 0110), 10(0000 1010)...... 各位置处都应填1。当最低的1位于第2位时,在表的第4,12,20......各位置处都应填2。当最低的1位于第3位时,在表的第8,24,40......各位置处都应填3。这些值位于表的第1行。当最低的1位于第4,5,6位时类推。当最低的1位于第7位时,只有一个值,也即第128个值为7。表中第0位置处的数据为0,但实际上这个值并不会被用到。
    以上是关于nucleus中用到的查询表的说明,其实ucos-II中的也一样,笔者也曾仔细分析过。
 
附录:部分代码及查询表

 /*TCC_Create_Task()*/
 task -> tc_sub_priority =           (DATA_ELEMENT) (1 << (priority & 7));
 priority =                          priority >> 3;
 task -> tc_priority_group =         ((UNSIGNED) 1) << priority;
 task -> tc_sub_priority_ptr =       &(TCD_Sub_Priority_Groups[priority]);
/*TCC_Resume_Task()*/
 /* Update the priority group bit map to indicate that this
    priority now has a task ready.  */
 TCD_Priority_Groups = 
         TCD_Priority_Groups | (task -> tc_priority_group);
 /* Update the sub-priority bit map to show that this priority
    is ready.  */
 *(task -> tc_sub_priority_ptr) =
    (*(task -> tc_sub_priority_ptr)) | task -> tc_sub_priority;
/*TCC_Signal_Shell()*/
 /* Find the next highest priority task.  */
 if (TCD_Priority_Groups & TC_HIGHEST_MASK)
 /* Base of sub-group is 0.  */
 index =  0;
 else if (TCD_Priority_Groups & TC_NEXT_HIGHEST_MASK)
 /* Base of sub-group is 8.  */
 index =  8;
 else if (TCD_Priority_Groups & TC_NEXT_LOWEST_MASK)
 /* Base of sub-group is 16.  */
 index =  16;
 else
 /* Base of sub-group is 24.  */
 index =  24;
 /* Calculate the highest available priority.  */
 index =  index + TCD_Lowest_Set_Bit[(INT)
 ((TCD_Priority_Groups >> index) & TC_HIGHEST_MASK)];
 /* Get the mask of the priority within the group of
 8 priorities.  */
 temp =  TCD_Sub_Priority_Groups[index];
 /* Calculate the actual priority.  */
 TCD_Highest_Priority = 
 (index << 3) + TCD_Lowest_Set_Bit[temp];
 
 /* 此表经过重新排列,以方便理解 */
 UNSIGNED_CHAR  TCD_Lowest_Set_Bit[] = {
  0, 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
 } ;

本文地址:http://com.8s8s.com/it/it25554.htm