time: add sleep
clock_nanosleep with EINTR restart from the kernel remainder.
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
// time — clocks, instants, durations. Mirrors Hare's lib/time
|
// time — clocks, instants, durations. Mirrors Hare's lib/time
|
||||||
// (ref/hare/time/duration.ha, instant.ha, arithm.ha,
|
// (ref/hare/time/duration.ha, instant.ha, arithm.ha,
|
||||||
// +linux/functions.ha). Calendar / date / strftime / timezone /
|
// +linux/functions.ha). Calendar / date / strftime / timezone live in
|
||||||
// sleep live in separate Hare modules and graduate when callers /
|
// separate Hare modules
|
||||||
// supporting stdlib arrive.
|
// and graduate when callers / supporting stdlib arrive.
|
||||||
//
|
//
|
||||||
// `duration` is a NAMED alias of i64 (lib/math/random precedent
|
// `duration` is a NAMED alias of i64 (lib/math/random precedent
|
||||||
// at lib/math/random/random.ww:8); ww treats NAMED as a newtype,
|
// at lib/math/random/random.ww:8); ww treats NAMED as a newtype,
|
||||||
@@ -13,8 +13,10 @@
|
|||||||
package time;
|
package time;
|
||||||
|
|
||||||
@symbol("rt_syscall") fn syscall2(num: i64, a: i64, b: i64) i64;
|
@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_GETTIME: i64 = 228;
|
||||||
|
def SYS_CLOCK_NANOSLEEP: i64 = 230;
|
||||||
|
|
||||||
// ref/hare/time/duration.ha:6. 290y representable range.
|
// ref/hare/time/duration.ha:6. 290y representable range.
|
||||||
export type duration = i64;
|
export type duration = i64;
|
||||||
@@ -56,6 +58,26 @@ export fn now(c: clock) instant = {
|
|||||||
return i;
|
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
|
// ref/hare/time/arithm.ha:9. Adds duration to instant. The
|
||||||
// negative-duration branch normalises nsec into [0, second).
|
// negative-duration branch normalises nsec into [0, second).
|
||||||
export fn add(i: instant, x: duration) instant = {
|
export fn add(i: instant, x: duration) instant = {
|
||||||
|
|||||||
@@ -157,3 +157,12 @@ import time;
|
|||||||
assert(!(time.compare(a, b) != -1i8));
|
assert(!(time.compare(a, b) != -1i8));
|
||||||
assert(!(time.compare(b, a) != 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)));
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user