diff --git a/code/common/src/timer.c b/code/common/src/timer.c index 90326dc1..a1c7abd1 100644 --- a/code/common/src/timer.c +++ b/code/common/src/timer.c @@ -196,7 +196,9 @@ timer_dequeue_bucket(timer_s *timer) timer_bucket->timers--; timer->timer_bucket = NULL; - /* Defer deleting empty buckets to timer_process_changes(). */ + /* + * Defer deleting empty buckets to timer_walk(). + */ } static void @@ -336,6 +338,23 @@ timer_del(timer_s *timer) } } +/** + * Delete a timer bucket + */ +void +timer_del_bucket(timer_root_s *root, timer_bucket_s *timer_bucket) +{ + CIRCLEQ_REMOVE(&root->timer_bucket_qhead, timer_bucket, timer_bucket_qnode); + +#ifdef BNGBLASTER_TIMER_LOGGING + LOG(TIMER_DETAIL, " Delete timer bucket %lu.%06lus\n", + timer_bucket->sec, timer_bucket->nsec/1000); +#endif + + free(timer_bucket); + root->buckets--; +} + /** * Deferred processing of all timers. */ @@ -475,7 +494,7 @@ void timer_walk(timer_root_s *root) { timer_s *timer; - timer_bucket_s *timer_bucket; + timer_bucket_s *timer_bucket, *timer_bucket_next; struct timespec now, min, sleep, rem; int res; @@ -495,7 +514,8 @@ timer_walk(timer_root_s *root) min.tv_nsec = 0; /* Walk all buckets. */ - CIRCLEQ_FOREACH(timer_bucket, &root->timer_bucket_qhead, timer_bucket_qnode) { + CIRCLEQ_FOREACH_SAFE(timer_bucket, &root->timer_bucket_qhead, + timer_bucket_qnode, timer_bucket_next) { #ifdef BNGBLASTER_TIMER_LOGGING LOG(TIMER_DETAIL, " Checking timer bucket %lu.%06lus\n", @@ -532,6 +552,11 @@ timer_walk(timer_root_s *root) timer_del(timer); } } + + /* If the bucket is empty, remove it. */ + if(!timer_bucket->timers) { + timer_del_bucket(root, timer_bucket); + } } /* Process all changes from the last timer run. */ diff --git a/code/common/src/timer.h b/code/common/src/timer.h index c0012d33..d9b37ed7 100644 --- a/code/common/src/timer.h +++ b/code/common/src/timer.h @@ -23,6 +23,14 @@ (var) = (tvar)) #endif +#ifndef CIRCLEQ_FOREACH_SAFE +#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = CIRCLEQ_FIRST((head)); \ + (var) != (void *)(head) && \ + ((tvar) = CIRCLEQ_NEXT((var), field), 1); \ + (var) = (tvar)) +#endif + /* Top level data structure for timers. */ typedef struct timer_root_ {