RT_Thread内核机制学习(二)
对于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 > 32rt_thread_ready_table[thread->number] &= ~thread->high_mask;if (rt_thread_ready_table[thread->number] == 0){rt_thread_ready_priority_group &= ~thread->number_mask;}
#elsert_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;}}elsebreak;}/* enable interrupt */rt_hw_interrupt_enable(level);RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n"));
}
依次判断定时器时间是否到了,到了的话就调用定时器超时函数。
定时器启动后放到链表中。
Tick中断检查定时器时,也是从链表中取出判断。