diff options
Diffstat (limited to 'libhw/host_alarmclock.c')
-rw-r--r-- | libhw/host_alarmclock.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/libhw/host_alarmclock.c b/libhw/host_alarmclock.c new file mode 100644 index 0000000..a89294c --- /dev/null +++ b/libhw/host_alarmclock.c @@ -0,0 +1,87 @@ +/* libhw/host_alarmclock.c - <libhw/generic/alarmclock.h> implementation for POSIX hosts + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <assert.h> +#include <time.h> /* for clock_gettime(), CLOCK_MONOTONIC, clockid_t, struct timespec */ + +#include <libmisc/vcall.h> + +#define IMPLEMENTATION_FOR_LIBHW_GENERIC_ALARMCLOCK_H YES +#include <libhw/generic/alarmclock.h> + +#include "host_sigrt.h" + +struct hostclock { + implements_alarmclock; + bool initialized; + clockid_t clock_id; + timer_t timer_id; + struct alarmclock_trigger *queue; +}; + +static uint64_t hostclock_get_ns(implements_alarmclock *_alarmclock) { + struct hostclock *alarmclock = + VCALL_SELF(struct hostclock, implements_alarmclock, _alarmclock); + assert(alarmclock); + + struct timespec ts; + int r; + + r = clock_gettime(alarmclock->clock_id, &ts); + assert(r == 0); + + return (((uint64_t)ts.tv_sec) * NS_PER_S) + (uint64_t)ts.tv_nsec; +} + +static void hostclock_handle_sig_alarm(int UNUSED(sig), siginfo_t *info, void *UNUSED(ucontext)) { + struct hostclock *alarmclock = info->si_value.sival_ptr; + assert(alarmclock) + + while (alarmclock->queue && + alarmclock->queue->fire_at_ns <= hostclock_get_ns(alarmclock)) { + struct alarmclock_trigger *trigger = alarmclock->queue; + trigger->cb(trigger->cb_arg); + alarmclock->queue = trigger->next; + trigger->alarmclock = NULL; + trigger->next = NULL; + trigger->prev = NULL; + } + + if (alarmclock->queue) { + timer_settime(alarmclock + } + timer_hw->alarm[alarm_num] = (uint32_t)NS_TO_US_ROUNDUP(alarmclock->queue->fire_at_ns); +} + +static bool hostclock_add_trigger(implements_alarmclock *self, + struct alarmclock_trigger *trigger, + uint64_t fire_at_ns, + void (*cb)(void *), + void *cb_arg) { + struct hostclock *clock = + VCALL_SELF(struct hostclock, implements_alarmclock, _clock); + + +} + +static void hostclock_del_trigger(implements_alarmclock *self, + struct alarmclock_trigger *trigger) { +} + +/* Globals ********************************************************************/ + +static struct alarmclock_vtable hostclock_vtable = { + .get_time_ns = hostclock_get_time_ns, + .add_trigger = hostclock_add_trigger, + .del_trigger = hostclock_del_trigger, +}; + +static struct hostclock clock_monotonic = { + .vtable = hostclock_vtable, + .clockid = CLOCK_MONOTONIC, +}; + +const implements_alarmclock *bootclock = &clock_monotonic; |