您的位置:首页 > 移动开发

RT-Thread的优先级算法

2011-06-10 15:45 197 查看
RT-Thread的优先级有3种级别,最大分别是8,32,256.我们逐一来分析,在此之前看一下下面的变量:
const rt_uint8_t rt_lowest_bitmap[] =
{
    /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};
         /* 任务优先级的链表—不同优先级有不同的链表(为了同优先级时间片轮) */
rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];         
         …
#if RT_THREAD_PRIORITY_MAX > 32
/* maximun priority level, 256 */
rt_uint32_t rt_thread_ready_priority_group;                   /* 任务优先级组 */
rt_uint8_t rt_thread_ready_table[32];                      /* 任务就绪表 */
#else
/* maximun priority level, 32 */
rt_uint32_t rt_thread_ready_priority_group;
#endif
 
一,初始化     --       rt_system_scheduler_init()
这一步初始化了rt_thread_priority_table,rt_thread_ready_priority_group。这里注意最大优先级是8,32的不初始化rt_thread_ready_table
 
二,任务建立         --     rt_application_init()
这里建立一个任务rt_thread_create(),并rt_thread_startup。这里要区分一下:
1,  RT_THREAD_PRIORITY_MAX > 32   :这种情况下
thread->number               = thread->current_priority >> 3;                    /* 5bit */          thread->number_mask        = 1L << thread->number;
thread->high_mask          = 1L << (thread->current_priority & 0x07);                    /* 3bit */
这里我们可以看出,他把任务的高5位作为行号(2^5 = 32),低3位作为列号(2^3 = 8)。
2,  RT_THREAD_PRIORITY_MAX <=32
thread->number_mask = 1L << thread->current_priority;
因为一个4字节的数有32位,所以这里用32位的数的每个bit位来表示对应的优先级。
紧接着调用rt_thread_resume(),在里面调用rt_schedule_insert_thread(thread,这这里首先会把任务的链表插入到对应优先级的链表rt_thread_priority_table里,接着如果RT_THREAD_PRIORITY_MAX > 32,那么还会执行:
rt_thread_ready_table[thread->number]  |=  thread->high_mask;
         把任务的列号与到任务就绪表对应的那一行。紧接着:
                   rt_thread_ready_priority_group |= thread->number_mask;
          这里就把任务的行号放到任务就绪表组里面。
 
三,调度器启动     --       rt_system_scheduler_start()
1,  RT_THREAD_PRIORITY_MAX == 8   :
highest_ready_priority = rt_lowest_bitmap[rt_thread_ready_priority_group];
这里根据任务就绪表组反推算出最高优先级。
2,  RT_THREAD_PRIORITY_MAX != 8   :
register rt_ubase_t number;
/* find out the highest priority task */
if (rt_thread_ready_priority_group & 0xff)
{number = rt_lowest_bitmap[rt_thread_ready_priority_group & 0xff];}
else if (rt_thread_ready_priority_group & 0xff00)
{number = rt_lowest_bitmap[(rt_thread_ready_priority_group >> 8) & 0xff] + 8;}
else if (rt_thread_ready_priority_group & 0xff0000)
{number = rt_lowest_bitmap[(rt_thread_ready_priority_group >> 16) & 0xff] + 16;}
else
{number = rt_lowest_bitmap[(rt_thread_ready_priority_group >> 24) & 0xff] + 24;}
这段代码我们可以计算出优先级对应的行号。
a)       RT_THREAD_PRIORITY_MAX == 32
highest_ready_priority = number;
因为这种模式下面没有rt_thread_ready_table也就是说每一个组里面只有一个任务,最高优先级就可以直接算出来。
b)       RT_THREAD_PRIORITY_MAX == 256
这种模式有rt_thread_ready_table也就是说每一个行里面需要有8个列号对应,highest_ready_priority = (number << 3) + rt_lowest_bitmap[rt_thread_ready_table[number]];这里的优先级是由行号与列号共同组合而成的。
 
四,任务从就绪态切换到其他形态     --       rt_sem_take()或者其他此类能够让任务进入挂起态的函数。
rt_sem_take()->rt_ipc_object_suspend()->rt_thread_suspend()->rt_schedule_remove_thread()这里就是真正进行任务就绪态转换其他形态的地方。首先rt_list_remove(&(thread->tlist));把任务的链表从就绪链表里面删除。然后判断当前优先级的链表组是否为空(事件片轮的调度),为空就需要把任务从就绪表里面删除。
/* remove thread from ready list */
    rt_list_remove(&(thread->tlist));
    if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
    {
#if RT_THREAD_PRIORITY_MAX > 32
        rt_thread_ready_table[thread->number] &= ~thread->high_mask;
        if (rt_thread_ready_table[thread->number] == 0)
        {
            rt_thread_ready_priority_group &= ~thread->number_mask;
        }
#else
        rt_thread_ready_priority_group &= ~thread->number_mask;
#endif
}
 
至此,基本上的原理分析就明了了。对RT-Thread的内核又深入了解了一步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息