diff --git a/lib/isc/include/isc/timer.h b/lib/isc/include/isc/timer.h index b86d74e4aa..1e828d6bc3 100644 --- a/lib/isc/include/isc/timer.h +++ b/lib/isc/include/isc/timer.h @@ -87,10 +87,13 @@ typedef enum { isc_timertype_inactive = 3 /*%< Inactive */ } isc_timertype_t; -typedef struct isc_timerevent { +typedef struct isc_timerevent isc_timerevent_t; + +struct isc_timerevent { struct isc_event common; isc_time_t due; -} isc_timerevent_t; + ISC_LINK(isc_timerevent_t) ev_timerlink; +}; #define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0) #define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1) diff --git a/lib/isc/timer.c b/lib/isc/timer.c index 1b278eff30..7bebc7c7a9 100644 --- a/lib/isc/timer.c +++ b/lib/isc/timer.c @@ -72,6 +72,7 @@ struct isc_timer { void *arg; unsigned int index; isc_time_t due; + ISC_LIST(isc_timerevent_t) active; LINK(isc_timer_t) link; }; @@ -204,18 +205,31 @@ deschedule(isc_timer_t *timer) { } } +static void +timerevent_unlink(isc_timer_t *timer, isc_timerevent_t *event) { + fprintf(stderr, "unlinking %p from %p\n", event, &timer->active); + + REQUIRE(ISC_LINK_LINKED(event, ev_timerlink)); + ISC_LIST_UNLINK(timer->active, event, ev_timerlink); +} + +static void +timer_purge(isc_timer_t *timer) { + isc_timerevent_t *event = NULL; + + while ((event = ISC_LIST_HEAD(timer->active)) != NULL) { + (void)isc_task_purgeevent(timer->task, (isc_event_t *)event); + timerevent_unlink(timer, event); + } +} + static void destroy(isc_timer_t *timer) { isc_timermgr_t *manager = timer->manager; - /* - * The caller must ensure it is safe to destroy the timer. - */ - LOCK(&manager->lock); - (void)isc_task_purgerange(timer->task, timer, ISC_TIMEREVENT_FIRSTEVENT, - ISC_TIMEREVENT_LASTEVENT, NULL); + timer_purge(timer); deschedule(timer); UNLINK(manager->timers, timer, link); @@ -309,6 +323,9 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, timer->index = 0; isc_mutex_init(&timer->lock); ISC_LINK_INIT(timer, link); + + ISC_LIST_INIT(timer->active); + timer->magic = TIMER_MAGIC; LOCK(&manager->lock); @@ -388,9 +405,7 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, LOCK(&timer->lock); if (purge) { - (void)isc_task_purgerange(timer->task, timer, - ISC_TIMEREVENT_FIRSTEVENT, - ISC_TIMEREVENT_LASTEVENT, NULL); + timer_purge(timer); } timer->type = type; timer->expires = *expires;