RT-Thread支持时间片调度算法,相同优先级的thread按其设定的ticks 轮流执行。
先上rt_schedule代码
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。
这时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
再次因超时或者资源唤醒进来,也不满足这个条件
/**
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;
// }
更多回帖