summaryrefslogtreecommitdiff
path: root/src/timer.c
diff options
context:
space:
mode:
authorShell <[email protected]>2024-02-23 17:49:15 +0800
committerGitHub <[email protected]>2024-02-23 17:49:15 +0800
commit71560bafb5735220696ca24a42ba4a668b55949b (patch)
tree236df5973a1fd5b6f0cc9f6c6b6a2d71fd069203 /src/timer.c
parent6fe69d7431ed54fcea863ed68d7c4f9746e771b0 (diff)
🎯 Sync smart & scheduler codes (#8537)
Signed-off-by: Shell <[email protected]> Co-authored-by: xqyjlj <[email protected]>
Diffstat (limited to 'src/timer.c')
-rw-r--r--src/timer.c147
1 files changed, 88 insertions, 59 deletions
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 <rtthread.h>
@@ -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,