From 7a7e3002c8fc2b4a65891db5ea84762ecdbcb66c Mon Sep 17 00:00:00 2001 From: bernard Date: Sat, 12 Jul 2014 15:59:45 +0800 Subject: [PATCH] [Kernel] system does not lock scheduler when invoking soft-timer timeout function. --- src/timer.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/timer.c b/src/timer.c index ac8a148d8d..9785403d8b 100644 --- a/src/timer.c +++ b/src/timer.c @@ -28,6 +28,8 @@ * 2010-05-12 Bernard fix the timer check bug. * 2010-11-02 Charlie re-implement tick overflow issue * 2012-12-15 Bernard fix the next timeout issue in soft timer + * 2014-07-12 Bernard does not lock scheduler when invoking soft-timer + * timeout function. */ #include @@ -140,6 +142,7 @@ static int rt_timer_count_height(struct rt_timer *timer) return cnt; } +#if RT_DEBUG_TIMER void rt_timer_dump(rt_list_t timer_heads[]) { rt_list_t *list; @@ -155,6 +158,7 @@ void rt_timer_dump(rt_list_t timer_heads[]) } rt_kprintf("\n"); } +#endif /** * @addtogroup Clock @@ -298,8 +302,14 @@ rt_err_t rt_timer_start(rt_timer_t timer) /* timer check */ RT_ASSERT(timer != RT_NULL); - if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) - return -RT_ERROR; + + /* 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))); @@ -560,6 +570,9 @@ void rt_soft_timer_check(void) 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]);) { @@ -579,6 +592,8 @@ void rt_soft_timer_check(void) /* 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); @@ -587,6 +602,9 @@ void rt_soft_timer_check(void) 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)) { @@ -603,6 +621,9 @@ void rt_soft_timer_check(void) else break; /* not check anymore */ } + /* unlock scheduler */ + rt_exit_critical(); + RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n")); } @@ -636,12 +657,8 @@ static void rt_thread_timer_entry(void *parameter) } } - /* lock scheduler */ - rt_enter_critical(); /* check software timer */ rt_soft_timer_check(); - /* unlock scheduler */ - rt_exit_critical(); } } #endif -- GitLab