diff options
Diffstat (limited to 'usr.sbin/bind/lib/isc/timer.c')
| -rw-r--r-- | usr.sbin/bind/lib/isc/timer.c | 469 |
1 files changed, 366 insertions, 103 deletions
diff --git a/usr.sbin/bind/lib/isc/timer.c b/usr.sbin/bind/lib/isc/timer.c index 34235cc1b01..b0ef62898e2 100644 --- a/usr.sbin/bind/lib/isc/timer.c +++ b/usr.sbin/bind/lib/isc/timer.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009, 2011-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,28 +15,42 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: timer.c,v 1.73.18.7.10.3 2008/07/29 18:35:53 jinmei Exp $ */ +/* $Id: timer.c,v 1.3 2019/12/16 16:16:26 deraadt Exp $ */ /*! \file */ #include <config.h> +#include <isc/app.h> #include <isc/condition.h> #include <isc/heap.h> #include <isc/log.h> #include <isc/magic.h> #include <isc/mem.h> #include <isc/msgs.h> +#include <isc/once.h> #include <isc/platform.h> +#include <isc/print.h> #include <isc/task.h> #include <isc/thread.h> #include <isc/time.h> #include <isc/timer.h> #include <isc/util.h> -#ifndef ISC_PLATFORM_USETHREADS +#ifdef OPENSSL_LEAKS +#include <openssl/err.h> +#endif + +/* See task.c about the following definition: */ +#ifdef ISC_PLATFORM_USETHREADS +#define USE_TIMER_THREAD +#else +#define USE_SHARED_MANAGER +#endif /* ISC_PLATFORM_USETHREADS */ + +#ifndef USE_TIMER_THREAD #include "timer_p.h" -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ #ifdef ISC_TIMER_TRACE #define XTRACE(s) fprintf(stderr, "%s\n", (s)) @@ -58,10 +72,13 @@ #define TIMER_MAGIC ISC_MAGIC('T', 'I', 'M', 'R') #define VALID_TIMER(t) ISC_MAGIC_VALID(t, TIMER_MAGIC) -struct isc_timer { +typedef struct isc__timer isc__timer_t; +typedef struct isc__timermgr isc__timermgr_t; + +struct isc__timer { /*! Not locked. */ - unsigned int magic; - isc_timermgr_t * manager; + isc_timer_t common; + isc__timermgr_t * manager; isc_mutex_t lock; /*! Locked by timer lock. */ unsigned int references; @@ -75,45 +92,104 @@ struct isc_timer { void * arg; unsigned int index; isc_time_t due; - LINK(isc_timer_t) link; + LINK(isc__timer_t) link; }; #define TIMER_MANAGER_MAGIC ISC_MAGIC('T', 'I', 'M', 'M') #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TIMER_MANAGER_MAGIC) -struct isc_timermgr { +struct isc__timermgr { /* Not locked. */ - unsigned int magic; + isc_timermgr_t common; isc_mem_t * mctx; isc_mutex_t lock; /* Locked by manager lock. */ isc_boolean_t done; - LIST(isc_timer_t) timers; + LIST(isc__timer_t) timers; unsigned int nscheduled; isc_time_t due; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD isc_condition_t wakeup; isc_thread_t thread; -#else /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ +#ifdef USE_SHARED_MANAGER unsigned int refs; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ isc_heap_t * heap; }; -#ifndef ISC_PLATFORM_USETHREADS +/*% + * The following are intended for internal use (indicated by "isc__" + * prefix) but are not declared as static, allowing direct access from + * unit tests etc. + */ + +isc_result_t +isc__timer_create(isc_timermgr_t *manager, isc_timertype_t type, + const isc_time_t *expires, const isc_interval_t *interval, + isc_task_t *task, isc_taskaction_t action, void *arg, + isc_timer_t **timerp); +isc_result_t +isc__timer_reset(isc_timer_t *timer, isc_timertype_t type, + const isc_time_t *expires, const isc_interval_t *interval, + isc_boolean_t purge); +isc_timertype_t +isc_timer_gettype(isc_timer_t *timer); +isc_result_t +isc__timer_touch(isc_timer_t *timer); +void +isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp); +void +isc__timer_detach(isc_timer_t **timerp); +isc_result_t +isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); +void +isc_timermgr_poke(isc_timermgr_t *manager0); +void +isc__timermgr_destroy(isc_timermgr_t **managerp); + +static struct isc__timermethods { + isc_timermethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ + void *gettype; +} timermethods = { + { + isc__timer_attach, + isc__timer_detach, + isc__timer_reset, + isc__timer_touch + }, + (void *)isc_timer_gettype +}; + +static struct isc__timermgrmethods { + isc_timermgrmethods_t methods; + void *poke; /* see above */ +} timermgrmethods = { + { + isc__timermgr_destroy, + isc__timer_create + }, + (void *)isc_timermgr_poke +}; + +#ifdef USE_SHARED_MANAGER /*! - * If threads are not in use, there can be only one. + * If the manager is supposed to be shared, there can be only one. */ -static isc_timermgr_t *timermgr = NULL; -#endif /* ISC_PLATFORM_USETHREADS */ +static isc__timermgr_t *timermgr = NULL; +#endif /* USE_SHARED_MANAGER */ static inline isc_result_t -schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { +schedule(isc__timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { isc_result_t result; - isc_timermgr_t *manager; + isc__timermgr_t *manager; isc_time_t due; int cmp; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD isc_boolean_t timedwait; #endif @@ -123,13 +199,13 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { REQUIRE(timer->type != isc_timertype_inactive); -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_TIMER_THREAD UNUSED(signal_ok); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ manager = timer->manager; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD /*! * If the manager was timed wait, we may need to signal the * manager to force a wakeup. @@ -199,7 +275,7 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { * the current "next" timer. We do this either by waking up the * run thread, or explicitly setting the value in the manager. */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD /* * This is a temporary (probably) hack to fix a bug on tru64 5.1 @@ -225,26 +301,28 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { "*** POKED TIMER ***"); } } - + if (timer->index == 1 && signal_ok) { XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SIGNALSCHED, "signal (schedule)")); SIGNAL(&manager->wakeup); } -#else /* ISC_PLATFORM_USETHREADS */ +#else /* USE_TIMER_THREAD */ if (timer->index == 1 && isc_time_compare(&timer->due, &manager->due) < 0) manager->due = timer->due; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ return (ISC_R_SUCCESS); } static inline void -deschedule(isc_timer_t *timer) { +deschedule(isc__timer_t *timer) { +#ifdef USE_TIMER_THREAD isc_boolean_t need_wakeup = ISC_FALSE; - isc_timermgr_t *manager; +#endif + isc__timermgr_t *manager; /* * The caller must ensure locking. @@ -252,26 +330,28 @@ deschedule(isc_timer_t *timer) { manager = timer->manager; if (timer->index > 0) { +#ifdef USE_TIMER_THREAD if (timer->index == 1) need_wakeup = ISC_TRUE; +#endif isc_heap_delete(manager->heap, timer->index); timer->index = 0; INSIST(manager->nscheduled > 0); manager->nscheduled--; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD if (need_wakeup) { XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SIGNALDESCHED, "signal (deschedule)")); SIGNAL(&manager->wakeup); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ } } static void -destroy(isc_timer_t *timer) { - isc_timermgr_t *manager = timer->manager; +destroy(isc__timer_t *timer) { + isc__timermgr_t *manager = timer->manager; /* * The caller must ensure it is safe to destroy the timer. @@ -291,17 +371,19 @@ destroy(isc_timer_t *timer) { isc_task_detach(&timer->task); DESTROYLOCK(&timer->lock); - timer->magic = 0; + timer->common.impmagic = 0; + timer->common.magic = 0; isc_mem_put(manager->mctx, timer, sizeof(*timer)); } isc_result_t -isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, - isc_time_t *expires, isc_interval_t *interval, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_timer_t **timerp) +isc__timer_create(isc_timermgr_t *manager0, isc_timertype_t type, + const isc_time_t *expires, const isc_interval_t *interval, + isc_task_t *task, isc_taskaction_t action, void *arg, + isc_timer_t **timerp) { - isc_timer_t *timer; + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + isc__timer_t *timer; isc_result_t result; isc_time_t now; @@ -382,7 +464,9 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, return (result); } ISC_LINK_INIT(timer, link); - timer->magic = TIMER_MAGIC; + timer->common.impmagic = TIMER_MAGIC; + timer->common.magic = ISCAPI_TIMER_MAGIC; + timer->common.methods = (isc_timermethods_t *)&timermethods; LOCK(&manager->lock); @@ -401,25 +485,27 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, UNLOCK(&manager->lock); if (result != ISC_R_SUCCESS) { - timer->magic = 0; + timer->common.impmagic = 0; + timer->common.magic = 0; DESTROYLOCK(&timer->lock); isc_task_detach(&timer->task); isc_mem_put(manager->mctx, timer, sizeof(*timer)); return (result); } - *timerp = timer; + *timerp = (isc_timer_t *)timer; return (ISC_R_SUCCESS); } isc_result_t -isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, - isc_time_t *expires, isc_interval_t *interval, - isc_boolean_t purge) +isc__timer_reset(isc_timer_t *timer0, isc_timertype_t type, + const isc_time_t *expires, const isc_interval_t *interval, + isc_boolean_t purge) { + isc__timer_t *timer = (isc__timer_t *)timer0; isc_time_t now; - isc_timermgr_t *manager; + isc__timermgr_t *manager; isc_result_t result; /* @@ -431,6 +517,7 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, REQUIRE(VALID_TIMER(timer)); manager = timer->manager; REQUIRE(VALID_MANAGER(manager)); + if (expires == NULL) expires = isc_time_epoch; if (interval == NULL) @@ -454,8 +541,6 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, isc_time_settoepoch(&now); } - manager = timer->manager; - LOCK(&manager->lock); LOCK(&timer->lock); @@ -490,7 +575,8 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, } isc_timertype_t -isc_timer_gettype(isc_timer_t *timer) { +isc_timer_gettype(isc_timer_t *timer0) { + isc__timer_t *timer = (isc__timer_t *)timer0; isc_timertype_t t; REQUIRE(VALID_TIMER(timer)); @@ -503,7 +589,8 @@ isc_timer_gettype(isc_timer_t *timer) { } isc_result_t -isc_timer_touch(isc_timer_t *timer) { +isc__timer_touch(isc_timer_t *timer0) { + isc__timer_t *timer = (isc__timer_t *)timer0; isc_result_t result; isc_time_t now; @@ -533,7 +620,9 @@ isc_timer_touch(isc_timer_t *timer) { } void -isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) { +isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp) { + isc__timer_t *timer = (isc__timer_t *)timer0; + /* * Attach *timerp to timer. */ @@ -545,12 +634,12 @@ isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) { timer->references++; UNLOCK(&timer->lock); - *timerp = timer; + *timerp = (isc_timer_t *)timer; } void -isc_timer_detach(isc_timer_t **timerp) { - isc_timer_t *timer; +isc__timer_detach(isc_timer_t **timerp) { + isc__timer_t *timer; isc_boolean_t free_timer = ISC_FALSE; /* @@ -558,7 +647,7 @@ isc_timer_detach(isc_timer_t **timerp) { */ REQUIRE(timerp != NULL); - timer = *timerp; + timer = (isc__timer_t *)*timerp; REQUIRE(VALID_TIMER(timer)); LOCK(&timer->lock); @@ -575,11 +664,11 @@ isc_timer_detach(isc_timer_t **timerp) { } static void -dispatch(isc_timermgr_t *manager, isc_time_t *now) { +dispatch(isc__timermgr_t *manager, isc_time_t *now) { isc_boolean_t done = ISC_FALSE, post_event, need_schedule; isc_timerevent_t *event; isc_eventtype_t type = 0; - isc_timer_t *timer; + isc__timer_t *timer; isc_result_t result; isc_boolean_t idle; @@ -589,7 +678,7 @@ dispatch(isc_timermgr_t *manager, isc_time_t *now) { while (manager->nscheduled > 0 && !done) { timer = isc_heap_element(manager->heap, 1); - INSIST(timer->type != isc_timertype_inactive); + INSIST(timer != NULL && timer->type != isc_timertype_inactive); if (isc_time_compare(now, &timer->due) >= 0) { if (timer->type == isc_timertype_ticker) { type = ISC_TIMEREVENT_TICK; @@ -662,7 +751,7 @@ dispatch(isc_timermgr_t *manager, isc_time_t *now) { isc_task_send(timer->task, ISC_EVENT_PTR(&event)); } else - UNEXPECTED_ERROR(__FILE__, __LINE__, + UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_EVENTNOTALLOC, @@ -678,11 +767,12 @@ dispatch(isc_timermgr_t *manager, isc_time_t *now) { result = schedule(timer, now, ISC_FALSE); if (result != ISC_R_SUCCESS) UNEXPECTED_ERROR(__FILE__, __LINE__, + "%s: %u", isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SCHEDFAIL, - "couldn't " - "schedule timer: %u"), + "couldn't schedule " + "timer"), result); } } else { @@ -692,13 +782,13 @@ dispatch(isc_timermgr_t *manager, isc_time_t *now) { } } -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD static isc_threadresult_t #ifdef _WIN32 /* XXXDCL */ WINAPI #endif run(void *uap) { - isc_timermgr_t *manager = uap; + isc__timermgr_t *manager = uap; isc_time_t now; isc_result_t result; @@ -731,13 +821,17 @@ run(void *uap) { } UNLOCK(&manager->lock); +#ifdef OPENSSL_LEAKS + ERR_remove_state(0); +#endif + return ((isc_threadresult_t)0); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ static isc_boolean_t sooner(void *v1, void *v2) { - isc_timer_t *t1, *t2; + isc__timer_t *t1, *t2; t1 = v1; t2 = v2; @@ -751,7 +845,7 @@ sooner(void *v1, void *v2) { static void set_index(void *what, unsigned int index) { - isc_timer_t *timer; + isc__timer_t *timer; timer = what; REQUIRE(VALID_TIMER(timer)); @@ -760,8 +854,8 @@ set_index(void *what, unsigned int index) { } isc_result_t -isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { - isc_timermgr_t *manager; +isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { + isc__timermgr_t *manager; isc_result_t result; /* @@ -770,19 +864,21 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { REQUIRE(managerp != NULL && *managerp == NULL); -#ifndef ISC_PLATFORM_USETHREADS +#ifdef USE_SHARED_MANAGER if (timermgr != NULL) { timermgr->refs++; - *managerp = timermgr; + *managerp = (isc_timermgr_t *)timermgr; return (ISC_R_SUCCESS); } -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ manager = isc_mem_get(mctx, sizeof(*manager)); if (manager == NULL) return (ISC_R_NOMEMORY); - manager->magic = TIMER_MANAGER_MAGIC; + manager->common.impmagic = TIMER_MANAGER_MAGIC; + manager->common.magic = ISCAPI_TIMERMGR_MAGIC; + manager->common.methods = (isc_timermgrmethods_t *)&timermgrmethods; manager->mctx = NULL; manager->done = ISC_FALSE; INIT_LIST(manager->timers); @@ -802,7 +898,7 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { return (result); } isc_mem_attach(mctx, &manager->mctx); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD if (isc_condition_init(&manager->wakeup) != ISC_R_SUCCESS) { isc_mem_detach(&manager->mctx); DESTROYLOCK(&manager->lock); @@ -827,30 +923,33 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { ISC_MSG_FAILED, "failed")); return (ISC_R_UNEXPECTED); } -#else /* ISC_PLATFORM_USETHREADS */ +#endif +#ifdef USE_SHARED_MANAGER manager->refs = 1; timermgr = manager; -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_SHARED_MANAGER */ - *managerp = manager; + *managerp = (isc_timermgr_t *)manager; return (ISC_R_SUCCESS); } void -isc_timermgr_poke(isc_timermgr_t *manager) { -#ifdef ISC_PLATFORM_USETHREADS +isc_timermgr_poke(isc_timermgr_t *manager0) { +#ifdef USE_TIMER_THREAD + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + REQUIRE(VALID_MANAGER(manager)); SIGNAL(&manager->wakeup); #else - UNUSED(manager); + UNUSED(manager0); #endif } void -isc_timermgr_destroy(isc_timermgr_t **managerp) { - isc_timermgr_t *manager; +isc__timermgr_destroy(isc_timermgr_t **managerp) { + isc__timermgr_t *manager; isc_mem_t *mctx; /* @@ -858,34 +957,37 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) { */ REQUIRE(managerp != NULL); - manager = *managerp; + manager = (isc__timermgr_t *)*managerp; REQUIRE(VALID_MANAGER(manager)); LOCK(&manager->lock); -#ifndef ISC_PLATFORM_USETHREADS - if (manager->refs > 1) { - manager->refs--; +#ifdef USE_SHARED_MANAGER + manager->refs--; + if (manager->refs > 0) { UNLOCK(&manager->lock); *managerp = NULL; return; } + timermgr = NULL; +#endif /* USE_SHARED_MANAGER */ - isc__timermgr_dispatch(); -#endif /* ISC_PLATFORM_USETHREADS */ +#ifndef USE_TIMER_THREAD + isc__timermgr_dispatch((isc_timermgr_t *)manager); +#endif REQUIRE(EMPTY(manager->timers)); manager->done = ISC_TRUE; -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SIGNALDESTROY, "signal (destroy)")); SIGNAL(&manager->wakeup); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ UNLOCK(&manager->lock); -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD /* * Wait for thread to exit. */ @@ -894,39 +996,200 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) { "isc_thread_join() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ /* * Clean up. */ -#ifdef ISC_PLATFORM_USETHREADS +#ifdef USE_TIMER_THREAD (void)isc_condition_destroy(&manager->wakeup); -#endif /* ISC_PLATFORM_USETHREADS */ +#endif /* USE_TIMER_THREAD */ DESTROYLOCK(&manager->lock); isc_heap_destroy(&manager->heap); - manager->magic = 0; + manager->common.impmagic = 0; + manager->common.magic = 0; mctx = manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); *managerp = NULL; + +#ifdef USE_SHARED_MANAGER + timermgr = NULL; +#endif } -#ifndef ISC_PLATFORM_USETHREADS +#ifndef USE_TIMER_THREAD isc_result_t -isc__timermgr_nextevent(isc_time_t *when) { - if (timermgr == NULL || timermgr->nscheduled == 0) +isc__timermgr_nextevent(isc_timermgr_t *manager0, isc_time_t *when) { + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = timermgr; +#endif + if (manager == NULL || manager->nscheduled == 0) return (ISC_R_NOTFOUND); - *when = timermgr->due; + *when = manager->due; return (ISC_R_SUCCESS); } void -isc__timermgr_dispatch(void) { +isc__timermgr_dispatch(isc_timermgr_t *manager0) { + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; isc_time_t now; - if (timermgr == NULL) + +#ifdef USE_SHARED_MANAGER + if (manager == NULL) + manager = timermgr; +#endif + if (manager == NULL) return; TIME_NOW(&now); - dispatch(timermgr, &now); + dispatch(manager, &now); +} +#endif /* USE_TIMER_THREAD */ + +isc_result_t +isc__timer_register(void) { + return (isc_timer_register(isc__timermgr_create)); +} + +static isc_mutex_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_timermgrcreatefunc_t timermgr_createfunc = NULL; + +static void +initialize(void) { + RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); +} + +isc_result_t +isc_timer_register(isc_timermgrcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); + + LOCK(&createlock); + if (timermgr_createfunc == NULL) + timermgr_createfunc = createfunc; + else + result = ISC_R_EXISTS; + UNLOCK(&createlock); + + return (result); +} + +isc_result_t +isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + isc_timermgr_t **managerp) +{ + isc_result_t result; + + LOCK(&createlock); + + REQUIRE(timermgr_createfunc != NULL); + result = (*timermgr_createfunc)(mctx, managerp); + + UNLOCK(&createlock); + + if (result == ISC_R_SUCCESS) + isc_appctx_settimermgr(actx, *managerp); + + return (result); +} + +isc_result_t +isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { + isc_result_t result; + + if (isc_bind9) + return (isc__timermgr_create(mctx, managerp)); + + LOCK(&createlock); + + REQUIRE(timermgr_createfunc != NULL); + result = (*timermgr_createfunc)(mctx, managerp); + + UNLOCK(&createlock); + + return (result); +} + +void +isc_timermgr_destroy(isc_timermgr_t **managerp) { + REQUIRE(*managerp != NULL && ISCAPI_TIMERMGR_VALID(*managerp)); + + if (isc_bind9) + isc__timermgr_destroy(managerp); + else + (*managerp)->methods->destroy(managerp); + + ENSURE(*managerp == NULL); +} + +isc_result_t +isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type, + const isc_time_t *expires, const isc_interval_t *interval, + isc_task_t *task, isc_taskaction_t action, void *arg, + isc_timer_t **timerp) +{ + REQUIRE(ISCAPI_TIMERMGR_VALID(manager)); + + if (isc_bind9) + return (isc__timer_create(manager, type, expires, interval, + task, action, arg, timerp)); + + return (manager->methods->timercreate(manager, type, expires, + interval, task, action, arg, + timerp)); +} + +void +isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) { + REQUIRE(ISCAPI_TIMER_VALID(timer)); + REQUIRE(timerp != NULL && *timerp == NULL); + + if (isc_bind9) + isc__timer_attach(timer, timerp); + else + timer->methods->attach(timer, timerp); + + ENSURE(*timerp == timer); +} + +void +isc_timer_detach(isc_timer_t **timerp) { + REQUIRE(timerp != NULL && ISCAPI_TIMER_VALID(*timerp)); + + if (isc_bind9) + isc__timer_detach(timerp); + else + (*timerp)->methods->detach(timerp); + + ENSURE(*timerp == NULL); +} + +isc_result_t +isc_timer_reset(isc_timer_t *timer, isc_timertype_t type, + const isc_time_t *expires, const isc_interval_t *interval, + isc_boolean_t purge) +{ + REQUIRE(ISCAPI_TIMER_VALID(timer)); + + if (isc_bind9) + return (isc__timer_reset(timer, type, expires, + interval, purge)); + + return (timer->methods->reset(timer, type, expires, interval, purge)); +} + +isc_result_t +isc_timer_touch(isc_timer_t *timer) { + REQUIRE(ISCAPI_TIMER_VALID(timer)); + + if (isc_bind9) + return (isc__timer_touch(timer)); + + return (timer->methods->touch(timer)); } -#endif /* ISC_PLATFORM_USETHREADS */ |
