@@ -188,29 +188,17 @@ timer_enqueue_bucket(timer_root_s *root, timer_s *timer, time_t sec, long nsec)
188188static void
189189timer_dequeue_bucket (timer_s * timer )
190190{
191- timer_root_s * timer_root ;
192191 timer_bucket_s * timer_bucket ;
193192
194193 timer_bucket = timer -> timer_bucket ;
195- timer_root = timer_bucket -> timer_root ;
196194
197195 CIRCLEQ_REMOVE (& timer_bucket -> timer_qhead , timer , timer_qnode );
198196 timer_bucket -> timers -- ;
199197 timer -> timer_bucket = NULL ;
200198
201- /* If the last timer of a bucket is gone,
202- * remove the bucket as well. */
203- if (!timer_bucket -> timers ) {
204- CIRCLEQ_REMOVE (& timer_root -> timer_bucket_qhead , timer_bucket , timer_bucket_qnode );
205-
206- #ifdef BNGBLASTER_TIMER_LOGGING
207- LOG (TIMER_DETAIL , " Delete timer bucket %lu.%06lus\n" ,
208- timer_bucket -> sec , timer_bucket -> nsec /1000 );
209- #endif
210-
211- free (timer_bucket );
212- timer_root -> buckets -- ;
213- }
199+ /*
200+ * Defer deleting empty buckets to timer_process_changes().
201+ */
214202}
215203
216204static void
@@ -357,11 +345,14 @@ static void
357345timer_process_changes (timer_root_s * root )
358346{
359347 timer_s * timer ;
360- timer_bucket_s * timer_bucket ;
348+ timer_bucket_s * timer_bucket , * timer_bucket_next ;
361349
362350 struct timespec now ;
363351 clock_gettime (CLOCK_MONOTONIC , & now );
364352
353+ /*
354+ * First work the chnaged timer list.
355+ */
365356 while (!CIRCLEQ_EMPTY (& root -> timer_change_qhead )) {
366357 timer = CIRCLEQ_FIRST (& root -> timer_change_qhead );
367358 timer_bucket = timer -> timer_bucket ;
@@ -388,6 +379,27 @@ timer_process_changes(timer_root_s *root)
388379 continue ;
389380 }
390381 }
382+
383+ /*
384+ * Some buckets may be empty by now.
385+ * Trash them here where it is safe.
386+ */
387+ CIRCLEQ_FOREACH_SAFE (timer_bucket , & root -> timer_bucket_qhead ,
388+ timer_bucket_qnode , timer_bucket_next ) {
389+
390+ /* If the bucket is empty, remove it. */
391+ if (!timer_bucket -> timers ) {
392+ CIRCLEQ_REMOVE (& root -> timer_bucket_qhead , timer_bucket , timer_bucket_qnode );
393+
394+ #ifdef BNGBLASTER_TIMER_LOGGING
395+ LOG (TIMER_DETAIL , " Delete timer bucket %lu.%06lus\n" ,
396+ timer_bucket -> sec , timer_bucket -> nsec /1000 );
397+ #endif
398+
399+ free (timer_bucket );
400+ root -> buckets -- ;
401+ }
402+ }
391403}
392404
393405/**
@@ -629,4 +641,4 @@ timer_flush_root(timer_root_s *timer_root)
629641 timer_root -> gc -- ;
630642 free (timer );
631643 }
632- }
644+ }
0 commit comments