diff options
| author | 2020-02-07 09:58:52 +0000 | |
|---|---|---|
| committer | 2020-02-07 09:58:52 +0000 | |
| commit | 5185a7002a54c85c252cec8ac1712898b2c4d364 (patch) | |
| tree | 85c674e5d41ec98028ad29a3aac4db558edae254 /usr.bin/dig/lib/isc/timer.c | |
| parent | It appears we have come full-circle, where source code starts to use (diff) | |
| download | wireguard-openbsd-5185a7002a54c85c252cec8ac1712898b2c4d364.tar.xz wireguard-openbsd-5185a7002a54c85c252cec8ac1712898b2c4d364.zip | |
Move dig(1) and needed DNS libraries into it's own source directory in
usr.bin/dig.
From the beginning when we started to remove unneeded nameserver code,
it was our goal to extract dig functionality from the bind sources,
for everyone's benefit as this is easier to reason about.
In total we removed about 2/3 or over 300.000 lines of code.
We kept the lib/ subdirectory layout but moved the content of bin/ to
the top from the old bind source directory.
Previous sources and history can be found in the src/usr.sbin/bind
Attic.
With & OK deraadt
Proposed directory layout sounds good to sthen
Diffstat (limited to 'usr.bin/dig/lib/isc/timer.c')
| -rw-r--r-- | usr.bin/dig/lib/isc/timer.c | 855 |
1 files changed, 855 insertions, 0 deletions
diff --git a/usr.bin/dig/lib/isc/timer.c b/usr.bin/dig/lib/isc/timer.c new file mode 100644 index 00000000000..10d9103c6d0 --- /dev/null +++ b/usr.bin/dig/lib/isc/timer.c @@ -0,0 +1,855 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: timer.c,v 1.1 2020/02/07 09:58:54 florian Exp $ */ + +/*! \file */ + + +#include <stdlib.h> +#include <isc/app.h> +#include <isc/heap.h> +#include <isc/log.h> +#include <isc/magic.h> +#include <isc/msgs.h> +#include <isc/task.h> +#include <isc/time.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include "timer_p.h" + +#ifdef ISC_TIMER_TRACE +#define XTRACE(s) fprintf(stderr, "%s\n", (s)) +#define XTRACEID(s, t) fprintf(stderr, "%s %p\n", (s), (t)) +#define XTRACETIME(s, d) fprintf(stderr, "%s %u.%09u\n", (s), \ + (d).seconds, (d).nanoseconds) +#define XTRACETIME2(s, d, n) fprintf(stderr, "%s %u.%09u %u.%09u\n", (s), \ + (d).seconds, (d).nanoseconds, (n).seconds, (n).nanoseconds) +#define XTRACETIMER(s, t, d) fprintf(stderr, "%s %p %u.%09u\n", (s), (t), \ + (d).seconds, (d).nanoseconds) +#else +#define XTRACE(s) +#define XTRACEID(s, t) +#define XTRACETIME(s, d) +#define XTRACETIME2(s, d, n) +#define XTRACETIMER(s, t, d) +#endif /* ISC_TIMER_TRACE */ + +#define TIMER_MAGIC ISC_MAGIC('T', 'I', 'M', 'R') +#define VALID_TIMER(t) ISC_MAGIC_VALID(t, TIMER_MAGIC) + +typedef struct isc__timer isc__timer_t; +typedef struct isc__timermgr isc__timermgr_t; + +struct isc__timer { + /*! Not locked. */ + isc_timer_t common; + isc__timermgr_t * manager; + /*! Locked by timer lock. */ + unsigned int references; + isc_time_t idle; + /*! Locked by manager lock. */ + isc_timertype_t type; + isc_time_t expires; + interval_t interval; + isc_task_t * task; + isc_taskaction_t action; + void * arg; + unsigned int index; + isc_time_t due; + 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 { + /* Not locked. */ + isc_timermgr_t common; + /* Locked by manager lock. */ + isc_boolean_t done; + LIST(isc__timer_t) timers; + unsigned int nscheduled; + isc_time_t due; + unsigned int refs; + isc_heap_t * heap; +}; + +/*% + * 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 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 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_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 +}; + +/*! + * If the manager is supposed to be shared, there can be only one. + */ +static isc__timermgr_t *timermgr = NULL; + +static inline isc_result_t +schedule(isc__timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { + isc_result_t result; + isc__timermgr_t *manager; + isc_time_t due; + int cmp; + + /*! + * Note: the caller must ensure locking. + */ + + REQUIRE(timer->type != isc_timertype_inactive); + + UNUSED(signal_ok); + + manager = timer->manager; + + /* + * Compute the new due time. + */ + if (timer->type != isc_timertype_once) { + result = isc_time_add(now, &timer->interval, &due); + if (result != ISC_R_SUCCESS) + return (result); + if (timer->type == isc_timertype_limited && + isc_time_compare(&timer->expires, &due) < 0) + due = timer->expires; + } else { + if (isc_time_isepoch(&timer->idle)) + due = timer->expires; + else if (isc_time_isepoch(&timer->expires)) + due = timer->idle; + else if (isc_time_compare(&timer->idle, &timer->expires) < 0) + due = timer->idle; + else + due = timer->expires; + } + + /* + * Schedule the timer. + */ + + if (timer->index > 0) { + /* + * Already scheduled. + */ + cmp = isc_time_compare(&due, &timer->due); + timer->due = due; + switch (cmp) { + case -1: + isc_heap_increased(manager->heap, timer->index); + break; + case 1: + isc_heap_decreased(manager->heap, timer->index); + break; + case 0: + /* Nothing to do. */ + break; + } + } else { + timer->due = due; + result = isc_heap_insert(manager->heap, timer); + if (result != ISC_R_SUCCESS) { + INSIST(result == ISC_R_NOMEMORY); + return (ISC_R_NOMEMORY); + } + manager->nscheduled++; + } + + XTRACETIMER("schedule", timer, due); + + /* + * If this timer is at the head of the queue, we need to ensure + * that we won't miss it if it has a more recent due time than + * the current "next" timer. We do this either by waking up the + * run thread, or explicitly setting the value in the manager. + */ + if (timer->index == 1 && + isc_time_compare(&timer->due, &manager->due) < 0) + manager->due = timer->due; + + return (ISC_R_SUCCESS); +} + +static inline void +deschedule(isc__timer_t *timer) { + isc__timermgr_t *manager; + + /* + * The caller must ensure locking. + */ + + manager = timer->manager; + if (timer->index > 0) { + isc_heap_delete(manager->heap, timer->index); + timer->index = 0; + INSIST(manager->nscheduled > 0); + manager->nscheduled--; + } +} + +static void +destroy(isc__timer_t *timer) { + isc__timermgr_t *manager = timer->manager; + + /* + * The caller must ensure it is safe to destroy the timer. + */ + + (void)isc_task_purgerange(timer->task, + timer, + ISC_TIMEREVENT_FIRSTEVENT, + ISC_TIMEREVENT_LASTEVENT, + NULL); + deschedule(timer); + UNLINK(manager->timers, timer, link); + + isc_task_detach(&timer->task); + timer->common.impmagic = 0; + timer->common.magic = 0; + free(timer); +} + +isc_result_t +isc__timer_create(isc_timermgr_t *manager0, isc_timertype_t type, + const isc_time_t *expires, const interval_t *interval, + isc_task_t *task, isc_taskaction_t action, void *arg, + isc_timer_t **timerp) +{ + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + isc__timer_t *timer; + isc_result_t result; + isc_time_t now; + + /* + * Create a new 'type' timer managed by 'manager'. The timers + * parameters are specified by 'expires' and 'interval'. Events + * will be posted to 'task' and when dispatched 'action' will be + * called with 'arg' as the arg value. The new timer is returned + * in 'timerp'. + */ + + REQUIRE(VALID_MANAGER(manager)); + REQUIRE(task != NULL); + REQUIRE(action != NULL); + if (expires == NULL) + expires = isc_time_epoch; + if (interval == NULL) + interval = interval_zero; + REQUIRE(type == isc_timertype_inactive || + !(isc_time_isepoch(expires) && interval_iszero(interval))); + REQUIRE(timerp != NULL && *timerp == NULL); + REQUIRE(type != isc_timertype_limited || + !(isc_time_isepoch(expires) || interval_iszero(interval))); + + /* + * Get current time. + */ + if (type != isc_timertype_inactive) { + TIME_NOW(&now); + } else { + /* + * We don't have to do this, but it keeps the compiler from + * complaining about "now" possibly being used without being + * set, even though it will never actually happen. + */ + isc_time_settoepoch(&now); + } + + + timer = malloc(sizeof(*timer)); + if (timer == NULL) + return (ISC_R_NOMEMORY); + + timer->manager = manager; + timer->references = 1; + + if (type == isc_timertype_once && !interval_iszero(interval)) { + result = isc_time_add(&now, interval, &timer->idle); + if (result != ISC_R_SUCCESS) { + free(timer); + return (result); + } + } else + isc_time_settoepoch(&timer->idle); + + timer->type = type; + timer->expires = *expires; + timer->interval = *interval; + timer->task = NULL; + isc_task_attach(task, &timer->task); + timer->action = action; + /* + * Removing the const attribute from "arg" is the best of two + * evils here. If the timer->arg member is made const, then + * it affects a great many recipients of the timer event + * which did not pass in an "arg" that was truly const. + * Changing isc_timer_create() to not have "arg" prototyped as const, + * though, can cause compilers warnings for calls that *do* + * have a truly const arg. The caller will have to carefully + * keep track of whether arg started as a true const. + */ + DE_CONST(arg, timer->arg); + timer->index = 0; + ISC_LINK_INIT(timer, link); + timer->common.impmagic = TIMER_MAGIC; + timer->common.magic = ISCAPI_TIMER_MAGIC; + timer->common.methods = (isc_timermethods_t *)&timermethods; + + if (type != isc_timertype_inactive) + result = schedule(timer, &now, ISC_TRUE); + else + result = ISC_R_SUCCESS; + if (result == ISC_R_SUCCESS) + APPEND(manager->timers, timer, link); + + if (result != ISC_R_SUCCESS) { + timer->common.impmagic = 0; + timer->common.magic = 0; + isc_task_detach(&timer->task); + free(timer); + return (result); + } + + *timerp = (isc_timer_t *)timer; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__timer_reset(isc_timer_t *timer0, isc_timertype_t type, + const isc_time_t *expires, const interval_t *interval, + isc_boolean_t purge) +{ + isc__timer_t *timer = (isc__timer_t *)timer0; + isc_time_t now; + isc__timermgr_t *manager; + isc_result_t result; + + /* + * Change the timer's type, expires, and interval values to the given + * values. If 'purge' is ISC_TRUE, any pending events from this timer + * are purged from its task's event queue. + */ + + REQUIRE(VALID_TIMER(timer)); + manager = timer->manager; + REQUIRE(VALID_MANAGER(manager)); + + if (expires == NULL) + expires = isc_time_epoch; + if (interval == NULL) + interval = interval_zero; + REQUIRE(type == isc_timertype_inactive || + !(isc_time_isepoch(expires) && interval_iszero(interval))); + REQUIRE(type != isc_timertype_limited || + !(isc_time_isepoch(expires) || interval_iszero(interval))); + + /* + * Get current time. + */ + if (type != isc_timertype_inactive) { + TIME_NOW(&now); + } else { + /* + * We don't have to do this, but it keeps the compiler from + * complaining about "now" possibly being used without being + * set, even though it will never actually happen. + */ + isc_time_settoepoch(&now); + } + + if (purge) + (void)isc_task_purgerange(timer->task, + timer, + ISC_TIMEREVENT_FIRSTEVENT, + ISC_TIMEREVENT_LASTEVENT, + NULL); + timer->type = type; + timer->expires = *expires; + timer->interval = *interval; + if (type == isc_timertype_once && !interval_iszero(interval)) { + result = isc_time_add(&now, interval, &timer->idle); + } else { + isc_time_settoepoch(&timer->idle); + result = ISC_R_SUCCESS; + } + + if (result == ISC_R_SUCCESS) { + if (type == isc_timertype_inactive) { + deschedule(timer); + result = ISC_R_SUCCESS; + } else + result = schedule(timer, &now, ISC_TRUE); + } + + return (result); +} + +isc_timertype_t +isc_timer_gettype(isc_timer_t *timer0) { + isc__timer_t *timer = (isc__timer_t *)timer0; + isc_timertype_t t; + + REQUIRE(VALID_TIMER(timer)); + + t = timer->type; + + return (t); +} + +isc_result_t +isc__timer_touch(isc_timer_t *timer0) { + isc__timer_t *timer = (isc__timer_t *)timer0; + isc_result_t result; + isc_time_t now; + + /* + * Set the last-touched time of 'timer' to the current time. + */ + + REQUIRE(VALID_TIMER(timer)); + + TIME_NOW(&now); + result = isc_time_add(&now, &timer->interval, &timer->idle); + + return (result); +} + +void +isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp) { + isc__timer_t *timer = (isc__timer_t *)timer0; + + /* + * Attach *timerp to timer. + */ + + REQUIRE(VALID_TIMER(timer)); + REQUIRE(timerp != NULL && *timerp == NULL); + + timer->references++; + + *timerp = (isc_timer_t *)timer; +} + +void +isc__timer_detach(isc_timer_t **timerp) { + isc__timer_t *timer; + isc_boolean_t free_timer = ISC_FALSE; + + /* + * Detach *timerp from its timer. + */ + + REQUIRE(timerp != NULL); + timer = (isc__timer_t *)*timerp; + REQUIRE(VALID_TIMER(timer)); + + REQUIRE(timer->references > 0); + timer->references--; + if (timer->references == 0) + free_timer = ISC_TRUE; + + if (free_timer) + destroy(timer); + + *timerp = NULL; +} + +static void +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_result_t result; + isc_boolean_t idle; + + /*! + * The caller must be holding the manager lock. + */ + + while (manager->nscheduled > 0 && !done) { + timer = isc_heap_element(manager->heap, 1); + 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; + post_event = ISC_TRUE; + need_schedule = ISC_TRUE; + } else if (timer->type == isc_timertype_limited) { + int cmp; + cmp = isc_time_compare(now, &timer->expires); + if (cmp >= 0) { + type = ISC_TIMEREVENT_LIFE; + post_event = ISC_TRUE; + need_schedule = ISC_FALSE; + } else { + type = ISC_TIMEREVENT_TICK; + post_event = ISC_TRUE; + need_schedule = ISC_TRUE; + } + } else if (!isc_time_isepoch(&timer->expires) && + isc_time_compare(now, + &timer->expires) >= 0) { + type = ISC_TIMEREVENT_LIFE; + post_event = ISC_TRUE; + need_schedule = ISC_FALSE; + } else { + idle = ISC_FALSE; + + if (!isc_time_isepoch(&timer->idle) && + isc_time_compare(now, + &timer->idle) >= 0) { + idle = ISC_TRUE; + } + if (idle) { + type = ISC_TIMEREVENT_IDLE; + post_event = ISC_TRUE; + need_schedule = ISC_FALSE; + } else { + /* + * Idle timer has been touched; + * reschedule. + */ + XTRACEID("idle reschedule", timer); + post_event = ISC_FALSE; + need_schedule = ISC_TRUE; + } + } + + if (post_event) { + XTRACEID("posting", timer); + /* + * XXX We could preallocate this event. + */ + event = (isc_timerevent_t *)isc_event_allocate( + timer, + type, + timer->action, + timer->arg, + sizeof(*event)); + + if (event != NULL) { + event->due = timer->due; + isc_task_send(timer->task, + ISC_EVENT_PTR(&event)); + } else + UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", + "couldn't allocate event"); + } + + timer->index = 0; + isc_heap_delete(manager->heap, 1); + manager->nscheduled--; + + if (need_schedule) { + result = schedule(timer, now, ISC_FALSE); + if (result != ISC_R_SUCCESS) + UNEXPECTED_ERROR(__FILE__, __LINE__, + "%s: %u", + "couldn't schedule timer", + result); + } + } else { + manager->due = timer->due; + done = ISC_TRUE; + } + } +} + +static isc_boolean_t +sooner(void *v1, void *v2) { + isc__timer_t *t1, *t2; + + t1 = v1; + t2 = v2; + REQUIRE(VALID_TIMER(t1)); + REQUIRE(VALID_TIMER(t2)); + + if (isc_time_compare(&t1->due, &t2->due) < 0) + return (ISC_TRUE); + return (ISC_FALSE); +} + +static void +set_index(void *what, unsigned int index) { + isc__timer_t *timer; + + timer = what; + REQUIRE(VALID_TIMER(timer)); + + timer->index = index; +} + +isc_result_t +isc__timermgr_create(isc_timermgr_t **managerp) { + isc__timermgr_t *manager; + isc_result_t result; + + /* + * Create a timer manager. + */ + + REQUIRE(managerp != NULL && *managerp == NULL); + + if (timermgr != NULL) { + timermgr->refs++; + *managerp = (isc_timermgr_t *)timermgr; + return (ISC_R_SUCCESS); + } + + manager = malloc(sizeof(*manager)); + if (manager == NULL) + return (ISC_R_NOMEMORY); + + manager->common.impmagic = TIMER_MANAGER_MAGIC; + manager->common.magic = ISCAPI_TIMERMGR_MAGIC; + manager->common.methods = (isc_timermgrmethods_t *)&timermgrmethods; + manager->done = ISC_FALSE; + INIT_LIST(manager->timers); + manager->nscheduled = 0; + isc_time_settoepoch(&manager->due); + manager->heap = NULL; + result = isc_heap_create(sooner, set_index, 0, &manager->heap); + if (result != ISC_R_SUCCESS) { + INSIST(result == ISC_R_NOMEMORY); + free(manager); + return (ISC_R_NOMEMORY); + } + manager->refs = 1; + timermgr = manager; + + *managerp = (isc_timermgr_t *)manager; + + return (ISC_R_SUCCESS); +} + +void +isc_timermgr_poke(isc_timermgr_t *manager0) { + UNUSED(manager0); +} + +void +isc__timermgr_destroy(isc_timermgr_t **managerp) { + isc__timermgr_t *manager; + + /* + * Destroy a timer manager. + */ + + REQUIRE(managerp != NULL); + manager = (isc__timermgr_t *)*managerp; + REQUIRE(VALID_MANAGER(manager)); + + manager->refs--; + if (manager->refs > 0) { + *managerp = NULL; + return; + } + timermgr = NULL; + + isc__timermgr_dispatch((isc_timermgr_t *)manager); + + REQUIRE(EMPTY(manager->timers)); + manager->done = ISC_TRUE; + + /* + * Clean up. + */ + isc_heap_destroy(&manager->heap); + manager->common.impmagic = 0; + manager->common.magic = 0; + free(manager); + + *managerp = NULL; + + timermgr = NULL; +} + +isc_result_t +isc__timermgr_nextevent(isc_timermgr_t *manager0, isc_time_t *when) { + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + + if (manager == NULL) + manager = timermgr; + if (manager == NULL || manager->nscheduled == 0) + return (ISC_R_NOTFOUND); + *when = manager->due; + return (ISC_R_SUCCESS); +} + +void +isc__timermgr_dispatch(isc_timermgr_t *manager0) { + isc__timermgr_t *manager = (isc__timermgr_t *)manager0; + isc_time_t now; + + if (manager == NULL) + manager = timermgr; + if (manager == NULL) + return; + TIME_NOW(&now); + dispatch(manager, &now); +} + +isc_result_t +isc__timer_register(void) { + return (isc_timer_register(isc__timermgr_create)); +} + +static isc_timermgrcreatefunc_t timermgr_createfunc = NULL; + +isc_result_t +isc_timer_register(isc_timermgrcreatefunc_t createfunc) { + isc_result_t result = ISC_R_SUCCESS; + + if (timermgr_createfunc == NULL) + timermgr_createfunc = createfunc; + else + result = ISC_R_EXISTS; + + return (result); +} + +isc_result_t +isc_timermgr_createinctx(isc_appctx_t *actx, + isc_timermgr_t **managerp) +{ + isc_result_t result; + + REQUIRE(timermgr_createfunc != NULL); + result = (*timermgr_createfunc)(managerp); + + if (result == ISC_R_SUCCESS) + isc_appctx_settimermgr(actx, *managerp); + + return (result); +} + +isc_result_t +isc_timermgr_create(isc_timermgr_t **managerp) { + return (isc__timermgr_create(managerp)); +} + +void +isc_timermgr_destroy(isc_timermgr_t **managerp) { + REQUIRE(*managerp != NULL && ISCAPI_TIMERMGR_VALID(*managerp)); + + isc__timermgr_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 interval_t *interval, + isc_task_t *task, isc_taskaction_t action, void *arg, + isc_timer_t **timerp) +{ + REQUIRE(ISCAPI_TIMERMGR_VALID(manager)); + + return (isc__timer_create(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); + + isc__timer_attach(timer, timerp); + + ENSURE(*timerp == timer); +} + +void +isc_timer_detach(isc_timer_t **timerp) { + REQUIRE(timerp != NULL && ISCAPI_TIMER_VALID(*timerp)); + + isc__timer_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 interval_t *interval, + isc_boolean_t purge) +{ + REQUIRE(ISCAPI_TIMER_VALID(timer)); + + return (isc__timer_reset(timer, type, expires, + interval, purge)); +} + +isc_result_t +isc_timer_touch(isc_timer_t *timer) { + REQUIRE(ISCAPI_TIMER_VALID(timer)); + + return (isc__timer_touch(timer)); +} |
