From 22c4fb20d407f464813ce1031308bc4c6db13bb4 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 14 Apr 2010 06:55:55 +0200 Subject: win32: add poll() Only works for pipes, as commented in the source code. --- include/mingw.h | 2 +- win32/mingw.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/include/mingw.h b/include/mingw.h index d41580da7..c2c0c7816 100644 --- a/include/mingw.h +++ b/include/mingw.h @@ -61,7 +61,7 @@ typedef unsigned long nfds_t; #define POLLIN 1 #define POLLHUP 2 -NOIMPL(poll,struct pollfd *ufds UNUSED_PARAM, unsigned int nfds UNUSED_PARAM, int timeout UNUSED_PARAM); +int poll(struct pollfd *ufds, unsigned int nfds, int timeout); /* * pwd.h diff --git a/win32/mingw.c b/win32/mingw.c index adf2d161e..0376c9b13 100644 --- a/win32/mingw.c +++ b/win32/mingw.c @@ -176,6 +176,75 @@ int pipe(int filedes[2]) return 0; } +int poll(struct pollfd *ufds, unsigned int nfds, int timeout) +{ + int i, pending; + + if (timeout >= 0) { + if (nfds == 0) { + Sleep(timeout); + return 0; + } + errno = EINVAL; + return -1; + } + + /* When there is only one fd to wait for, then we pretend that + * input is available and let the actual wait happen when the + * caller invokes read(). + */ + if (nfds == 1) { + if (!(ufds[0].events & POLLIN)) { + errno = EINVAL; + return -1; + } + ufds[0].revents = POLLIN; + return 0; + } + +repeat: + pending = 0; + for (i = 0; i < nfds; i++) { + DWORD avail = 0; + HANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd); + if (h == INVALID_HANDLE_VALUE) + return -1; /* errno was set */ + + if (!(ufds[i].events & POLLIN)) { + errno = EINVAL; + return -1; + } + + /* this emulation works only for pipes */ + if (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) { + int err = GetLastError(); + if (err == ERROR_BROKEN_PIPE) { + ufds[i].revents = POLLHUP; + pending++; + } else { + errno = EINVAL; + return -1; + } + } else if (avail) { + ufds[i].revents = POLLIN; + pending++; + } else + ufds[i].revents = 0; + } + if (!pending) { + /* The only times that we spin here is when the process + * that is connected through the pipes is waiting for + * its own input data to become available. But since + * the process (pack-objects) is itself CPU intensive, + * it will happily pick up the time slice that we are + * relinguishing here. + */ + Sleep(0); + goto repeat; + } + return 0; +} + struct tm *gmtime_r(const time_t *timep, struct tm *result) { /* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */ -- cgit v1.2.3-55-g6feb