time: add sleep

clock_nanosleep with EINTR restart from the kernel remainder.
This commit is contained in:
2026-08-07 23:00:47 +09:00
parent 1acd57a408
commit 25fd1958d3
2 changed files with 34 additions and 3 deletions

View File

@@ -1,8 +1,8 @@
// time — clocks, instants, durations. Mirrors Hare's lib/time
// (ref/hare/time/duration.ha, instant.ha, arithm.ha,
// +linux/functions.ha). Calendar / date / strftime / timezone /
// sleep live in separate Hare modules and graduate when callers /
// supporting stdlib arrive.
// +linux/functions.ha). Calendar / date / strftime / timezone live in
// separate Hare modules
// and graduate when callers / supporting stdlib arrive.
//
// `duration` is a NAMED alias of i64 (lib/math/random precedent
// at lib/math/random/random.ww:8); ww treats NAMED as a newtype,
@@ -13,8 +13,10 @@
package time;
@symbol("rt_syscall") fn syscall2(num: i64, a: i64, b: i64) i64;
@symbol("rt_syscall") fn syscall4(num: i64, a: i64, b: i64, c: i64, d: i64) i64;
def SYS_CLOCK_GETTIME: i64 = 228;
def SYS_CLOCK_NANOSLEEP: i64 = 230;
// ref/hare/time/duration.ha:6. 290y representable range.
export type duration = i64;
@@ -56,6 +58,26 @@ export fn now(c: clock) instant = {
return i;
};
// ref/hare/time/+linux/functions.ha:40-58 and
// ref/hare/sys/+linux/syscalls.ha:524-536. WW has no default parameters,
// so the Hare clock argument is explicit. The raw syscall reports -EINTR;
// restarting with the kernel-written remainder keeps the requested delay.
export fn sleep(d: duration, c: clock) void = {
let ns: i64 = d: i64;
let sec: i64 = second: i64;
let req: instant;
req.sec = ns / sec;
req.nsec = ns % sec;
for (true) {
let rem: instant;
let rc: i64 = syscall4(SYS_CLOCK_NANOSLEEP,
(c as i32): i64, 0i64, (&req): i64, (&rem): i64);
if (rc == 0i64) { return; };
if (rc != -4i64) { abort("time.sleep: clock_nanosleep failed"); };
req = rem;
};
};
// ref/hare/time/arithm.ha:9. Adds duration to instant. The
// negative-duration branch normalises nsec into [0, second).
export fn add(i: instant, x: duration) instant = {

View File

@@ -157,3 +157,12 @@ import time;
assert(!(time.compare(a, b) != -1i8));
assert(!(time.compare(b, a) != 1i8));
};
@test fn sleepmonotonic() void = {
let before: time.instant = time.now(time.clock.monotonic);
time.sleep((5i64 * (time.millisecond: i64)): time.duration,
time.clock.monotonic);
let after: time.instant = time.now(time.clock.monotonic);
let elapsed: i64 = time.diff(before, after): i64;
assert(!(elapsed < 5i64 * (time.millisecond: i64)));
};