1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008 Free Software Foundation, Inc.
6 This file is part of gnulib.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
25 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
26 #include <sys/types.h>
39 unsigned char in[FD_SETSIZE / CHAR_BIT];
40 unsigned char out[FD_SETSIZE / CHAR_BIT];
43 /* Declare data structures for ntdll functions. */
44 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
46 ULONG NamedPipeConfiguration;
47 ULONG MaximumInstances;
48 ULONG CurrentInstances;
50 ULONG ReadDataAvailable;
52 ULONG WriteQuotaAvailable;
55 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
57 typedef struct _IO_STATUS_BLOCK
63 ULONG_PTR Information;
64 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
66 typedef enum _FILE_INFORMATION_CLASS {
67 FilePipeLocalInformation = 24
68 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
70 typedef DWORD (WINAPI *PNtQueryInformationFile)
71 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
77 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */
80 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
83 BOOL read, write, except;
85 INPUT_RECORD *irbuffer;
89 FILE_PIPE_LOCAL_INFORMATION fpli;
90 static PNtQueryInformationFile NtQueryInformationFile;
91 static BOOL once_only;
93 read = write = except = FALSE;
94 switch (GetFileType (h))
104 NtQueryInformationFile = (PNtQueryInformationFile)
105 GetProcAddress (GetModuleHandle ("ntdll.dll"),
106 "NtQueryInformationFile");
110 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
118 /* It was the write-end of the pipe. Check if it is writable.
119 If NtQueryInformationFile fails, optimistically assume the pipe is
120 writable. This could happen on Win9x, where NtQueryInformationFile
121 is not available, or if we inherit a pipe that doesn't permit
122 FILE_READ_ATTRIBUTES access on the write end (I think this should
123 not happen since WinXP SP2; WINE seems fine too). Otherwise,
124 ensure that enough space is available for atomic writes. */
125 memset (&iosb, 0, sizeof (iosb));
126 memset (&fpli, 0, sizeof (fpli));
128 if (!NtQueryInformationFile
129 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
130 FilePipeLocalInformation)
131 || fpli.WriteQuotaAvailable >= PIPE_BUF
132 || (fpli.OutboundQuota < PIPE_BUF &&
133 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
139 ret = WaitForSingleObject (h, 0);
141 if (ret == WAIT_OBJECT_0)
144 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
145 if (!bRet || nbuffer == 0)
148 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
149 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
150 if (!bRet || avail == 0)
153 for (i = 0; i < avail; i++)
154 if (irbuffer[i].EventType == KEY_EVENT)
160 ret = WaitForSingleObject (h, 0);
162 if (ret == WAIT_OBJECT_0)
169 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
171 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
175 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
177 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
181 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
183 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
191 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
192 struct timeval *timeout)
194 static struct timeval tv0;
195 static HANDLE hEvent;
196 HANDLE h, handle_array[FD_SETSIZE + 2];
197 fd_set handle_rfds, handle_wfds, handle_xfds;
198 struct bitset rbits, wbits, xbits;
199 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
200 DWORD ret, wait_timeout, nhandles, nsock;
204 if (nfds > FD_SETSIZE)
208 wait_timeout = INFINITE;
211 wait_timeout = timeout->tv_sec + timeout->tv_usec / 1000;
213 /* select is also used as a portable usleep. */
214 if (!rfds && !wfds && !xfds)
216 Sleep (wait_timeout);
222 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
224 handle_array[0] = hEvent;
228 /* Copy descriptors to bitsets. */
229 memset (&rbits, 0, sizeof (rbits));
230 memset (&wbits, 0, sizeof (wbits));
231 memset (&xbits, 0, sizeof (xbits));
232 memset (anyfds_in, 0, sizeof (anyfds_in));
234 for (i = 0; i < rfds->fd_count; i++)
236 fd = rfds->fd_array[i];
237 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
238 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
241 rfds = (fd_set *) alloca (sizeof (fd_set));
244 for (i = 0; i < wfds->fd_count; i++)
246 fd = wfds->fd_array[i];
247 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
248 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
251 wfds = (fd_set *) alloca (sizeof (fd_set));
254 for (i = 0; i < xfds->fd_count; i++)
256 fd = xfds->fd_array[i];
257 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
258 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
261 xfds = (fd_set *) alloca (sizeof (fd_set));
263 /* Zero all the fd_sets, including the application's. */
267 FD_ZERO (&handle_rfds);
268 FD_ZERO (&handle_wfds);
269 FD_ZERO (&handle_xfds);
271 /* Classify handles. Create fd sets for sockets, poll the others. */
272 for (i = 0; i < nfds; i++)
276 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
279 h = (HANDLE) _get_osfhandle (i);
286 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
287 WSAEnumNetworkEvents instead distinguishes the two correctly. */
288 ev.lNetworkEvents = 0xDEADBEEF;
289 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
290 if (ev.lNetworkEvents != 0xDEADBEEF)
292 int requested = FD_CLOSE;
294 /* See above; socket handles are mapped onto select, but we
295 need to map descriptors to handles. */
296 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
298 requested |= FD_READ | FD_ACCEPT;
299 FD_SET ((SOCKET) h, rfds);
300 FD_SET ((SOCKET) h, &handle_rfds);
302 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
304 requested |= FD_WRITE | FD_CONNECT;
305 FD_SET ((SOCKET) h, wfds);
306 FD_SET ((SOCKET) h, &handle_wfds);
308 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
311 FD_SET ((SOCKET) h, xfds);
312 FD_SET ((SOCKET) h, &handle_xfds);
315 WSAEventSelect ((SOCKET) h, hEvent, requested);
320 handle_array[nhandles++] = h;
322 /* Poll now. If we get an event, do not wait below. */
323 if (wait_timeout != 0
324 && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
329 if (wait_timeout == 0 || nsock == 0)
333 /* See if we need to wait in the loop below. If any select is ready,
334 do MsgWaitForMultipleObjects anyway to dispatch messages, but
335 no need to call select again. */
336 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
339 /* Restore the fd_sets for the other select we do below. */
340 memcpy (&handle_rfds, rfds, sizeof (fd_set));
341 memcpy (&handle_wfds, wfds, sizeof (fd_set));
342 memcpy (&handle_xfds, xfds, sizeof (fd_set));
350 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
351 wait_timeout, QS_ALLINPUT);
353 if (ret == WAIT_OBJECT_0 + nhandles)
355 /* new input of some other kind */
357 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
359 TranslateMessage (&msg);
360 DispatchMessage (&msg);
367 /* If we haven't done it yet, check the status of the sockets. */
368 if (rc == 0 && nsock > 0)
369 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
371 /* Now fill in the results. */
376 /* Place a sentinel at the end of the array. */
377 handle_array[nhandles] = NULL;
379 for (i = 0; i < nfds; i++)
381 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
384 h = (HANDLE) _get_osfhandle (i);
385 if (h != handle_array[nhandles])
387 /* Perform handle->descriptor mapping. Don't update rc, as these
388 results are counted in the return value of Winsock's select. */
389 WSAEventSelect ((SOCKET) h, NULL, 0);
390 if (FD_ISSET (h, &handle_rfds))
392 if (FD_ISSET (h, &handle_wfds))
394 if (FD_ISSET (h, &handle_xfds))
401 win32_poll_handle (h, i, &rbits, &wbits, &xbits);
402 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
407 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
412 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
423 #endif /* Native Win32. */