| ... | ... | @@ -13,44 +13,35 @@ const posix = std.os.posix; |
| 13 | 13 | |
| 14 | 14 | pub const epoch = @import("epoch.zig"); |
| 15 | 15 | |
| 16 | | /// Sleep for the specified duration |
| 16 | /// Spurious wakeups are possible and no precision of timing is guaranteed. |
| 17 | 17 | pub fn sleep(nanoseconds: u64) void { |
| 18 | 18 | switch (builtin.os) { |
| 19 | 19 | Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => { |
| 20 | 20 | const s = nanoseconds / ns_per_s; |
| 21 | 21 | const ns = nanoseconds % ns_per_s; |
| 22 | | posixSleep(@intCast(u63, s), @intCast(u63, ns)); |
| 22 | posixSleep(s, ns); |
| 23 | 23 | }, |
| 24 | 24 | Os.windows => { |
| 25 | 25 | const ns_per_ms = ns_per_s / ms_per_s; |
| 26 | 26 | const milliseconds = nanoseconds / ns_per_ms; |
| 27 | | windows.Sleep(@intCast(windows.DWORD, milliseconds)); |
| 27 | const ms_that_will_fit = std.math.cast(windows.DWORD, milliseconds) catch std.math.maxInt(windows.DWORD); |
| 28 | windows.Sleep(ms_that_will_fit); |
| 28 | 29 | }, |
| 29 | 30 | else => @compileError("Unsupported OS"), |
| 30 | 31 | } |
| 31 | 32 | } |
| 32 | 33 | |
| 33 | | pub fn posixSleep(seconds: u63, nanoseconds: u63) void { |
| 34 | | var req: posix.timespec = undefined; |
| 34 | /// Spurious wakeups are possible and no precision of timing is guaranteed. |
| 35 | pub fn posixSleep(seconds: u64, nanoseconds: u64) void { |
| 36 | var req = posix.timespec{ |
| 37 | .tv_sec = std.math.cast(isize, seconds) catch std.math.maxInt(isize), |
| 38 | .tv_nsec = std.math.cast(isize, nanoseconds) catch std.math.maxInt(isize), |
| 39 | }; |
| 35 | 40 | var rem: posix.timespec = undefined; |
| 36 | | |
| 37 | | var req_sec = seconds; |
| 38 | | var req_nsec = nanoseconds; |
| 39 | | |
| 40 | 41 | while (true) { |
| 41 | | req.tv_sec = math.min(math.maxInt(isize), req_sec); |
| 42 | | req.tv_nsec = @intCast(isize, req_nsec); |
| 43 | | |
| 44 | | req_sec -= @intCast(u63, req.tv_sec); |
| 45 | | req_nsec = 0; |
| 46 | | |
| 47 | 42 | const ret_val = posix.nanosleep(&req, &rem); |
| 48 | 43 | const err = posix.getErrno(ret_val); |
| 49 | 44 | switch (err) { |
| 50 | | 0 => { |
| 51 | | // If there's still time to wait keep running the loop |
| 52 | | if (req_sec == 0 and req_nsec == 0) return; |
| 53 | | }, |
| 54 | 45 | posix.EFAULT => unreachable, |
| 55 | 46 | posix.EINVAL => { |
| 56 | 47 | // Sometimes Darwin returns EINVAL for no reason. |
| ... | ... | @@ -58,10 +49,10 @@ pub fn posixSleep(seconds: u63, nanoseconds: u63) void { |
| 58 | 49 | return; |
| 59 | 50 | }, |
| 60 | 51 | posix.EINTR => { |
| 61 | | req_sec += @intCast(u63, rem.tv_sec); |
| 62 | | req_nsec = @intCast(u63, rem.tv_nsec); |
| 52 | req = rem; |
| 63 | 53 | continue; |
| 64 | 54 | }, |
| 55 | // This prong handles success as well as unexpected errors. |
| 65 | 56 | else => return, |
| 66 | 57 | } |
| 67 | 58 | } |