Skip to content

Commit 01585c9

Browse files
committed
[timer] Merge and optimize some code
- The rt_timer_check and _soft_timer_check functions are merged - With macro compilation, some code is no longer executed when RT_TIMER_SKIP_LIST_LEVEL=1
1 parent 75f4172 commit 01585c9

File tree

1 file changed

+91
-144
lines changed

1 file changed

+91
-144
lines changed

src/timer.c

+91-144
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2006-2022, RT-Thread Development Team
2+
* Copyright (c) 2006-2024, RT-Thread Development Team
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*
@@ -21,6 +21,7 @@
2121
* 2022-04-19 Stanley Correct descriptions
2222
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
2323
* 2024-01-25 Shell add RT_TIMER_FLAG_THREAD_TIMER for timer to sync with sched
24+
* 2024-05-01 wdfk-prog Merge and optimize some code
2425
*/
2526

2627
#include <rtthread.h>
@@ -399,7 +400,6 @@ static rt_err_t _timer_start(rt_list_t *timer_list, rt_timer_t timer)
399400
{
400401
unsigned int row_lvl;
401402
rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL];
402-
unsigned int tst_nr;
403403
static unsigned int random_nr;
404404

405405
if (timer->parent.flag & RT_TIMER_FLAG_PROCESSING)
@@ -442,19 +442,22 @@ static rt_err_t _timer_start(rt_list_t *timer_list, rt_timer_t timer)
442442
break;
443443
}
444444
}
445+
#if (RT_TIMER_SKIP_LIST_LEVEL > 1)
445446
if (row_lvl != RT_TIMER_SKIP_LIST_LEVEL - 1)
446447
row_head[row_lvl + 1] = row_head[row_lvl] + 1;
448+
#endif /* RT_TIMER_SKIP_LIST_LEVEL > 1 */
447449
}
448450

449451
/* Interestingly, this super simple timer insert counter works very very
450452
* well on distributing the list height uniformly. By means of "very very
451453
* well", I mean it beats the randomness of timer->timeout_tick very easily
452454
* (actually, the timeout_tick is not random and easy to be attacked). */
453455
random_nr++;
454-
tst_nr = random_nr;
455456

456457
rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL - 1],
457458
&(timer->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
459+
#if (RT_TIMER_SKIP_LIST_LEVEL > 1)
460+
unsigned int tst_nr = random_nr;
458461
for (row_lvl = 2; row_lvl <= RT_TIMER_SKIP_LIST_LEVEL; row_lvl++)
459462
{
460463
if (!(tst_nr & RT_TIMER_SKIP_LIST_MASK))
@@ -466,12 +469,91 @@ static rt_err_t _timer_start(rt_list_t *timer_list, rt_timer_t timer)
466469
* bits. */
467470
tst_nr >>= (RT_TIMER_SKIP_LIST_MASK + 1) >> 1;
468471
}
472+
#endif /* RT_TIMER_SKIP_LIST_LEVEL > 1 */
469473

470474
timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;
471475

472476
return RT_EOK;
473477
}
474478

