From 25fd1958d3f5ffc01707e748552dd3b3210df9f7 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Fri, 7 Aug 2026 23:00:47 +0900 Subject: [PATCH] time: add sleep clock_nanosleep with EINTR restart from the kernel remainder. --- lib/time/time.ww | 28 +++++++++++++++++++++++++--- lib/time/timetest.ww | 9 +++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/lib/time/time.ww b/lib/time/time.ww index 2eefaa08..e54215cc 100644 --- a/lib/time/time.ww +++ b/lib/time/time.ww @@ -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 = { diff --git a/lib/time/timetest.ww b/lib/time/timetest.ww index 23b34062..bd8d971e 100644 --- a/lib/time/timetest.ww +++ b/lib/time/timetest.ww @@ -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))); +};