From 127fa8009011e19d552ffdd834c6a607498f1c1e Mon Sep 17 00:00:00 2001 From: Bas van den Berg Date: Thu, 10 Sep 2020 20:20:27 +0200 Subject: [PATCH] implement poll for windows with WSAPoll (only available on vista and higher) --- lib/std/os.zig | 32 +++++++++++++++++++++++++------- lib/std/os/bits/windows.zig | 13 +++++++++++++ lib/std/os/windows.zig | 4 ++++ lib/std/os/windows/ws2_32.zig | 26 ++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index 54c80eb788..fdd25fde35 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -5208,6 +5208,9 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len } pub const PollError = error{ + /// The network subsystem has failed. + NetworkSubsystemFailed, + /// The kernel had no space to allocate file descriptor tables. SystemResources, } || UnexpectedError; @@ -5215,14 +5218,29 @@ pub const PollError = error{ pub fn poll(fds: []pollfd, timeout: i32) PollError!usize { while (true) { const rc = system.poll(fds.ptr, fds.len, timeout); - switch (errno(rc)) { - 0 => return @intCast(usize, rc), - EFAULT => unreachable, - EINTR => continue, - EINVAL => unreachable, - ENOMEM => return error.SystemResources, - else => |err| return unexpectedErrno(err), + if (builtin.os.tag == .windows) { + if (rc == windows.ws2_32.SOCKET_ERROR) { + switch (windows.ws2_32.WSAGetLastError()) { + .WSANOTINITIALISED => unreachable, + .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENOBUFS => return error.SystemResources, + // TODO: handle more errors + else => |err| return windows.unexpectedWSAError(err), + } + } else { + return @intCast(usize, rc); + } + } else { + switch (errno(rc)) { + 0 => return @intCast(usize, rc), + EFAULT => unreachable, + EINTR => continue, + EINVAL => unreachable, + ENOMEM => return error.SystemResources, + else => |err| return unexpectedErrno(err), + } } + unreachable; } } diff --git a/lib/std/os/bits/windows.zig b/lib/std/os/bits/windows.zig index de17fd83fa..a92961881e 100644 --- a/lib/std/os/bits/windows.zig +++ b/lib/std/os/bits/windows.zig @@ -243,6 +243,19 @@ pub const IPPROTO_UDP = ws2_32.IPPROTO_UDP; pub const IPPROTO_ICMPV6 = ws2_32.IPPROTO_ICMPV6; pub const IPPROTO_RM = ws2_32.IPPROTO_RM; +pub const pollfd = ws2_32.pollfd; + +pub const POLLRDNORM = ws2_32.POLLRDNORM; +pub const POLLRDBAND = ws2_32.POLLRDBAND; +pub const POLLIN = ws2_32.POLLIN; +pub const POLLPRI = ws2_32.POLLPRI; +pub const POLLWRNORM = ws2_32.POLLWRNORM; +pub const POLLOUT = ws2_32.POLLOUT; +pub const POLLWRBAND = ws2_32.POLLWRBAND; +pub const POLLERR = ws2_32.POLLERR; +pub const POLLHUP = ws2_32.POLLHUP; +pub const POLLNVAL = ws2_32.POLLNVAL; + pub const O_RDONLY = 0o0; pub const O_WRONLY = 0o1; pub const O_RDWR = 0o2; diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 69bfd0fbcf..f53979fc7c 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -1201,6 +1201,10 @@ pub fn recvfrom(s: ws2_32.SOCKET, buf: [*]u8, len: usize, flags: u32, from: ?*ws } } +pub fn poll(fds: [*]ws2_32.pollfd, n: usize, timeout: i32) i32 { + return ws2_32.WSAPoll(fds, @intCast(u32, n), timeout); +} + pub fn WSAIoctl( s: ws2_32.SOCKET, dwIoControlCode: DWORD, diff --git a/lib/std/os/windows/ws2_32.zig b/lib/std/os/windows/ws2_32.zig index a54a29ed5e..0f6381a9a1 100644 --- a/lib/std/os/windows/ws2_32.zig +++ b/lib/std/os/windows/ws2_32.zig @@ -234,6 +234,27 @@ pub const WSAMSG = extern struct { dwFlags: DWORD, }; +pub const pollfd = extern struct { + fd: SOCKET, + events: SHORT, + revents: SHORT, +}; + +// Event flag definitions for WSAPoll(). + +pub const POLLRDNORM = 0x0100; +pub const POLLRDBAND = 0x0200; +pub const POLLIN = (POLLRDNORM | POLLRDBAND); +pub const POLLPRI = 0x0400; + +pub const POLLWRNORM = 0x0010; +pub const POLLOUT = (POLLWRNORM); +pub const POLLWRBAND = 0x0020; + +pub const POLLERR = 0x0001; +pub const POLLHUP = 0x0002; +pub const POLLNVAL = 0x0004; + // https://docs.microsoft.com/en-au/windows/win32/winsock/windows-sockets-error-codes-2 pub const WinsockError = extern enum(u16) { /// Specified event object handle is invalid. @@ -790,6 +811,11 @@ pub extern "ws2_32" fn WSASendTo( lpOverlapped: ?*WSAOVERLAPPED, lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE, ) callconv(.Stdcall) c_int; +pub extern "ws2_32" fn WSAPoll( + fdArray: [*]pollfd, + fds: c_ulong, + timeout: c_int, +) callconv(.Stdcall) c_int; pub extern "ws2_32" fn getaddrinfo( pNodeName: [*:0]const u8, pServiceName: [*:0]const u8,