对于RTT来说,每个线程创建时都自带一个定时器
rt_err_t rt_thread_sleep(rt_tick_t tick)
{
register rt_base_t temp;
struct rt_thread *thread;
/* set to current thread */
thread = rt_thread_self();
RT_ASSERT(thread != RT_NULL);
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
/* disable interrupt */
temp = rt_hw_interrupt_disable();
/* suspend thread */
rt_thread_suspend(thread); //从就绪链表移除
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick); //设置定时器定时时间
rt_timer_start(&(thread->thread_timer)); //开启定时器
/* enable interrupt */
rt_hw_interrupt_enable(temp);
rt_schedule();
/* clear error number of this thread to RT_EOK */
if (thread->error == -RT_ETIMEOUT)
thread->error = RT_EOK;
return RT_EOK;
}
延时过程:
- 将线程从就绪链表移除。
- 设置/启动定时器
- 每个Tick判断,定时器是否超时,调用超时函数。
/**
* This function is the timeout function for thread, normally which is invoked
* when thread is timeout to wait some resource.
*
* @param parameter the parameter of thread timeout function
*/
void rt_thread_timeout(void *parameter)
{
struct rt_thread *thread;
thread = (struct rt_thread *)parameter;
/* thread check */
RT_ASSERT(thread != RT_NULL);
RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND);
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
/* set error number */
thread->error = -RT_ETIMEOUT; //表示被唤醒原因是:超时
/* remove from suspend list */
rt_list_remove(&(thread->tlist)); //可能因为等待队列等原因而挂起,先移除
/* insert to schedule ready list */
rt_schedule_insert_thread(thread);
/* do schedule */
rt_schedule();
}
RTM_EXPORT(rt_thread_timeout);
超时函数:
- 将线程放入就绪链表尾部
- 发起调度
void rt_schedule_remove_thread(struct rt_thread *thread)
{
register rt_base_t level;
RT_ASSERT(thread != RT_NULL);
/* disable interrupt */
level = rt_hw_interrupt_disable();
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("remove thread[%.*s], the priority: %d\n",
RT_NAME_MAX, thread->name,
thread->current_priority));
/* 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
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
}
将线程从就绪链表中移除,首先从链表中删除,再判断优先级对应的链表是否空了?
可以快速查找到哪一位是1。
每次Tick中断还需要检查定时器
/**
* This function will check timer list, if a timeout event happens, the
* corresponding timeout function will be invoked.
*
* @note this function shall be invoked in operating system timer interrupt.
*/
void rt_timer_check(void)
{
struct rt_timer *t;
rt_tick_t current_tick;
register rt_base_t level;
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));
current_tick = rt_tick_get();
/* disable interrupt */
level = rt_hw_interrupt_disable();
while (!rt_list_isempty(&rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
{
t = rt_list_entry(rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]); //从链表中取出定时器
/*
* It supposes that the new tick shall less than the half duration of
* tick max.
*/
if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2) //判断时间是否到了
{
RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
/* remove timer from timer list firstly */
_rt_timer_remove(t);
/* call timeout function */
t->timeout_func(t->parameter);
/* re-get tick */
current_tick = rt_tick_get();
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
{
/* start it */
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
rt_timer_start(t);
}
else
{
/* stop timer */
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
}
}
else
break;
}
/* enable interrupt */
rt_hw_interrupt_enable(level);
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n"));
}
依次判断定时器时间是否到了,到了的话就调用定时器超时函数。
定时器启动后放到链表中。
Tick中断检查定时器时,也是从链表中取出判断。