Commit 127fa80090

Bas van den Berg <BarabasGitHub@users.noreply.github.com>
2020-09-10 20:20:27
implement poll for windows with WSAPoll (only available on vista and higher)
1 parent f5b9e44
Changed files (4)
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;
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,
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,
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;
     }
 }