diff options
Diffstat (limited to 'shared/n-acd/src/util')
| -rw-r--r-- | shared/n-acd/src/util/timer.c | 189 | ||||
| -rw-r--r-- | shared/n-acd/src/util/timer.h | 54 |
2 files changed, 0 insertions, 243 deletions
diff --git a/shared/n-acd/src/util/timer.c b/shared/n-acd/src/util/timer.c deleted file mode 100644 index af2a887c..00000000 --- a/shared/n-acd/src/util/timer.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Timer Utility Library - */ - -#include <assert.h> -#include <c-rbtree.h> -#include <c-stdaux.h> -#include <errno.h> -#include <stdlib.h> -#include <sys/timerfd.h> -#include <time.h> -#include "timer.h" - -int timer_init(Timer *timer) { - clockid_t clock = CLOCK_BOOTTIME; - int r; - - r = timerfd_create(clock, TFD_CLOEXEC | TFD_NONBLOCK); - if (r < 0 && errno == EINVAL) { - clock = CLOCK_MONOTONIC; - r = timerfd_create(clock, TFD_CLOEXEC | TFD_NONBLOCK); - } - if (r < 0) - return -errno; - - *timer = (Timer)TIMER_NULL(*timer); - timer->fd = r; - timer->clock = clock; - - return 0; -} - -void timer_deinit(Timer *timer) { - c_assert(c_rbtree_is_empty(&timer->tree)); - - if (timer->fd >= 0) { - close(timer->fd); - timer->fd = -1; - } -} - -void timer_now(Timer *timer, uint64_t *nowp) { - struct timespec ts; - int r; - - r = clock_gettime(timer->clock, &ts); - c_assert(r >= 0); - - *nowp = ts.tv_sec * UINT64_C(1000000000) + ts.tv_nsec; -} - -void timer_rearm(Timer *timer) { - uint64_t time; - Timeout *timeout; - int r; - - /* - * A timeout value of 0 clears the timer, we should only set that if - * no timeout exists in the tree. - */ - - timeout = c_rbnode_entry(c_rbtree_first(&timer->tree), Timeout, node); - c_assert(!timeout || timeout->timeout); - - time = timeout ? timeout->timeout : 0; - - if (time != timer->scheduled_timeout) { - r = timerfd_settime(timer->fd, - TFD_TIMER_ABSTIME, - &(struct itimerspec){ - .it_value = { - .tv_sec = time / UINT64_C(1000000000), - .tv_nsec = time % UINT64_C(1000000000), - }, - }, - NULL); - c_assert(r >= 0); - - timer->scheduled_timeout = time; - } -} - -int timer_read(Timer *timer) { - uint64_t v; - int r; - - r = read(timer->fd, &v, sizeof(v)); - if (r < 0) { - if (errno == EAGAIN) { - /* - * No more pending events. - */ - return 0; - } else { - /* - * Something failed. We use CLOCK_BOOTTIME/MONOTONIC, - * so ECANCELED cannot happen. Hence, there is no - * error that we could gracefully handle. Fail hard - * and let the caller deal with it. - */ - return -errno; - } - } else if (r != sizeof(v) || v == 0) { - /* - * Kernel guarantees 8-byte reads, and only to return - * data if at least one timer triggered; fail hard if - * it suddenly starts doing weird shit. - */ - return -EIO; - } - - return TIMER_E_TRIGGERED; -} - - -int timer_pop_timeout(Timer *timer, uint64_t until, Timeout **timeoutp) { - Timeout *timeout; - - /* - * If the first timeout is scheduled before @until, then unlink - * it and return it. Otherwise, return NULL. - */ - timeout = c_rbnode_entry(c_rbtree_first(&timer->tree), Timeout, node); - if (timeout && timeout->timeout <= until) { - c_rbnode_unlink(&timeout->node); - timeout->timeout = 0; - *timeoutp = timeout; - } else { - *timeoutp = NULL; - } - - return 0; -} - -void timeout_schedule(Timeout *timeout, Timer *timer, uint64_t time) { - c_assert(time); - - /* - * In case @timeout was already scheduled, remove it from the - * tree. If we are moving it to a new timer, rearm the old one. - */ - if (timeout->timer) { - c_rbnode_unlink(&timeout->node); - if (timeout->timer != timer) - timer_rearm(timeout->timer); - } - timeout->timer = timer; - timeout->timeout = time; - - /* - * Now insert it back into the tree in the correct new position. - * We allow duplicates in the tree, so this insertion is open-coded. - */ - { - Timeout *other; - CRBNode **slot, *parent; - - slot = &timer->tree.root; - parent = NULL; - while (*slot) { - other = c_rbnode_entry(*slot, Timeout, node); - parent = *slot; - if (timeout->timeout < other->timeout) - slot = &(*slot)->left; - else - slot = &(*slot)->right; - } - - c_rbtree_add(&timer->tree, parent, slot, &timeout->node); - } - - /* - * Rearm the timer as we updated the timeout tree. - */ - timer_rearm(timer); -} - -void timeout_unschedule(Timeout *timeout) { - Timer *timer = timeout->timer; - - if (!timer) - return; - - c_rbnode_unlink(&timeout->node); - timeout->timeout = 0; - timeout->timer = NULL; - - timer_rearm(timer); -} diff --git a/shared/n-acd/src/util/timer.h b/shared/n-acd/src/util/timer.h deleted file mode 100644 index d01b2741..00000000 --- a/shared/n-acd/src/util/timer.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include <c-rbtree.h> -#include <c-stdaux.h> -#include <inttypes.h> -#include <stdlib.h> -#include <time.h> -#include <unistd.h> - -typedef struct Timer Timer; -typedef struct Timeout Timeout; - -enum { - _TIMER_E_SUCCESS, - - TIMER_E_TRIGGERED, - - _TIMER_E_N, -}; - -struct Timer { - int fd; - clockid_t clock; - CRBTree tree; - uint64_t scheduled_timeout; -}; - -#define TIMER_NULL(_x) { \ - .fd = -1, \ - .tree = C_RBTREE_INIT, \ - } - -struct Timeout { - Timer *timer; - CRBNode node; - uint64_t timeout; -}; - -#define TIMEOUT_INIT(_x) { \ - .node = C_RBNODE_INIT((_x).node), \ - } - -int timer_init(Timer *timer); -void timer_deinit(Timer *timer); - -void timer_now(Timer *timer, uint64_t *nowp); - -int timer_pop_timeout(Timer *timer, uint64_t now, Timeout **timerp); -void timer_rearm(Timer *timer); -int timer_read(Timer *timer); - -void timeout_schedule(Timeout *timeout, Timer *timer, uint64_t time); -void timeout_unschedule(Timeout *timeout); - |