30 likes | 240 Views
Nucleus 任务调度算法原理. Nucleus 最多有 256 个优先级: 0~255, 0 表示最高优先级, 255 表示最低优先级, 我们用 P0~P255 来表示。 我们在创建并运行一个任务时必须将该任务的优先级保存起来,以便我们在任务调度时可以知道当前就绪的任务的优先级, 从而找到一个最高优先级的任务, 那么我们如何来找到最高的优先级呢? Solution 1 : 我们可以用一个 256 个 BOOL 类型元素的数组来保存优先级 : unsigned long TCD_Priority [8] ;
E N D
Nucleus任务调度算法原理 Nucleus最多有256个优先级:0~255, 0表示最高优先级,255表示最低优先级, 我们用P0~P255来表示。 我们在创建并运行一个任务时必须将该任务的优先级保存起来,以便我们在任务调度时可以知道当前就绪的任务的优先级, 从而找到一个最高优先级的任务, 那么我们如何来找到最高的优先级呢? Solution 1: 我们可以用一个256个BOOL类型元素的数组来保存优先级 :unsigned long TCD_Priority [8]; 该数组有32X8位,每一位对应一个有限级,当为1时,表示该优先级有任务就绪,为0时表示该优先级无任务就绪。 然后我们再来遍历每一位,看具体是哪个优先级。该方法的缺点是速度慢,因为我们要遍历8个32位数的每一位。 Solution 2: 将这256个优先级分组,Nucleus将其分成了32组(用一个32位数即可表示每组的状态),每组为8个, unsigned long TCD_Priority_Groups; P8~P15 bit31 bit30 bit1 bit0 P248 ~ P255 只要P0~P7的任务有一个就绪,那么该位将置1 P0~P7 那么我们如何快速确定究竟是哪一位为1呢?我们的原则是找到最高优先级,OK, 那么我们就应该从最低位开始找, 用遍历每一位的方式可以找到,但效率低!在Nucleus 中使用了一个256个元素的数组,我们通过这个数组可以快速找到最高优先级。 它的原理是什么呢? 我们先来看这样一个例子: unsigned char Prio; 加入用它的8位来表示8个优先级 P0 ~ P7 Prio = 0000 0101B , 那它表示P0 和 P3优先级有任务就绪。最高优先级当然是P0了 。 Prio = 5, Phigh = P0; Prio = 1000 0101B,那它表示P0 和 P7优先级有任务就绪。最高优先级当然还是P0了 。Prio = 0x85, Phigh = P0; Prio = 0000 0110B , 那它表示P1 和 P3优先级有任务就绪。最高优先级当然是P1了 。Prio = 6, Phigh = P1; Prio = 1000 0110B,那它表示P1 和 P7优先级有任务就绪。最高优先级当然还是P1了 。Prio = 0x86, Phigh = P1; 到这里我想大家应该发现这样一个规律:我们只需要找到最低位的1就可以确定我们想要的最高优先级了。于是我们就可以将这个8 位的数据的256(0~255)种可能做一个256个元素的表格,即当prio = 0, 1 ,2, 3, 4 ……………255时,最高优先级的值。 该表格的生成见:Nucleus_lookup_table.c
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 • 这个表格只能查找一个8为数啊!我们上面使用了一个32位数啊,怎么查?有办法, 我们先判断一下这个32位数的哪8位不为零不就可以了。 • if(TCD_Priority_Groups > 0) • { • if(TCD_Priority_Groups & 0x00 00 00 FF) • index = 0; • else if (TCD_Priority_Groups & 0x00 00 FF 00) • index = 8; • else if (TCD_Priority_Groups & 0x00 FF 00 00) • index = 16; • else • index = 24; • } • 查 TCD_Lowest_Set_Bit[ (TCD_Priority_Groups >> index) & 0x 00 00 00 FF]; 就是我们要的值。 • 此时我们只是确定了哪8个优先级有任务就绪,具体是哪个优先级呢? • 一个优先级可以这样表示:组索引+偏移量。 • 例:85这个优先级可以表示为第10组(每组有8个)的第5个优先级, 如下图所示。 bit31 bit30 bit9 bit1 bit0 1 x x x 1 x x x x 于是我们在创建任务时,可以用如上的方式来保存我们创建的任务的优先级。我们有把任务分成32组,因此我们需要一个32个 元素的数据:unsgined char TCD_Sub_Priority_Groups[32];
我们在创建任务时: task_tcb->tc_priority = task_prio; task_tcb->tc_sub_priority = (DATA_ELEMENT)(1<<(task_prio&7)); task_prio >>= 3; task_tcb->tc_priority_group = ((UNSIGNED)1)<<task_prio; task_tcb->tc_sub_priority_ptr = &(TCD_Sub_Priority_Groups[task_prio]); 执行任务时: TCD_Priority_Groups |= task_tcb->tc_priority_group; *(task_tcb->tc_sub_priority_ptr) |= task_tcb->tc_sub_priority; if((INT)(task_tcb->tc_priority) < TCD_Highest_Priority) TCD_Highest_Priority = (INT)task_tcb->tc_priority; 任务调度时: if(TCD_Priority_Groups & TC_HIGHEST_MASK) index = 0; else if (TCD_Priority_Groups & TC_NEXT_HIGHEST_MASK) index = 8; else if (TCD_Priority_Groups & TC_NEXT_LOWEST_MASK) index = 16; else index = 24; index += TCD_Lowest_Set_Bit[(INT)((TCD_Priority_Groups >> index) & TC_HIGHEST_MASK)]; temp = TCD_Sub_Priority_Groups[index]; TCD_Highest_Priority = (index << 3) + TCD_Lowest_Set_Bit[temp]; 具体代码请见文件Nucleus_task_dispatch.c