4
0
mirror of https://github.com/RT-Thread/rt-thread.git synced 2025-02-21 01:07:18 +08:00

[timer] The rt_timer_check and _soft_timer_check functions are merged (#8884)

This commit is contained in:
wdfk-prog 2024-05-08 09:27:38 +08:00 committed by GitHub
parent 48bd0e49f2
commit 7879986e38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
* Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@ -21,6 +21,7 @@
* 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
* 2024-05-01 wdfk-prog The rt_timer_check and _soft_timer_check functions are merged
*/
#include <rtthread.h>
@ -472,6 +473,84 @@ static rt_err_t _timer_start(rt_list_t *timer_list, rt_timer_t timer)
return RT_EOK;
}
/**
* @brief This function will check timer list, if a timeout event happens,
* the corresponding timeout function will be invoked.
*
* @param timer_list The timer list to check.
* @param lock The lock for the timer list.
*/
static void _timer_check(rt_list_t *timer_list, struct rt_spinlock *lock)
{
struct rt_timer *t;
rt_tick_t current_tick;
rt_base_t level;
rt_list_t list;
level = rt_spin_lock_irqsave(lock);
current_tick = rt_tick_get();
rt_list_init(&list);
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,
struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
/* re-get tick */
current_tick = rt_tick_get();
/*
* 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));
/* remove timer from timer list firstly */
_timer_remove(t);
if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
{
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
}
t->parent.flag |= RT_TIMER_FLAG_PROCESSING;
/* add timer to temporary list */
rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
rt_spin_unlock_irqrestore(lock, level);
/* call timeout function */
t->timeout_func(t->parameter);
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
LOG_D("current tick: %d", current_tick);
level = rt_spin_lock_irqsave(lock);
t->parent.flag &= ~RT_TIMER_FLAG_PROCESSING;
/* Check whether the timer object is detached or started again */
if (rt_list_isempty(&list))
{
continue;
}
rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
{
/* start it */
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
_timer_start(timer_list, t);
}
}
else break;
}
rt_spin_unlock_irqrestore(lock, level);
}
/**
* @brief This function will start the timer
*
@ -669,83 +748,19 @@ RTM_EXPORT(rt_timer_control);
*/
void rt_timer_check(void)
{
struct rt_timer *t;
rt_tick_t current_tick;
rt_base_t level;
rt_list_t list;
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_cpu_get_id() != 0)
{
rt_spin_unlock_irqrestore(&_htimer_lock, level);
return;
}
#endif
_timer_check(_timer_list, &_htimer_lock);
rt_list_init(&list);
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,
struct rt_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));
/* remove timer from timer list firstly */
_timer_remove(t);
if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
{
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
}
t->parent.flag |= RT_TIMER_FLAG_PROCESSING;
/* add timer to temporary list */
rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
rt_spin_unlock_irqrestore(&_htimer_lock, level);
/* 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));
LOG_D("current tick: %d", current_tick);
level = rt_spin_lock_irqsave(&_htimer_lock);
t->parent.flag &= ~RT_TIMER_FLAG_PROCESSING;
/* Check whether the timer object is detached or started again */
if (rt_list_isempty(&list))
{
continue;
}
rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
{
/* start it */
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
_timer_start(_timer_list, t);
}
}
else break;
}
rt_spin_unlock_irqrestore(&_htimer_lock, level);
LOG_D("timer check leave");
}
@ -767,81 +782,6 @@ rt_tick_t rt_timer_next_timeout_tick(void)
}
#ifdef RT_USING_TIMER_SOFT
/**
* @brief This function will check software-timer list, if a timeout event happens, the
* corresponding timeout function will be invoked.
*/
static void _soft_timer_check(void)
{
rt_tick_t current_tick;
struct rt_timer *t;
rt_base_t level;
rt_list_t list;
rt_list_init(&list);
LOG_D("software timer check enter");
level = rt_spin_lock_irqsave(&_stimer_lock);
while (!rt_list_isempty(&_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
{
t = rt_list_entry(_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
current_tick = rt_tick_get();
/*
* 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));
/* remove timer from timer list firstly */
_timer_remove(t);
if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
{
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
}
t->parent.flag |= RT_TIMER_FLAG_PROCESSING;
/* add timer to temporary list */
rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
rt_spin_unlock_irqrestore(&_stimer_lock, level);
/* call timeout function */
t->timeout_func(t->parameter);
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
LOG_D("current tick: %d", current_tick);
level = rt_spin_lock_irqsave(&_stimer_lock);
t->parent.flag &= ~RT_TIMER_FLAG_PROCESSING;
/* Check whether the timer object is detached or started again */
if (rt_list_isempty(&list))
{
continue;
}
rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
{
/* start it */
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
_timer_start(_soft_timer_list, t);
}
}
else break; /* not check anymore */
}
rt_spin_unlock_irqrestore(&_stimer_lock, level);
LOG_D("software timer check leave");
}
/**
* @brief System timer thread entry
*
@ -884,7 +824,11 @@ static void _timer_thread_entry(void *parameter)
}
/* check software timer */
_soft_timer_check();
LOG_D("software timer check enter");
_timer_check(_soft_timer_list, &_stimer_lock);
LOG_D("software timer check leave");
}
}
#endif /* RT_USING_TIMER_SOFT */