From 71560bafb5735220696ca24a42ba4a668b55949b Mon Sep 17 00:00:00 2001 From: Shell Date: Fri, 23 Feb 2024 17:49:15 +0800 Subject: 🎯 Sync smart & scheduler codes (#8537) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Shell Co-authored-by: xqyjlj --- src/timer.c | 147 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 88 insertions(+), 59 deletions(-) (limited to 'src/timer.c') diff --git a/src/timer.c b/src/timer.c index a470ca2890..e9ab34eb07 100644 --- a/src/timer.c +++ b/src/timer.c @@ -20,6 +20,7 @@ * 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 + * 2024-01-25 Shell add RT_TIMER_FLAG_THREAD_TIMER for timer to sync with sched */ #include @@ -31,7 +32,7 @@ /* hard timer list */ static rt_list_t _timer_list[RT_TIMER_SKIP_LIST_LEVEL]; -static struct rt_spinlock _hard_spinlock; +static struct rt_spinlock _htimer_lock; #ifdef RT_USING_TIMER_SOFT @@ -50,7 +51,7 @@ static struct rt_spinlock _hard_spinlock; 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_spinlock _stimer_lock; static struct rt_thread _timer_thread; static struct rt_semaphore _soft_timer_sem; rt_align(RT_ALIGN_SIZE) @@ -94,6 +95,35 @@ void rt_timer_exit_sethook(void (*hook)(struct rt_timer *timer)) /**@}*/ #endif /* RT_USING_HOOK */ +rt_inline struct rt_spinlock* _timerlock_idx(struct rt_timer *timer) +{ +#ifdef RT_USING_TIMER_SOFT + if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) + { + return &_stimer_lock; + } + else +#endif /* RT_USING_TIMER_SOFT */ + { + return &_htimer_lock; + } +} + +rt_inline rt_list_t* _timerhead_idx(struct rt_timer *timer) +{ +#ifdef RT_USING_TIMER_SOFT + if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) + { + /* insert timer to soft timer list */ + return _soft_timer_list; + } + else +#endif /* RT_USING_TIMER_SOFT */ + { + /* insert timer to system timer list */ + return _timer_list; + } +} /** * @brief [internal] The init funtion of timer @@ -280,17 +310,7 @@ rt_err_t rt_timer_detach(rt_timer_t timer) RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); RT_ASSERT(rt_object_is_systemobject(&timer->parent)); -#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; - } - + spinlock = _timerlock_idx(timer); level = rt_spin_lock_irqsave(spinlock); _timer_remove(timer); @@ -325,6 +345,7 @@ RTM_EXPORT(rt_timer_detach); * * RT_TIMER_FLAG_HARD_TIMER Hardware timer * RT_TIMER_FLAG_SOFT_TIMER Software timer + * RT_TIMER_FLAG_THREAD_TIMER Thread timer * * NOTE: * You can use multiple values with "|" logical operator. By default, system will use the RT_TIME_FLAG_HARD_TIMER. @@ -373,16 +394,7 @@ rt_err_t rt_timer_delete(rt_timer_t timer) RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); RT_ASSERT(rt_object_is_systemobject(&timer->parent) == RT_FALSE); -#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; - } + spinlock = _timerlock_idx(timer); level = rt_spin_lock_irqsave(spinlock); @@ -485,6 +497,8 @@ static rt_err_t _timer_start(rt_list_t *timer_list, rt_timer_t timer) */ rt_err_t rt_timer_start(rt_timer_t timer) { + rt_sched_lock_level_t slvl; + int is_thread_timer = 0; struct rt_spinlock *spinlock; rt_list_t *timer_list; rt_base_t level; @@ -498,13 +512,24 @@ rt_err_t rt_timer_start(rt_timer_t timer) if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { timer_list = _soft_timer_list; - spinlock = &_soft_spinlock; + spinlock = &_stimer_lock; } else #endif /* RT_USING_TIMER_SOFT */ { timer_list = _timer_list; - spinlock = &_hard_spinlock; + spinlock = &_htimer_lock; + } + + if (timer->parent.flag & RT_TIMER_FLAG_THREAD_TIMER) + { + rt_thread_t thread; + is_thread_timer = 1; + rt_sched_lock(&slvl); + + thread = rt_container_of(timer, struct rt_thread, thread_timer); + RT_ASSERT(rt_object_get_type(&thread->parent) == RT_Object_Class_Thread); + rt_sched_thread_timer_start(thread); } level = rt_spin_lock_irqsave(spinlock); @@ -512,17 +537,19 @@ rt_err_t rt_timer_start(rt_timer_t timer) err = _timer_start(timer_list, timer); #ifdef RT_USING_TIMER_SOFT - if (err == RT_EOK) + if (err == RT_EOK && (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)) { - if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) - { - rt_sem_release(&_soft_timer_sem); - } + rt_sem_release(&_soft_timer_sem); } #endif /* RT_USING_TIMER_SOFT */ rt_spin_unlock_irqrestore(spinlock, level); + if (is_thread_timer) + { + rt_sched_unlock(slvl); + } + return err; } RTM_EXPORT(rt_timer_start); @@ -543,16 +570,8 @@ rt_err_t rt_timer_stop(rt_timer_t timer) 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; - } + spinlock = _timerlock_idx(timer); + level = rt_spin_lock_irqsave(spinlock); if (!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)) @@ -565,6 +584,7 @@ rt_err_t rt_timer_stop(rt_timer_t timer) _timer_remove(timer); /* change status */ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; + rt_spin_unlock_irqrestore(spinlock, level); return RT_EOK; @@ -582,10 +602,16 @@ RTM_EXPORT(rt_timer_stop); */ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg) { + struct rt_spinlock *spinlock; + rt_base_t level; + /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); + spinlock = _timerlock_idx(timer); + + level = rt_spin_lock_irqsave(spinlock); switch (cmd) { case RT_TIMER_CTRL_GET_TIME: @@ -640,6 +666,7 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg) default: break; } + rt_spin_unlock_irqrestore(spinlock, level); return RT_EOK; } @@ -660,21 +687,23 @@ void rt_timer_check(void) RT_ASSERT(rt_interrupt_get_nest() > 0); + LOG_D("timer check enter"); + + level = rt_spin_lock_irqsave(&_htimer_lock); + + current_tick = rt_tick_get(); + #ifdef RT_USING_SMP + /* Running on core 0 only */ if (rt_hw_cpu_id() != 0) { + rt_spin_unlock_irqrestore(&_htimer_lock, level); return; } #endif rt_list_init(&list); - LOG_D("timer check enter"); - - current_tick = rt_tick_get(); - - level = rt_spin_lock_irqsave(&_hard_spinlock); - while (!rt_list_isempty(&_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1])) { t = rt_list_entry(_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next, @@ -696,7 +725,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); + rt_spin_unlock_irqrestore(&_htimer_lock, level); /* call timeout function */ t->timeout_func(t->parameter); @@ -705,7 +734,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); + level = rt_spin_lock_irqsave(&_htimer_lock); /* Check whether the timer object is detached or started again */ if (rt_list_isempty(&list)) { @@ -722,7 +751,7 @@ void rt_timer_check(void) } else break; } - rt_spin_unlock_irqrestore(&_hard_spinlock, level); + rt_spin_unlock_irqrestore(&_htimer_lock, level); LOG_D("timer check leave"); } @@ -736,9 +765,9 @@ 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); + level = rt_spin_lock_irqsave(&_htimer_lock); _timer_list_next_timeout(_timer_list, &next_timeout); - rt_spin_unlock_irqrestore(&_hard_spinlock, level); + rt_spin_unlock_irqrestore(&_htimer_lock, level); return next_timeout; } @@ -757,7 +786,7 @@ static void _soft_timer_check(void) rt_list_init(&list); LOG_D("software timer check enter"); - level = rt_spin_lock_irqsave(&_soft_spinlock); + level = rt_spin_lock_irqsave(&_stimer_lock); while (!rt_list_isempty(&_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1])) { @@ -785,7 +814,7 @@ static void _soft_timer_check(void) _soft_timer_status = RT_SOFT_TIMER_BUSY; - rt_spin_unlock_irqrestore(&_soft_spinlock, level); + rt_spin_unlock_irqrestore(&_stimer_lock, level); /* call timeout function */ t->timeout_func(t->parameter); @@ -793,7 +822,7 @@ static void _soft_timer_check(void) RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t)); LOG_D("current tick: %d", current_tick); - level = rt_spin_lock_irqsave(&_soft_spinlock); + level = rt_spin_lock_irqsave(&_stimer_lock); _soft_timer_status = RT_SOFT_TIMER_IDLE; /* Check whether the timer object is detached or started again */ @@ -813,7 +842,7 @@ static void _soft_timer_check(void) else break; /* not check anymore */ } - rt_spin_unlock_irqrestore(&_soft_spinlock, level); + rt_spin_unlock_irqrestore(&_stimer_lock, level); LOG_D("software timer check leave"); } @@ -836,9 +865,9 @@ static void _timer_thread_entry(void *parameter) while (1) { /* get the next timeout tick */ - level = rt_spin_lock_irqsave(&_soft_spinlock); + level = rt_spin_lock_irqsave(&_stimer_lock); ret = _timer_list_next_timeout(_soft_timer_list, &next_timeout); - rt_spin_unlock_irqrestore(&_soft_spinlock, level); + rt_spin_unlock_irqrestore(&_stimer_lock, level); if (ret != RT_EOK) { @@ -878,7 +907,7 @@ void rt_system_timer_init(void) { rt_list_init(_timer_list + i); } - rt_spin_lock_init(&_hard_spinlock); + rt_spin_lock_init(&_htimer_lock); } /** @@ -897,7 +926,7 @@ void rt_system_timer_thread_init(void) { rt_list_init(_soft_timer_list + i); } - rt_spin_lock_init(&_soft_spinlock); + rt_spin_lock_init(&_stimer_lock); rt_sem_init(&_soft_timer_sem, "stimer", 0, RT_IPC_FLAG_PRIO); /* start software timer thread */ rt_thread_init(&_timer_thread, -- cgit v1.3.1