/* libhw/host_alarmclock.c - implementation for POSIX hosts * * Copyright (C) 2024 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later */ #include #include /* for clock_gettime(), CLOCK_MONOTONIC, clockid_t, struct timespec */ #include #define IMPLEMENTATION_FOR_LIBHW_GENERIC_ALARMCLOCK_H YES #include #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;