@matheusbsbs / matheus-bagliano / commits / 6ed807f843
Fork 0

Windows: A rudimentary poll() emulation.

This emulation of poll() is by far not general. It assumes that the fds that are to be waited for are connected to pipes. The pipes are polled in a loop until data becomes available in at least one of them. If only a single fd is waited for, the implementation actually does not wait at all, but assumes that a subsequent read() will block. In order not to needlessly burn CPU time, the CPU is yielded to other processes before the next round in the poll loop using Sleep(0). Note that any sleep timeout greater than zero will reduce the efficiency by a magnitude. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>

Johannes Sixt committed Dec 1, 2007 at 22:00 UTC 6ed807f8432c558ef102c94cb2e8ae4e03c48d4e
1 file changed +56 -1
compat/mingw.c
+56 -1
@@ -101,7 +101,62 @@ int pipe(int filedes[2])
101
102 int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
103 {
104 - return -1;
104 + int i, pending;
105 +
106 + if (timeout != -1)
107 + return errno = EINVAL, error("poll timeout not supported");
108 +
109 + /* When there is only one fd to wait for, then we pretend that
110 + * input is available and let the actual wait happen when the
111 + * caller invokes read().
112 + */
113 + if (nfds == 1) {
114 + if (!(ufds[0].events & POLLIN))
115 + return errno = EINVAL, error("POLLIN not set");
116 + ufds[0].revents = POLLIN;
117 + return 0;
118 + }
119 +
120 +repeat:
121 + pending = 0;
122 + for (i = 0; i < nfds; i++) {
123 + DWORD avail = 0;
124 + HANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);
125 + if (h == INVALID_HANDLE_VALUE)
126 + return -1; /* errno was set */
127 +
128 + if (!(ufds[i].events & POLLIN))
129 + return errno = EINVAL, error("POLLIN not set");
130 +
131 + /* this emulation works only for pipes */
132 + if (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {
133 + int err = GetLastError();
134 + if (err == ERROR_BROKEN_PIPE) {
135 + ufds[i].revents = POLLHUP;
136 + pending++;
137 + } else {
138 + errno = EINVAL;
139 + return error("PeekNamedPipe failed,"
140 + " GetLastError: %u", err);
141 + }
142 + } else if (avail) {
143 + ufds[i].revents = POLLIN;
144 + pending++;
145 + } else
146 + ufds[i].revents = 0;
147 + }
148 + if (!pending) {
149 + /* The only times that we spin here is when the process
150 + * that is connected through the pipes is waiting for
151 + * its own input data to become available. But since
152 + * the process (pack-objects) is itself CPU intensive,
153 + * it will happily pick up the time slice that we are
154 + * relinguishing here.
155 + */
156 + Sleep(0);
157 + goto repeat;
158 + }
159 + return 0;
160 }
161
162 struct tm *gmtime_r(const time_t *timep, struct tm *result)