From ad8a5cb6c7e9931bea51f2f8b493c4a9f7433a48 Mon Sep 17 00:00:00 2001 From: Nicholas Rodrigues Lordello Date: Mon, 18 Aug 2025 10:32:26 +0200 Subject: [PATCH] Read System Clock for Monotonic Time This PR changes the `janet_gettime` implementation for OSX <10.12 to read the system clock for `(os/clock :monotonic)`. As far as I was able to find online this is _a_ monotonic clock, although it produces different values from `clock_gettime(CLOCK_MONOTONIC, ...)` on the same system. I can speculate that this is related to `SYSTEM_CLOCK` monotonic time being implemented with `mach_absolute_time` which is documented to _not advance during sleep_, and I suspect that `clock_gettime(CLOCK_MONOTONIC, ...)` does. **Resources**: - `clock_get_time` implementation for the `SYSTEM_CLOCK`: - `mach_absolute_time` and `mach_continuous_time` definitions: - Stack overflow post for implementing `clock_gettime` on OS X before 10.12: --- src/core/util.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/core/util.c b/src/core/util.c index 5914b99e..f239d38e 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -931,27 +931,24 @@ int janet_gettime(struct timespec *spec, enum JanetTimeSource source) { #include #include int janet_gettime(struct timespec *spec, enum JanetTimeSource source) { - if (source == JANET_TIME_REALTIME) { - clock_serv_t cclock; - mach_timespec_t mts; - host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - spec->tv_sec = mts.tv_sec; - spec->tv_nsec = mts.tv_nsec; - } else if (source == JANET_TIME_MONOTONIC) { - clock_serv_t cclock; - int nsecs; - mach_msg_type_number_t count; - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_attributes(cclock, CLOCK_GET_TIME_RES, (clock_attr_t)&nsecs, &count); - mach_port_deallocate(mach_task_self(), cclock); - clock_getres(CLOCK_MONOTONIC, spec); - } if (source == JANET_TIME_CPUTIME) { clock_t tmp = clock(); spec->tv_sec = tmp / CLOCKS_PER_SEC; spec->tv_nsec = ((tmp - (spec->tv_sec * CLOCKS_PER_SEC)) * 1000000000) / CLOCKS_PER_SEC; + } else { + clock_serv_t cclock; + mach_timespec_t mts; + clock_id_t cid = CALENDAR_CLOCK; + if (source == JANET_TIME_REALTIME) { + cid = CALENDAR_CLOCK; + } else if (source == JANET_TIME_MONOTONIC) { + cid = SYSTEM_CLOCK; + } + host_get_clock_service(mach_host_self(), cid, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + spec->tv_sec = mts.tv_sec; + spec->tv_nsec = mts.tv_nsec; } return 0; }