34
34
#include <rthw.h>
35
35
36
36
/* hard timer list */
37
- static rt_list_t rt_timer_list = RT_LIST_OBJECT_INIT ( rt_timer_list ) ;
37
+ static rt_list_t rt_timer_list [ RT_TIMER_SKIP_LIST_LEVEL ] ;
38
38
39
39
#ifdef RT_USING_TIMER_SOFT
40
40
#ifndef RT_TIMER_THREAD_STACK_SIZE
@@ -46,7 +46,7 @@ static rt_list_t rt_timer_list = RT_LIST_OBJECT_INIT(rt_timer_list);
46
46
#endif
47
47
48
48
/* soft timer list */
49
- static rt_list_t rt_soft_timer_list ;
49
+ static rt_list_t rt_soft_timer_list [ RT_TIMER_SKIP_LIST_LEVEL ] ;
50
50
static struct rt_thread timer_thread ;
51
51
ALIGN (RT_ALIGN_SIZE )
52
52
static rt_uint8_t timer_thread_stack [RT_TIMER_THREAD_STACK_SIZE ];
@@ -83,6 +83,8 @@ static void _rt_timer_init(rt_timer_t timer,
83
83
rt_tick_t time ,
84
84
rt_uint8_t flag )
85
85
{
86
+ int i ;
87
+
86
88
/* set flag */
87
89
timer -> parent .flag = flag ;
88
90
@@ -96,21 +98,64 @@ static void _rt_timer_init(rt_timer_t timer,
96
98
timer -> init_tick = time ;
97
99
98
100
/* initialize timer list */
99
- rt_list_init (& (timer -> list ));
101
+ for (i = 0 ; i < RT_TIMER_SKIP_LIST_LEVEL ; i ++ )
102
+ {
103
+ rt_list_init (& (timer -> row [i ]));
104
+ }
100
105
}
101
106
102
- static rt_tick_t rt_timer_list_next_timeout (rt_list_t * timer_list )
107
+ /* the fist timer always in the last row */
108
+ static rt_tick_t rt_timer_list_next_timeout (rt_list_t timer_list [])
103
109
{
104
110
struct rt_timer * timer ;
105
111
106
- if (rt_list_isempty (timer_list ))
112
+ if (rt_list_isempty (& timer_list [ RT_TIMER_SKIP_LIST_LEVEL - 1 ] ))
107
113
return RT_TICK_MAX ;
108
114
109
- timer = rt_list_entry (timer_list -> next , struct rt_timer , list );
115
+ timer = rt_list_entry (timer_list [RT_TIMER_SKIP_LIST_LEVEL - 1 ].next ,
116
+ struct rt_timer , row [RT_TIMER_SKIP_LIST_LEVEL - 1 ]);
110
117
111
118
return timer -> timeout_tick ;
112
119
}
113
120
121
+ rt_inline void _rt_timer_remove (rt_timer_t timer )
122
+ {
123
+ int i ;
124
+
125
+ for (i = 0 ; i < RT_TIMER_SKIP_LIST_LEVEL ; i ++ )
126
+ {
127
+ rt_list_remove (& timer -> row [i ]);
128
+ }
129
+ }
130
+
131
+ static int rt_timer_count_height (struct rt_timer * timer )
132
+ {
133
+ int i , cnt = 0 ;
134
+
135
+ for (i = 0 ; i < RT_TIMER_SKIP_LIST_LEVEL ; i ++ )
136
+ {
137
+ if (!rt_list_isempty (& timer -> row [i ]))
138
+ cnt ++ ;
139
+ }
140
+ return cnt ;
141
+ }
142
+
143
+ static void rt_timer_dump (rt_list_t timer_heads [])
144
+ {
145
+ rt_list_t * list ;
146
+
147
+ for (list = timer_heads [RT_TIMER_SKIP_LIST_LEVEL - 1 ].next ;
148
+ list != & timer_heads [RT_TIMER_SKIP_LIST_LEVEL - 1 ];
149
+ list = list -> next )
150
+ {
151
+ struct rt_timer * timer = rt_list_entry (list ,
152
+ struct rt_timer ,
153
+ row [RT_TIMER_SKIP_LIST_LEVEL - 1 ]);
154
+ rt_kprintf ("%d" , rt_timer_count_height (timer ));
155
+ }
156
+ rt_kprintf ("\n" );
157
+ }
158
+
114
159
/**
115
160
* @addtogroup Clock
116
161
*/
@@ -162,8 +207,7 @@ rt_err_t rt_timer_detach(rt_timer_t timer)
162
207
/* disable interrupt */
163
208
level = rt_hw_interrupt_disable ();
164
209
165
- /* remove it from timer list */
166
- rt_list_remove (& (timer -> list ));
210
+ _rt_timer_remove (timer );
167
211
168
212
/* enable interrupt */
169
213
rt_hw_interrupt_enable (level );
@@ -224,8 +268,7 @@ rt_err_t rt_timer_delete(rt_timer_t timer)
224
268
/* disable interrupt */
225
269
level = rt_hw_interrupt_disable ();
226
270
227
- /* remove it from timer list */
228
- rt_list_remove (& (timer -> list ));
271
+ _rt_timer_remove (timer );
229
272
230
273
/* enable interrupt */
231
274
rt_hw_interrupt_enable (level );
@@ -246,9 +289,14 @@ RTM_EXPORT(rt_timer_delete);
246
289
*/
247
290
rt_err_t rt_timer_start (rt_timer_t timer )
248
291
{
292
+ int row_lvl ;
249
293
struct rt_timer * t ;
294
+ rt_list_t * timer_list ;
250
295
register rt_base_t level ;
251
- rt_list_t * n , * timer_list ;
296
+ rt_list_t * row_head [RT_TIMER_SKIP_LIST_LEVEL ];
297
+ rt_list_t * row_head_li ;
298
+ static unsigned int random_nr ;
299
+ unsigned int tst_nr ;
252
300
253
301
/* timer check */
254
302
RT_ASSERT (timer != RT_NULL );
@@ -271,39 +319,62 @@ rt_err_t rt_timer_start(rt_timer_t timer)
271
319
if (timer -> parent .flag & RT_TIMER_FLAG_SOFT_TIMER )
272
320
{
273
321
/* insert timer to soft timer list */
274
- timer_list = & rt_soft_timer_list ;
322
+ timer_list = rt_soft_timer_list ;
275
323
}
276
324
else
277
325
#endif
278
326
{
279
327
/* insert timer to system timer list */
280
- timer_list = & rt_timer_list ;
328
+ timer_list = rt_timer_list ;
281
329
}
282
330
283
- for (n = timer_list -> next ; n != timer_list ; n = n -> next )
331
+ row_head_li = timer_list ;
332
+ for (row_lvl = 0 ; row_lvl < RT_TIMER_SKIP_LIST_LEVEL ; row_lvl ++ )
284
333
{
285
- t = rt_list_entry (n , struct rt_timer , list );
286
-
287
- /*
288
- * It supposes that the new tick shall less than the half duration of
289
- * tick max. And if we have two timers that timeout at the same time,
290
- * it's prefered that the timer inserted early get called early.
291
- */
292
- if ((t -> timeout_tick - timer -> timeout_tick ) == 0 )
293
- {
294
- rt_list_insert_after (n , & (timer -> list ));
295
- break ;
296
- }
297
- else if ((t -> timeout_tick - timer -> timeout_tick ) < RT_TICK_MAX / 2 )
334
+ for (row_head [row_lvl ] = row_head_li [row_lvl ].next ;
335
+ row_head [row_lvl ] != timer_list [row_lvl ].prev ;
336
+ row_head [row_lvl ] = row_head [row_lvl ]-> next )
298
337
{
299
- rt_list_insert_before (n , & (timer -> list ));
300
- break ;
338
+ rt_list_t * p = row_head [row_lvl ]-> next ;
339
+ /* fix up the entry pointer */
340
+ t = rt_list_entry (p , struct rt_timer , row [row_lvl ]);
341
+
342
+ /* If we have two timers that timeout at the same time, it's
343
+ * preferred that the timer inserted early get called early.
344
+ * So insert the new timer to the end the the some-timeout timer
345
+ * list.
346
+ */
347
+ if ((t -> timeout_tick - timer -> timeout_tick ) == 0 )
348
+ {
349
+ continue ;
350
+ }
351
+ else if ((t -> timeout_tick - timer -> timeout_tick ) < RT_TICK_MAX / 2 )
352
+ {
353
+ row_head_li = row_head [row_lvl ]- row_lvl ;
354
+ break ;
355
+ }
301
356
}
302
357
}
303
- /* no found suitable position in timer list */
304
- if (n == timer_list )
358
+
359
+ /* Interestingly, this super simple timer insert counter works very very
360
+ * well on distributing the list height uniformly. By means of "very very
361
+ * well", I mean it beats the randomness of timer->timeout_tick very easily
362
+ * (actually, the timeout_tick is not random and easy to be attacked). */
363
+ random_nr ++ ;
364
+ tst_nr = random_nr ;
365
+
366
+ rt_list_insert_after (row_head [RT_TIMER_SKIP_LIST_LEVEL - 1 ],
367
+ & (timer -> row [RT_TIMER_SKIP_LIST_LEVEL - 1 ]));
368
+ for (row_lvl = 2 ; row_lvl <= RT_TIMER_SKIP_LIST_LEVEL ; row_lvl ++ )
305
369
{
306
- rt_list_insert_before (n , & (timer -> list ));
370
+ if (!(tst_nr & RT_TIMER_SKIP_LIST_MASK ))
371
+ rt_list_insert_after (row_head [RT_TIMER_SKIP_LIST_LEVEL - row_lvl ],
372
+ & (timer -> row [RT_TIMER_SKIP_LIST_LEVEL - row_lvl ]));
373
+ else
374
+ break ;
375
+ /* Shift over the bits we have tested. Works well with 1 bit and 2
376
+ * bits. */
377
+ tst_nr >>= (RT_TIMER_SKIP_LIST_MASK + 1 )>>1 ;
307
378
}
308
379
309
380
timer -> parent .flag |= RT_TIMER_FLAG_ACTIVATED ;
@@ -349,8 +420,7 @@ rt_err_t rt_timer_stop(rt_timer_t timer)
349
420
/* disable interrupt */
350
421
level = rt_hw_interrupt_disable ();
351
422
352
- /* remove it from timer list */
353
- rt_list_remove (& (timer -> list ));
423
+ _rt_timer_remove (timer );
354
424
355
425
/* enable interrupt */
356
426
rt_hw_interrupt_enable (level );
@@ -410,6 +480,7 @@ void rt_timer_check(void)
410
480
struct rt_timer * t ;
411
481
rt_tick_t current_tick ;
412
482
register rt_base_t level ;
483
+ /*int dumped = 0;*/
413
484
414
485
RT_DEBUG_LOG (RT_DEBUG_TIMER , ("timer check enter\n" ));
415
486
@@ -418,20 +489,30 @@ void rt_timer_check(void)
418
489
/* disable interrupt */
419
490
level = rt_hw_interrupt_disable ();
420
491
421
- while (!rt_list_isempty (& rt_timer_list ))
492
+ while (!rt_list_isempty (& rt_timer_list [ RT_TIMER_SKIP_LIST_LEVEL - 1 ] ))
422
493
{
423
- t = rt_list_entry (rt_timer_list .next , struct rt_timer , list );
494
+ t = rt_list_entry (rt_timer_list [RT_TIMER_SKIP_LIST_LEVEL - 1 ].next ,
495
+ struct rt_timer , row [RT_TIMER_SKIP_LIST_LEVEL - 1 ]);
424
496
425
497
/*
426
498
* It supposes that the new tick shall less than the half duration of
427
499
* tick max.
428
500
*/
429
501
if ((current_tick - t -> timeout_tick ) < RT_TICK_MAX /2 )
430
502
{
503
+ /*
504
+ *if (!dumped)
505
+ *{
506
+ * dumped = 1;
507
+ * [>rt_kprintf("%s:\n", __FUNCTION__);<]
508
+ * rt_timer_dump(rt_timer_list);
509
+ *}
510
+ */
511
+
431
512
RT_OBJECT_HOOK_CALL (rt_timer_timeout_hook , (t ));
432
513
433
514
/* remove timer from timer list firstly */
434
- rt_list_remove ( & ( t -> list ) );
515
+ _rt_timer_remove ( t );
435
516
436
517
/* call timeout function */
437
518
t -> timeout_func (t -> parameter );
@@ -471,7 +552,7 @@ void rt_timer_check(void)
471
552
*/
472
553
rt_tick_t rt_timer_next_timeout_tick (void )
473
554
{
474
- return rt_timer_list_next_timeout (& rt_timer_list );
555
+ return rt_timer_list_next_timeout (rt_timer_list );
475
556
}
476
557
477
558
#ifdef RT_USING_TIMER_SOFT
@@ -489,9 +570,10 @@ void rt_soft_timer_check(void)
489
570
490
571
current_tick = rt_tick_get ();
491
572
492
- for (n = rt_soft_timer_list .next ; n != & (rt_soft_timer_list );)
573
+ for (n = rt_soft_timer_list [RT_TIMER_SKIP_LIST_LEVEL - 1 ].next ;
574
+ n != & (rt_soft_timer_list [RT_TIMER_SKIP_LIST_LEVEL - 1 ]);)
493
575
{
494
- t = rt_list_entry (n , struct rt_timer , list );
576
+ t = rt_list_entry (n , struct rt_timer , row [ RT_TIMER_SKIP_LIST_LEVEL - 1 ] );
495
577
496
578
/*
497
579
* It supposes that the new tick shall less than the half duration of
@@ -505,7 +587,7 @@ void rt_soft_timer_check(void)
505
587
n = n -> next ;
506
588
507
589
/* remove timer from timer list firstly */
508
- rt_list_remove ( & ( t -> list ) );
590
+ _rt_timer_remove ( timer );
509
591
510
592
/* call timeout function */
511
593
t -> timeout_func (t -> parameter );
@@ -542,7 +624,7 @@ static void rt_thread_timer_entry(void *parameter)
542
624
while (1 )
543
625
{
544
626
/* get the next timeout tick */
545
- next_timeout = rt_timer_list_next_timeout (& rt_soft_timer_list );
627
+ next_timeout = rt_timer_list_next_timeout (rt_soft_timer_list );
546
628
if (next_timeout == RT_TICK_MAX )
547
629
{
548
630
/* no software timer exist, suspend self. */
@@ -584,6 +666,12 @@ static void rt_thread_timer_entry(void *parameter)
584
666
*/
585
667
void rt_system_timer_init (void )
586
668
{
669
+ int i ;
670
+
671
+ for (i = 0 ; i < sizeof (rt_timer_list )/sizeof (rt_timer_list [0 ]); i ++ )
672
+ {
673
+ rt_list_init (rt_timer_list + i );
674
+ }
587
675
}
588
676
589
677
/**
@@ -594,7 +682,14 @@ void rt_system_timer_init(void)
594
682
void rt_system_timer_thread_init (void )
595
683
{
596
684
#ifdef RT_USING_TIMER_SOFT
597
- rt_list_init (& rt_soft_timer_list );
685
+ int i ;
686
+
687
+ for (i = 0 ;
688
+ i < sizeof (rt_soft_timer_list )/sizeof (rt_soft_timer_list [0 ]);
689
+ i ++ )
690
+ {
691
+ rt_list_init (rt_soft_timer_list + i );
692
+ }
598
693
599
694
/* start software timer thread */
600
695
rt_thread_init (& timer_thread ,
0 commit comments