diff --git a/std/os/time.zig b/std/os/time.zig index 99c8b5992..abb641284 100644 --- a/std/os/time.zig +++ b/std/os/time.zig @@ -13,44 +13,35 @@ const posix = std.os.posix; pub const epoch = @import("epoch.zig"); -/// Sleep for the specified duration +/// Spurious wakeups are possible and no precision of timing is guaranteed. pub fn sleep(nanoseconds: u64) void { switch (builtin.os) { Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { const s = nanoseconds / ns_per_s; const ns = nanoseconds % ns_per_s; - posixSleep(@intCast(u63, s), @intCast(u63, ns)); + posixSleep(s, ns); }, Os.windows => { const ns_per_ms = ns_per_s / ms_per_s; const milliseconds = nanoseconds / ns_per_ms; - windows.Sleep(@intCast(windows.DWORD, milliseconds)); + const ms_that_will_fit = std.math.cast(windows.DWORD, milliseconds) catch std.math.maxInt(windows.DWORD); + windows.Sleep(ms_that_will_fit); }, else => @compileError("Unsupported OS"), } } -pub fn posixSleep(seconds: u63, nanoseconds: u63) void { - var req: posix.timespec = undefined; +/// Spurious wakeups are possible and no precision of timing is guaranteed. +pub fn posixSleep(seconds: u64, nanoseconds: u64) void { + var req = posix.timespec{ + .tv_sec = std.math.cast(isize, seconds) catch std.math.maxInt(isize), + .tv_nsec = std.math.cast(isize, nanoseconds) catch std.math.maxInt(isize), + }; var rem: posix.timespec = undefined; - - var req_sec = seconds; - var req_nsec = nanoseconds; - while (true) { - req.tv_sec = math.min(math.maxInt(isize), req_sec); - req.tv_nsec = @intCast(isize, req_nsec); - - req_sec -= @intCast(u63, req.tv_sec); - req_nsec = 0; - const ret_val = posix.nanosleep(&req, &rem); const err = posix.getErrno(ret_val); switch (err) { - 0 => { - // If there's still time to wait keep running the loop - if (req_sec == 0 and req_nsec == 0) return; - }, posix.EFAULT => unreachable, posix.EINVAL => { // Sometimes Darwin returns EINVAL for no reason. @@ -58,10 +49,10 @@ pub fn posixSleep(seconds: u63, nanoseconds: u63) void { return; }, posix.EINTR => { - req_sec += @intCast(u63, rem.tv_sec); - req_nsec = @intCast(u63, rem.tv_nsec); + req = rem; continue; }, + // This prong handles success as well as unexpected errors. else => return, } }