summaryrefslogtreecommitdiff
path: root/libhw/host_alarmclock.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhw/host_alarmclock.c')
-rw-r--r--libhw/host_alarmclock.c87
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;