Commit 751ab72a82

Andrew Kelley <superjoe30@gmail.com>
2017-09-19 15:46:41
std: fix os.sleep on darwin and windows
1 parent 86eb183
std/c/index.zig
@@ -40,3 +40,4 @@ pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: u
 pub extern "c" fn realpath(noalias file_name: &const u8, noalias resolved_name: &u8) -> ?&u8;
 pub extern "c" fn sigprocmask(how: c_int, noalias set: &const sigset_t, noalias oset: ?&sigset_t) -> c_int;
 pub extern "c" fn sigaction(sig: c_int, noalias act: &const Sigaction, noalias oact: ?&Sigaction) -> c_int;
+pub extern "c" fn nanosleep(rqtp: &const timespec, rmtp: ?&timespec) -> c_int;
std/os/windows/index.zig
@@ -37,6 +37,8 @@ pub extern "kernel32" stdcallcc fn WriteFile(in_hFile: HANDLE, in_lpBuffer: &con
     in_nNumberOfBytesToWrite: DWORD, out_lpNumberOfBytesWritten: ?&DWORD,
     in_out_lpOverlapped: ?&OVERLAPPED) -> BOOL;
 
+pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD);
+
 pub const PROV_RSA_FULL = 1;
 
 pub const UNICODE = false;
std/os/darwin.zig
@@ -221,6 +221,10 @@ pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -
     errnoWrap(c.readlink(path, buf_ptr, buf_len))
 }
 
+pub fn nanosleep(req: &const timespec, rem: ?&timespec) -> usize {
+    errnoWrap(c.nanosleep(req, rem))
+}
+
 pub fn realpath(noalias filename: &const u8, noalias resolved_name: &u8) -> usize {
     if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(*c._errno())) else 0
 }
@@ -255,6 +259,8 @@ pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigacti
 pub const sigset_t = c.sigset_t;
 pub const empty_sigset = sigset_t(0);
 
+pub const timespec = c.timespec;
+
 /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
 pub const Sigaction = struct {
     handler: extern fn(i32),
std/os/index.zig
@@ -949,7 +949,21 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
     }
 }
 
-pub fn sleep(seconds: u64, nanoseconds: u64) {
+pub fn sleep(seconds: usize, nanoseconds: usize) {
+    switch(builtin.os) {
+        Os.linux, Os.darwin, Os.macosx, Os.ios => {
+            posixSleep(u63(seconds), u63(nanoseconds));
+        },
+        Os.windows => {
+            const milliseconds = seconds * 1000 + nanoseconds / 1000000;
+            windows.Sleep(windows.DWORD(milliseconds));
+        },
+        else => @compileError("Unsupported OS"),
+    }
+}
+
+const u63 = @IntType(false, 63);
+pub fn posixSleep(seconds: u63, nanoseconds: u63) {
     var req = posix.timespec {
         .tv_sec = seconds,
         .tv_nsec = nanoseconds,
@@ -961,7 +975,11 @@ pub fn sleep(seconds: u64, nanoseconds: u64) {
         if (err == 0) return;
         switch (err) {
             posix.EFAULT => unreachable,
-            posix.EINVAL => unreachable,
+            posix.EINVAL => {
+                // Sometimes Darwin returns EINVAL for no reason.
+                // We treat it as a spurious wakeup.
+                return;
+            },
             posix.EINTR => {
                 req = rem;
                 continue;
@@ -970,3 +988,7 @@ pub fn sleep(seconds: u64, nanoseconds: u64) {
         }
     }
 }
+
+test "os.sleep" {
+    sleep(0, 1);
+}
std/os/linux_x86_64.zig
@@ -484,6 +484,6 @@ pub const Stat = extern struct {
 };
 
 pub const timespec = extern struct {
-    tv_sec: usize,
-    tv_nsec: usize,
+    tv_sec: isize,
+    tv_nsec: isize,
 };