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;
|