summaryrefslogtreecommitdiff
path: root/libhw/host_alarmclock.c
blob: a89294c2ca6066369eaadc53208578234053a651 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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;