std: fix os.sleep on darwin and windows

This commit is contained in:
Andrew Kelley 2017-09-19 09:46:41 -04:00
parent 86eb183668
commit 751ab72a82
5 changed files with 35 additions and 4 deletions

View File

@ -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;

View File

@ -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),

View File

@ -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);
}

View File

@ -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,
};

View File

@ -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;