479+
/**
480+
* @brief This function will check timer list, if a timeout event happens,
481+
* the corresponding timeout function will be invoked.
482+
*
483+
* @param timer_list The timer list to check.
484+
* @param lock The lock for the timer list.
485+
*/
486+
static void _timer_check(rt_list_t *timer_list, struct rt_spinlock *lock)
487+
{
488+
struct rt_timer *t;
489+
rt_tick_t current_tick;
490+
rt_base_t level;
491+
rt_list_t list;
492+
493+
level = rt_spin_lock_irqsave(lock);
494+
495+
current_tick = rt_tick_get();
496+
497+
rt_list_init(&list);
498+
499+
while (!rt_list_isempty(&timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
500+
{
501+
t = rt_list_entry(timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
502+
struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
503+
504+
/* re-get tick */
505+
current_tick = rt_tick_get();
506+
507+
/*
508+
* It supposes that the new tick shall less than the half duration of
509+
* tick max.
510+
*/
511+
if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
512+
{
513+
RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
514+
515+
/* remove timer from timer list firstly */
516+
_timer_remove(t);
517+
if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
518+
{
519+
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
520+
}
521+
522+
t->parent.flag |= RT_TIMER_FLAG_PROCESSING;
523+
/* add timer to temporary list */
524+
rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
525+
526+
rt_spin_unlock_irqrestore(lock, level);
527+
528+
/* call timeout function */
529+
t->timeout_func(t->parameter);
530+
531+
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
532+
LOG_D("current tick: %d", current_tick);
533+
534+
level = rt_spin_lock_irqsave(lock);
535+
536+
t->parent.flag &= ~RT_TIMER_FLAG_PROCESSING;
537+
538+
/* Check whether the timer object is detached or started again */
539+
if (rt_list_isempty(&list))
540+
{
541+
continue;
542+
}
543+
rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
544+
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
545+
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
546+
{
547+
/* start it */
548+
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
549+
_timer_start(timer_list, t);
550+
}
551+
}
552+
else break;
553+
}
554+
rt_spin_unlock_irqrestore(lock, level);
555+
}
556+
475557
/**
476558
* @brief This function will start the timer
477559
*
@@ -669,83 +751,19 @@ RTM_EXPORT(rt_timer_control);
669751
*/
670752
void rt_timer_check(void)
671753
{
672-
struct rt_timer *t;
673-
rt_tick_t current_tick;
674-
rt_base_t level;
675-
rt_list_t list;
676-
677754
RT_ASSERT(rt_interrupt_get_nest() > 0);
678755

679756
LOG_D("timer check enter");
680757

681-
level = rt_spin_lock_irqsave(&_htimer_lock);
682-
683-
current_tick = rt_tick_get();
684-
685758
#ifdef RT_USING_SMP
686759
/* Running on core 0 only */
687760
if (rt_hw_cpu_id() != 0)
688761
{
689-
rt_spin_unlock_irqrestore(&_htimer_lock, level);
690762
return;
691763
}
692764
#endif
765+
_timer_check(_timer_list, &_htimer_lock);
693766

694-
rt_list_init(&list);
695-
696-
while (!rt_list_isempty(&_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
697-
{
698-
t = rt_list_entry(_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
699-
struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
700-
701-
/*
702-
* It supposes that the new tick shall less than the half duration of
703-
* tick max.
704-
*/
705-
if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
706-
{
707-
RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
708-
709-
/* remove timer from timer list firstly */
710-
_timer_remove(t);
711-
if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
712-
{
713-
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
714-
}
715-
716-
t->parent.flag |= RT_TIMER_FLAG_PROCESSING;
717-
/* add timer to temporary list */
718-
rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
719-
rt_spin_unlock_irqrestore(&_htimer_lock, level);
720-
/* call timeout function */
721-
t->timeout_func(t->parameter);
722-
723-
/* re-get tick */
724-
current_tick = rt_tick_get();
725-
726-
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
727-
LOG_D("current tick: %d", current_tick);
728-
level = rt_spin_lock_irqsave(&_htimer_lock);
729-
730-
t->parent.flag &= ~RT_TIMER_FLAG_PROCESSING;
731-
732-
/* Check whether the timer object is detached or started again */
733-
if (rt_list_isempty(&list))
734-
{
735-
continue;
736-
}
737-
rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
738-
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
739-
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
740-
{
741-
/* start it */
742-
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
743-
_timer_start(_timer_list, t);
744-
}
745-
}
746-
else break;
747-
}
748-
rt_spin_unlock_irqrestore(&_htimer_lock, level);
749767
LOG_D("timer check leave");
750768
}
751769

@@ -767,81 +785,6 @@ rt_tick_t rt_timer_next_timeout_tick(void)
767785
}
768786

769787
#ifdef RT_USING_TIMER_SOFT
770-
/**
771-
* @brief This function will check software-timer list, if a timeout event happens, the
772-
* corresponding timeout function will be invoked.
773-
*/
774-
static void _soft_timer_check(void)
775-
{
776-
rt_tick_t current_tick;
777-
struct rt_timer *t;
778-
rt_base_t level;
779-
rt_list_t list;
780-
781-
rt_list_init(&list);
782-
LOG_D("software timer check enter");
783-
level = rt_spin_lock_irqsave(&_stimer_lock);
784-
785-
while (!rt_list_isempty(&_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
786-
{
787-
t = rt_list_entry(_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
788-
struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
789-
790-
current_tick = rt_tick_get();
791-
792-
/*
793-
* It supposes that the new tick shall less than the half duration of
794-
* tick max.
795-
*/
796-
if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
797-
{
798-
RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
799-
800-
/* remove timer from timer list firstly */
801-
_timer_remove(t);
802-
if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
803-
{
804-
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
805-
}
806-
807-
t->parent.flag |= RT_TIMER_FLAG_PROCESSING;
808-
/* add timer to temporary list */
809-
rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
810-
811-
rt_spin_unlock_irqrestore(&_stimer_lock, level);
812-
813-
/* call timeout function */
814-
t->timeout_func(t->parameter);
815-
816-
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
817-
LOG_D("current tick: %d", current_tick);
818-
819-
level = rt_spin_lock_irqsave(&_stimer_lock);
820-
821-
t->parent.flag &= ~RT_TIMER_FLAG_PROCESSING;
822-
823-
/* Check whether the timer object is detached or started again */
824-
if (rt_list_isempty(&list))
825-
{
826-
continue;
827-
}
828-
rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
829-
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
830-
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
831-
{
832-
/* start it */
833-
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
834-
_timer_start(_soft_timer_list, t);
835-
}
836-
}
837-
else break; /* not check anymore */
838-
}
839-
840-
rt_spin_unlock_irqrestore(&_stimer_lock, level);
841-
842-
LOG_D("software timer check leave");
843-
}
844-
845788
/**
846789
* @brief System timer thread entry
847790
*
@@ -884,7 +827,11 @@ static void _timer_thread_entry(void *parameter)
884827
}
885828

886829
/* check software timer */
887-
_soft_timer_check();
830+
LOG_D("software timer check enter");
831+
832+
_timer_check(_soft_timer_list, &_stimer_lock);
833+
834+
LOG_D("software timer check leave");
888835
}
889836
}
890837
#endif /* RT_USING_TIMER_SOFT */

0 commit comments

Comments
 (0)