1
1
/*
2
- * Copyright (c) 2006-2022 , RT-Thread Development Team
2
+ * Copyright (c) 2006-2024 , RT-Thread Development Team
3
3
*
4
4
* SPDX-License-Identifier: Apache-2.0
5
5
*
21
21
* 2022-04-19 Stanley Correct descriptions
22
22
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
23
23
* 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
24
25
*/
25
26
26
27
#include <rtthread.h>
@@ -399,7 +400,6 @@ static rt_err_t _timer_start(rt_list_t *timer_list, rt_timer_t timer)
399
400
{
400
401
unsigned int row_lvl ;
401
402
rt_list_t * row_head [RT_TIMER_SKIP_LIST_LEVEL ];
402
- unsigned int tst_nr ;
403
403
static unsigned int random_nr ;
404
404
405
405
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)
442
442
break ;
443
443
}
444
444
}
445
+ #if (RT_TIMER_SKIP_LIST_LEVEL > 1 )
445
446
if (row_lvl != RT_TIMER_SKIP_LIST_LEVEL - 1 )
446
447
row_head [row_lvl + 1 ] = row_head [row_lvl ] + 1 ;
448
+ #endif /* RT_TIMER_SKIP_LIST_LEVEL > 1 */
447
449
}
448
450
449
451
/* Interestingly, this super simple timer insert counter works very very
450
452
* well on distributing the list height uniformly. By means of "very very
451
453
* well", I mean it beats the randomness of timer->timeout_tick very easily
452
454
* (actually, the timeout_tick is not random and easy to be attacked). */
453
455
random_nr ++ ;
454
- tst_nr = random_nr ;
455
456
456
457
rt_list_insert_after (row_head [RT_TIMER_SKIP_LIST_LEVEL - 1 ],
457
458
& (timer -> row [RT_TIMER_SKIP_LIST_LEVEL - 1 ]));
459
+ #if (RT_TIMER_SKIP_LIST_LEVEL > 1 )
460
+ unsigned int tst_nr = random_nr ;
458
461
for (row_lvl = 2 ; row_lvl <= RT_TIMER_SKIP_LIST_LEVEL ; row_lvl ++ )
459
462
{
460
463
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)
466
469
* bits. */
467
470
tst_nr >>= (RT_TIMER_SKIP_LIST_MASK + 1 ) >> 1 ;
468
471
}
472
+ #endif /* RT_TIMER_SKIP_LIST_LEVEL > 1 */
469
473
470
474
timer -> parent .flag |= RT_TIMER_FLAG_ACTIVATED ;
471
475
472
476
return RT_EOK ;
473
477
}
474
478
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
+
475
557
/**
476
558
* @brief This function will start the timer
477
559
*
@@ -669,83 +751,19 @@ RTM_EXPORT(rt_timer_control);
669
751
*/
670
752
void rt_timer_check (void )
671
753
{
672
- struct rt_timer * t ;
673
- rt_tick_t current_tick ;
674
- rt_base_t level ;
675
- rt_list_t list ;
676
-
677
754
RT_ASSERT (rt_interrupt_get_nest () > 0 );
678
755
679
756
LOG_D ("timer check enter" );
680
757
681
- level = rt_spin_lock_irqsave (& _htimer_lock );
682
-
683
- current_tick = rt_tick_get ();
684
-
685
758
#ifdef RT_USING_SMP
686
759
/* Running on core 0 only */
687
760
if (rt_hw_cpu_id () != 0 )
688
761
{
689
- rt_spin_unlock_irqrestore (& _htimer_lock , level );
690
762
return ;
691
763
}
692
764
#endif
765
+ _timer_check (_timer_list , & _htimer_lock );
693
766
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 );
749
767
LOG_D ("timer check leave" );
750
768
}
751
769
@@ -767,81 +785,6 @@ rt_tick_t rt_timer_next_timeout_tick(void)
767
785
}
768
786
769
787
#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
-
845
788
/**
846
789
* @brief System timer thread entry
847
790
*
@@ -884,7 +827,11 @@ static void _timer_thread_entry(void *parameter)
884
827
}
885
828
886
829
/* 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" );
888
835
}
889
836
}
890
837
#endif /* RT_USING_TIMER_SOFT */
0 commit comments