嵌入式技术论坛
直播中

青sky

8年用户 1248经验值
擅长:模拟技术
私信 关注
[问答]

求助,关于rt_schedule中need_insert_from_thread的问题

RT-Thread支持时间片调度算法,相同优先级的thread按其设定的ticks 轮流执行。

先上rt_schedule代码
1.png

need_insert_from_thread 标志主要是用来标记是否从当前任务切换到其他任务,切出意味着需要把当前任务插入到对应优先级的readylist。

情况1

这个很好理解:没有和当前任务task1优先级相同的任务,其优先级readylist为空。

假如有一个低优先级task2任务, systic中断里 rt_timer_check()发现超时;或者资源就绪把它唤醒,都会发起一次调度,把它插入对应readylist,这时_scheduler_get_highest_priority_thread得到的是task2,无需切换。

或者当前任务时间片用完,主动发起调度,发现自己还是老大,那就继续运行吧

task主动调用rt_thread_yield,礼让CPU资源,结果和上面一样

情况2

假设还有一个task2和当前任务task1优先级相同, 同样可能因为超时;或者资源就绪把它唤醒,发起一次调度,把它插入对readylist。
1.png

这时task1的时间片还未用完,依旧无需切换,让它等着吧。

情况3

可以直接列出剩余的三种情况,

1)

if (rt_current_thread->current_priority == highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0)

和情况2相同,当前任务的时间片用完了或者主动礼让,把自己插入对应readylist前

2)

if (rt_current_thread->current_priority > highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0)

这个情况实际是不存在的,因为在SysTick_Handler 调用 的rt_tick_increase,一旦发现时间片用完或者主动礼让就会发起一次调度,清除了RT_THREAD_STAT_YIELD

再次因超时或者资源唤醒进来,也不满足这个条件

/**

  • [url=home.php?mod=space&uid=2666770]@Brief[/url] This function will notify kernel there is one tick passed.
  • Normally, this function is invoked by clock ISR.
    

*/

void rt_tick_increase(void)

{

struct rt_thread *thread;

rt_base_t level;

RT_OBJECT_HOOK_CALL(rt_tick_hook, ());

level = rt_hw_interrupt_disable();

/* increase the global tick */

#ifdef RT_USING_SMP

rt_cpu_self()->tick ++;

#else

++ rt_tick;

#endif /* RT_USING_SMP */

/* check time slice */

thread = rt_thread_self();

-- thread->remaining_tick;

if (thread->remaining_tick == 0)

{

/* change to initialized tick */

thread->remaining_tick = thread->init_tick;

thread->stat |= RT_THREAD_STAT_YIELD;

rt_hw_interrupt_enable(level);

rt_schedule();

}

else

{

rt_hw_interrupt_enable(level);

}

/* check timer */

rt_timer_check();

3)

if (rt_current_thread->current_priority > highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)

新就绪的任务优先级高于当前任务,虽然当前任务时间片有剩余,也必须切出,同时保留剩余时间片

插入到readylist

void rt_schedule_insert_thread(struct rt_thread *thread)

{

register rt_base_t temp;

RT_ASSERT(thread != RT_NULL);

/* disable interrupt */

temp = rt_hw_interrupt_disable();

/* it's current thread, it should be RUNNING thread */

if (thread == rt_current_thread)

{

thread->stat = RT_THREAD_RUNNING | (thread->stat & ~RT_THREAD_STAT_MASK);

goto __exit;

}

/* READY thread, insert to ready queue */

thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);

/* insert thread to ready list */

rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),

&(thread->tlist));

RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("insert thread[%.*s], the priority: %d\n",

RT_NAME_MAX, thread->name, thread->current_priority));

/* set priority mask */

#if RT_THREAD_PRIORITY_MAX > 32

rt_thread_ready_table[thread->number] |= thread->high_mask;

#endif /* RT_THREAD_PRIORITY_MAX > 32 */

rt_thread_ready_priority_group |= thread->number_mask;

__exit:

/* enable interrupt */

rt_hw_interrupt_enable(temp);

}

问题

问题出在情况3的第三种情景下:

新就绪的任务优先级高于当前任务,当前任务时间片有剩余,

插入动作没有问题,但是使用rt_list_insert_before把未执行完时间片的任务插入到其优先级readylist的最后面,是不是对其不太公平,毕竟是高优先级的任务打断了它。

是不是应该按下面分类处理比较好, 使用rt_list_insert_after把它插在list->next位置,下次轮到该优先级时,首先执行,直到其时间片用完!

if (rt_current_thread->current_priority < highest_ready_priority)
            {
                to_thread = rt_current_thread;// no task of same priority
            }
            else if (rt_current_thread->current_priority == highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
            {
                to_thread = rt_current_thread; // another tasks of same priority ,not preemption
            }
            else if (rt_current_thread->current_priority == highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0)
            {
                need_insert_from_thread = 1; //  insert before
            }
            else if (rt_current_thread->current_priority > highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
            {
                need_insert_from_thread = 2;//   insert after to make sure the remained ticks can be used continually
            }

// else if (rt_current_thread->current_priority > highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) != 0)

// {

// need_insert_from_thread = 1;

// }

回帖(2)

江左盟

2023-9-8 16:03:40
分析得有道理,按这分析,我觉得正常逻辑应该是,高优先级打断了它,它住后等,等高优先级执行完后,就应该再执行它
举报

李涛

2023-9-21 16:24:00
和task1优先级相同的任务task3,则先插入task1,再插入task3到readylist中。那么_scheduler_get_highest_priority_thread得到的是task1,需要切换到task1执行。总的来说,需要插入的情况主要是在当前任务需要切出时,需要把当前任务插入到对应优先级的readylist中。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分