hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit f542960084521e9d9a3e356c2ba180c2910bff42
parent e1e882bfc20377e734c14a764dbf556452244d83
Author: Lorenz (xha) <me@xha.li>
Date:   Sat, 25 Nov 2023 15:18:09 +0100

OpenBSD: add time

Signed-off-by: Lorenz (xha) <me@xha.li>

Diffstat:
Atime/+openbsd/functions.ha | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+), 0 deletions(-)

diff --git a/time/+openbsd/functions.ha b/time/+openbsd/functions.ha @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MPL-2.0 +// (c) Hare authors <https://harelang.org> + +use rt; + +// Converts a [[duration]] to an [[rt::timespec]]. This function is +// non-portable. +export fn duration_to_timespec(n: duration, ts: *rt::timespec) void = { + ts.tv_sec = n / SECOND; + ts.tv_nsec = n % SECOND; +}; + +// Converts an [[instant]] to an [[rt::timespec]]. This function is +// non-portable. +export fn instant_to_timespec(t: instant, ts: *rt::timespec) void = { + ts.tv_sec = t.sec; + ts.tv_nsec = t.nsec; +}; + +// Converts a [[rt::timespec]] to an [[instant]]. This function is +// non-portable. +export fn timespec_to_instant(ts: rt::timespec) instant = instant { + sec = ts.tv_sec, + nsec = ts.tv_nsec, +}; + +// Yields the process to the kernel and returns after the requested duration. +export fn sleep(n: duration) void = { + let in = rt::timespec { ... }; + duration_to_timespec(n, &in); + let req = &in; + + for (true) { + let res = rt::timespec { ... }; + match (rt::nanosleep(req, &res)) { + case void => + return; + case let err: rt::errno => + switch (err) { + case rt::EINTR => + req = &res; + case => + abort("Unexpected error from nanosleep"); + }; + }; + }; +}; + +// An enumeration of clocks available on this system. Different clocks represent +// times from different epochs, and have different characteristics with regards +// to leap seconds, NTP adjustments, and so on. All systems provide the REALTIME +// and MONOTONIC clocks at least; use of other clocks is not guaranteed to be +// portable. +export type clock = enum { + // The current wall-clock time. This may jump forwards or backwards in + // time to account for leap seconds, NTP adjustments, etc. + REALTIME = rt::CLOCK_REALTIME, + + // The current monotonic time. This clock measures from some undefined + // epoch and is not affected by leap seconds, NTP adjustments, and + // changes to the system time: it always increases by one second per + // second. + MONOTONIC = rt::CLOCK_MONOTONIC, + + // The uptime clock. It is the time that has elapsed since the system + // booted. Begins at zero. + BOOT = rt::CLOCK_BOOTTIME, + + // The runtime clock. It only advances while the system is not suspended + // and begins when the system is booted. Begins at zero. + UPTIME = rt::CLOCK_UPTIME, + + // The process CPU clock. It begins at zero and is advanced while the + // calling process is running in user or kernel mode. + PROCESS_CPU = rt::CLOCK_PROCESS_CPUTIME_ID, + + // The thread CPU clock. It begins at zero and is advanced while the + // calling thread is running in user or kernel mode. + THREAD_CPU = rt::CLOCK_THREAD_CPUTIME_ID, +}; + +// Returns the current time for a given clock. +export fn now(clock: clock) instant = { + let ts = rt::timespec { ... }; + match (rt::clock_gettime(clock, &ts)) { + case void => + return timespec_to_instant(ts); + case let err: rt::errno => + abort("Unexpected error from clock_gettime"); + }; +};