From 3283f54c7a0444b2e51ec79a4da57e7871528f05 Mon Sep 17 00:00:00 2001 From: xqyjlj Date: Wed, 25 Oct 2023 20:31:25 +0800 Subject: 🎈 perf: perf rt_hw_interrupt_disable/enable (#8042) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Shell Co-authored-by: Shell --- src/timer.c | 165 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 92 insertions(+), 73 deletions(-) (limited to 'src/timer.c') diff --git a/src/timer.c b/src/timer.c index 6a077f7575..98e8f6defb 100644 --- a/src/timer.c +++ b/src/timer.c @@ -19,6 +19,7 @@ * 2021-08-15 supperthomas add the comment * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to timer.c * 2022-04-19 Stanley Correct descriptions + * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable */ #include @@ -30,6 +31,7 @@ /* hard timer list */ static rt_list_t _timer_list[RT_TIMER_SKIP_LIST_LEVEL]; +static struct rt_spinlock _hard_spinlock; #ifdef RT_USING_TIMER_SOFT @@ -48,6 +50,7 @@ static rt_list_t _timer_list[RT_TIMER_SKIP_LIST_LEVEL]; static rt_uint8_t _soft_timer_status = RT_SOFT_TIMER_IDLE; /* soft timer list */ static rt_list_t _soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL]; +static struct rt_spinlock _soft_spinlock; static struct rt_thread _timer_thread; rt_align(RT_ALIGN_SIZE) static rt_uint8_t _timer_thread_stack[RT_TIMER_THREAD_STACK_SIZE]; @@ -161,26 +164,14 @@ static void _timer_init(rt_timer_t timer, static rt_err_t _timer_list_next_timeout(rt_list_t timer_list[], rt_tick_t *timeout_tick) { struct rt_timer *timer; - rt_base_t level; - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); if (!rt_list_isempty(&timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1])) { timer = rt_list_entry(timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next, struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]); *timeout_tick = timer->timeout_tick; - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - return RT_EOK; } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - return -RT_ERROR; } @@ -294,22 +285,31 @@ RTM_EXPORT(rt_timer_init); rt_err_t rt_timer_detach(rt_timer_t timer) { rt_base_t level; + struct rt_spinlock *spinlock; /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); RT_ASSERT(rt_object_is_systemobject(&timer->parent)); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); +#ifdef RT_USING_TIMER_SOFT + if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) + { + spinlock = &_soft_spinlock; + } + else +#endif /* RT_USING_TIMER_SOFT */ + { + spinlock = &_hard_spinlock; + } + + level = rt_spin_lock_irqsave(spinlock); _timer_remove(timer); /* stop timer */ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; - /* enable interrupt */ - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(spinlock, level); rt_object_detach(&(timer->parent)); return RT_EOK; @@ -378,22 +378,30 @@ RTM_EXPORT(rt_timer_create); rt_err_t rt_timer_delete(rt_timer_t timer) { rt_base_t level; + struct rt_spinlock *spinlock; /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); RT_ASSERT(rt_object_is_systemobject(&timer->parent) == RT_FALSE); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); +#ifdef RT_USING_TIMER_SOFT + if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) + { + spinlock = &_soft_spinlock; + } + else +#endif /* RT_USING_TIMER_SOFT */ + { + spinlock = &_hard_spinlock; + } + + level = rt_spin_lock_irqsave(spinlock); _timer_remove(timer); /* stop timer */ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(spinlock, level); rt_object_delete(&(timer->parent)); return RT_EOK; @@ -413,41 +421,42 @@ rt_err_t rt_timer_start(rt_timer_t timer) unsigned int row_lvl; rt_list_t *timer_list; rt_base_t level; - rt_bool_t need_schedule; rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL]; unsigned int tst_nr; static unsigned int random_nr; + struct rt_spinlock *spinlock; /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); - need_schedule = RT_FALSE; - - /* stop timer firstly */ - level = rt_hw_interrupt_disable(); - /* remove timer from list */ - _timer_remove(timer); - /* change status of timer */ - timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; - - RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent))); - - timer->timeout_tick = rt_tick_get() + timer->init_tick; #ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { /* insert timer to soft timer list */ timer_list = _soft_timer_list; + spinlock = &_soft_spinlock; } else #endif /* RT_USING_TIMER_SOFT */ { /* insert timer to system timer list */ timer_list = _timer_list; + spinlock = &_hard_spinlock; } + /* stop timer firstly */ + level = rt_spin_lock_irqsave(spinlock); + /* remove timer from list */ + _timer_remove(timer); + /* change status of timer */ + timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; + + RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent))); + + timer->timeout_tick = rt_tick_get() + timer->init_tick; + row_head[0] = &timer_list[0]; for (row_lvl = 0; row_lvl < RT_TIMER_SKIP_LIST_LEVEL; row_lvl++) { @@ -510,18 +519,12 @@ rt_err_t rt_timer_start(rt_timer_t timer) { /* resume timer thread to check soft timer */ rt_thread_resume(&_timer_thread); - need_schedule = RT_TRUE; } } #endif /* RT_USING_TIMER_SOFT */ - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(spinlock, level); - if (need_schedule) - { - rt_schedule(); - } return RT_EOK; } @@ -537,28 +540,35 @@ RTM_EXPORT(rt_timer_start); rt_err_t rt_timer_stop(rt_timer_t timer) { rt_base_t level; - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + struct rt_spinlock *spinlock; /* timer check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); +#ifdef RT_USING_TIMER_SOFT + if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) + { + spinlock = &_soft_spinlock; + } + else +#endif /* RT_USING_TIMER_SOFT */ + { + spinlock = &_hard_spinlock; + } + level = rt_spin_lock_irqsave(spinlock); + if (!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)) { - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(spinlock, level); return -RT_ERROR; } - RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(timer->parent))); _timer_remove(timer); /* change status */ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; - - /* enable interrupt */ - rt_hw_interrupt_enable(level); + rt_spin_unlock_irqrestore(spinlock, level); return RT_EOK; } @@ -575,13 +585,10 @@ RTM_EXPORT(rt_timer_stop); */ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg) { - rt_base_t level; - /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); - level = rt_hw_interrupt_disable(); switch (cmd) { case RT_TIMER_CTRL_GET_TIME: @@ -636,7 +643,6 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg) default: break; } - rt_hw_interrupt_enable(level); return RT_EOK; } @@ -655,14 +661,20 @@ void rt_timer_check(void) rt_base_t level; rt_list_t list; +#ifdef RT_USING_SMP + if (rt_hw_cpu_id() != 0) + { + return; + } +#endif + rt_list_init(&list); LOG_D("timer check enter"); current_tick = rt_tick_get(); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&_hard_spinlock); while (!rt_list_isempty(&_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1])) { @@ -685,6 +697,7 @@ void rt_timer_check(void) } /* add timer to temporary list */ rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1])); + rt_spin_unlock_irqrestore(&_hard_spinlock, level); /* call timeout function */ t->timeout_func(t->parameter); @@ -693,7 +706,7 @@ void rt_timer_check(void) RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t)); LOG_D("current tick: %d", current_tick); - + level = rt_spin_lock_irqsave(&_hard_spinlock); /* Check whether the timer object is detached or started again */ if (rt_list_isempty(&list)) { @@ -710,10 +723,7 @@ void rt_timer_check(void) } else break; } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - + rt_spin_unlock_irqrestore(&_hard_spinlock, level); LOG_D("timer check leave"); } @@ -724,8 +734,13 @@ void rt_timer_check(void) */ rt_tick_t rt_timer_next_timeout_tick(void) { + rt_base_t level; rt_tick_t next_timeout = RT_TICK_MAX; + + level = rt_spin_lock_irqsave(&_hard_spinlock); _timer_list_next_timeout(_timer_list, &next_timeout); + rt_spin_unlock_irqrestore(&_hard_spinlock, level); + return next_timeout; } @@ -742,11 +757,8 @@ void rt_soft_timer_check(void) rt_list_t list; rt_list_init(&list); - LOG_D("software timer check enter"); - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&_soft_spinlock); while (!rt_list_isempty(&_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1])) { @@ -773,8 +785,8 @@ void rt_soft_timer_check(void) rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1])); _soft_timer_status = RT_SOFT_TIMER_BUSY; - /* enable interrupt */ - rt_hw_interrupt_enable(level); + + rt_spin_unlock_irqrestore(&_soft_spinlock, level); /* call timeout function */ t->timeout_func(t->parameter); @@ -782,8 +794,7 @@ void rt_soft_timer_check(void) RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t)); LOG_D("current tick: %d", current_tick); - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + level = rt_spin_lock_irqsave(&_soft_spinlock); _soft_timer_status = RT_SOFT_TIMER_IDLE; /* Check whether the timer object is detached or started again */ @@ -802,8 +813,8 @@ void rt_soft_timer_check(void) } else break; /* not check anymore */ } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + + rt_spin_unlock_irqrestore(&_soft_spinlock, level); LOG_D("software timer check leave"); } @@ -815,12 +826,18 @@ void rt_soft_timer_check(void) */ static void _timer_thread_entry(void *parameter) { + rt_err_t ret = RT_ERROR; rt_tick_t next_timeout; + rt_base_t level; while (1) { /* get the next timeout tick */ - if (_timer_list_next_timeout(_soft_timer_list, &next_timeout) != RT_EOK) + level = rt_spin_lock_irqsave(&_soft_spinlock); + ret = _timer_list_next_timeout(_soft_timer_list, &next_timeout); + rt_spin_unlock_irqrestore(&_soft_spinlock, level); + + if (ret != RT_EOK) { /* no software timer exist, suspend self. */ rt_thread_suspend_with_flag(rt_thread_self(), RT_UNINTERRUPTIBLE); @@ -860,6 +877,7 @@ void rt_system_timer_init(void) { rt_list_init(_timer_list + i); } + rt_spin_lock_init(&_hard_spinlock); } /** @@ -878,6 +896,7 @@ void rt_system_timer_thread_init(void) { rt_list_init(_soft_timer_list + i); } + rt_spin_lock_init(&_soft_spinlock); /* start software timer thread */ rt_thread_init(&_timer_thread, -- cgit v1.3.1