Browse Source

[fix][kernel][timer]fixed timer ASSERT exception due to multithreaded scheduling

Signed-off-by: WillianChan <chentingwei@rt-thread.com>
WillianChan 3 years ago
parent
commit
75b65ebcf2
1 changed files with 12 additions and 4 deletions
  1. 12 4
      src/timer.c

+ 12 - 4
src/timer.c

@@ -367,6 +367,7 @@ rt_err_t rt_timer_start(rt_timer_t timer)
     unsigned int row_lvl;
     unsigned int row_lvl;
     rt_list_t *timer_list;
     rt_list_t *timer_list;
     register rt_base_t level;
     register rt_base_t level;
+    register rt_bool_t need_schedule;
     rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL];
     rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL];
     unsigned int tst_nr;
     unsigned int tst_nr;
     static unsigned int random_nr;
     static unsigned int random_nr;
@@ -375,6 +376,8 @@ rt_err_t rt_timer_start(rt_timer_t timer)
     RT_ASSERT(timer != RT_NULL);
     RT_ASSERT(timer != RT_NULL);
     RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
     RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
 
 
+    need_schedule = RT_FALSE;
+
     /* stop timer firstly */
     /* stop timer firstly */
     level = rt_hw_interrupt_disable();
     level = rt_hw_interrupt_disable();
     /* remove timer from list */
     /* remove timer from list */
@@ -457,9 +460,6 @@ rt_err_t rt_timer_start(rt_timer_t timer)
 
 
     timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;
     timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;
 
 
-    /* enable interrupt */
-    rt_hw_interrupt_enable(level);
-
 #ifdef RT_USING_TIMER_SOFT
 #ifdef RT_USING_TIMER_SOFT
     if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
     if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
     {
     {
@@ -469,11 +469,19 @@ rt_err_t rt_timer_start(rt_timer_t timer)
         {
         {
             /* resume timer thread to check soft timer */
             /* resume timer thread to check soft timer */
             rt_thread_resume(&_timer_thread);
             rt_thread_resume(&_timer_thread);
-            rt_schedule();
+            need_schedule = RT_TRUE;
         }
         }
     }
     }
 #endif /* RT_USING_TIMER_SOFT */
 #endif /* RT_USING_TIMER_SOFT */
 
 
+    /* enable interrupt */
+    rt_hw_interrupt_enable(level);
+
+    if (need_schedule)
+    {
+        rt_schedule();
+    }
+
     return RT_EOK;
     return RT_EOK;
 }
 }
 RTM_EXPORT(rt_timer_start);
 RTM_EXPORT(rt_timer_start);