RT-Thread的优先级算法

本文详细解析了RT-Thread操作系统中任务优先级的三种级别(8, 32, 256)下的调度机制,包括初始化、任务创建、调度启动及任务状态切换的过程。通过具体代码示例说明如何确定最高优先级任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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_tablert_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_threadthread,这这里首先会把任务的链表插入到对应优先级的链表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的内核又深入了解了一步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值