voidrt_soft_timer_check(void){rt_tick_t current_tick;rt_list_t*n;structrt_timer*t;RT_DEBUG_LOG(RT_DEBUG_TIMER,("software timer check enter\n"));
current_tick =rt_tick_get();/* lock scheduler */rt_enter_critical();for(n = rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL -1].next;
n !=&(rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL -1]);){
t =rt_list_entry(n,structrt_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));/* move node to the next */
n = n->next;/* remove timer from timer list firstly */_rt_timer_remove(t);/* not lock scheduler when performing timeout function */rt_exit_critical();/* 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));/* lock scheduler */rt_enter_critical();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;/* not check anymore */}/* unlock scheduler */rt_exit_critical();RT_DEBUG_LOG(RT_DEBUG_TIMER,("software timer check leave\n"));}
超时判断方式
/*
* 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_err_trt_timer_start(rt_timer_t timer){.../*
* get timeout tick,
* the max timeout tick shall not great than RT_TICK_MAX/2
*/RT_ASSERT(timer->init_tick < RT_TICK_MAX /2);
timer->timeout_tick =rt_tick_get()+ timer->init_tick;...return RT_EOK;}
/**
* This function will notify kernel there is one tick passed. Normally,
* this function is invoked by clock ISR.
*/voidrt_tick_increase(void){.../* check timer */rt_timer_check();}
rt_err_trt_timer_start(rt_timer_t timer){unsignedint row_lvl;rt_list_t*timer_list;registerrt_base_t level;rt_list_t*row_head[RT_TIMER_SKIP_LIST_LEVEL];unsignedint tst_nr;staticunsignedint random_nr;/* timer check */RT_ASSERT(timer != RT_NULL);RT_ASSERT(rt_object_get_type(&timer->parent)== RT_Object_Class_Timer);/* stop timer firstly */
level =rt_hw_interrupt_disable();/* remove timer from list */_rt_timer_remove(timer);/* change status of timer */
timer->parent.flag &=~RT_TIMER_FLAG_ACTIVATED;rt_hw_interrupt_enable(level);RT_OBJECT_HOOK_CALL(rt_object_take_hook,(&(timer->parent)));/*
* get timeout tick,
* the max timeout tick shall not great than RT_TICK_MAX/2
*/RT_ASSERT(timer->init_tick < RT_TICK_MAX /2);
timer->timeout_tick =rt_tick_get()+ timer->init_tick;/* disable interrupt */
level =rt_hw_interrupt_disable();#ifdefRT_USING_TIMER_SOFTif(timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER){/* insert timer to soft timer list */
timer_list = rt_soft_timer_list;}else#endif{/* insert timer to system timer list */
timer_list = rt_timer_list;}
row_head[0]=&timer_list[0];for(row_lvl =0; row_lvl < RT_TIMER_SKIP_LIST_LEVEL; row_lvl++){for(; row_head[row_lvl]!= timer_list[row_lvl].prev;
row_head[row_lvl]= row_head[row_lvl]->next){structrt_timer*t;rt_list_t*p = row_head[row_lvl]->next;/* fix up the entry pointer */
t =rt_list_entry(p,structrt_timer, row[row_lvl]);/* If we have two timers that timeout at the same time, it's
* preferred that the timer inserted early get called early.
* So insert the new timer to the end the the some-timeout timer
* list.
*/if((t->timeout_tick - timer->timeout_tick)==0){continue;}elseif((t->timeout_tick - timer->timeout_tick)< RT_TICK_MAX /2){break;}}if(row_lvl != RT_TIMER_SKIP_LIST_LEVEL -1)
row_head[row_lvl +1]= row_head[row_lvl]+1;}/* Interestingly, this super simple timer insert counter works very very
* well on distributing the list height uniformly. By means of "very very
* well", I mean it beats the randomness of timer->timeout_tick very easily
* (actually, the timeout_tick is not random and easy to be attacked). */
random_nr++;
tst_nr = random_nr;rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL -1],&(timer->row[RT_TIMER_SKIP_LIST_LEVEL -1]));for(row_lvl =2; row_lvl <= RT_TIMER_SKIP_LIST_LEVEL; row_lvl++){if(!(tst_nr & RT_TIMER_SKIP_LIST_MASK))rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL - row_lvl],&(timer->row[RT_TIMER_SKIP_LIST_LEVEL - row_lvl]));elsebreak;/* Shift over the bits we have tested. Works well with 1 bit and 2
* bits. */
tst_nr >>=(RT_TIMER_SKIP_LIST_MASK +1)>>1;}
timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;/* enable interrupt */rt_hw_interrupt_enable(level);#ifdefRT_USING_TIMER_SOFTif(timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER){/* check whether timer thread is ready */if((timer_thread.stat & RT_THREAD_STAT_MASK)!= RT_THREAD_READY){/* resume timer thread to check soft timer */rt_thread_resume(&timer_thread);rt_schedule();}}#endifreturn RT_EOK;}RTM_EXPORT(rt_timer_start);
#ifdefRT_USING_HOOKexternvoid(*rt_object_take_hook)(structrt_object*object);externvoid(*rt_object_put_hook)(structrt_object*object);staticvoid(*rt_timer_enter_hook)(structrt_timer*timer);staticvoid(*rt_timer_exit_hook)(structrt_timer*timer);/**
* @addtogroup Hook
*//**@{*//**
* This function will set a hook function, which will be invoked when enter
* timer timeout callback function.
*
* @param hook the hook function
*/voidrt_timer_enter_sethook(void(*hook)(structrt_timer*timer)){
rt_timer_enter_hook = hook;}/**
* This function will set a hook function, which will be invoked when exit
* timer timeout callback function.
*
* @param hook the hook function
*/voidrt_timer_exit_sethook(void(*hook)(structrt_timer*timer)){
rt_timer_exit_hook = hook;}/**@}*/#endif
调试
rt_timer_count_height用于计算跳表的层数
rt_timer_dump将每个定时器的跳表层数打印出来
#ifRT_DEBUG_TIMERstaticintrt_timer_count_height(structrt_timer*timer){int i, cnt =0;for(i =0; i < RT_TIMER_SKIP_LIST_LEVEL; i++){if(!rt_list_isempty(&timer->row[i]))
cnt++;}return cnt;}voidrt_timer_dump(rt_list_t timer_heads[]){rt_list_t*list;for(list = timer_heads[RT_TIMER_SKIP_LIST_LEVEL -1].next;
list !=&timer_heads[RT_TIMER_SKIP_LIST_LEVEL -1];
list = list->next){structrt_timer*timer =rt_list_entry(list,structrt_timer,
row[RT_TIMER_SKIP_LIST_LEVEL -1]);rt_kprintf("%d",rt_timer_count_height(timer));}rt_kprintf("\n");}#endif