Merge branch 'jk/perf-no-dups'
[git/git.git] / compat / poll / poll.c
CommitLineData
49521af8
EFL
1/* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
3
f0bd6649 4 Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
49521af8
EFL
5
6 This file is part of gnulib.
7
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)
11 any later version.
12
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.
17
18 You should have received a copy of the GNU General Public License along
48425792 19 with this program; if not, see <http://www.gnu.org/licenses/>. */
49521af8 20
e8dfcace
SH
21/* To bump the minimum Windows version to Windows Vista */
22#include "git-compat-util.h"
23
49521af8
EFL
24/* Tell gcc not to warn about the (nfd < 0) tests, below. */
25#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
26# pragma GCC diagnostic ignored "-Wtype-limits"
27#endif
28
98c573a9
JS
29#if defined(WIN32)
30# include <malloc.h>
31#endif
49521af8
EFL
32
33#include <sys/types.h>
f0bd6649 34
49521af8
EFL
35#include <errno.h>
36#include <limits.h>
37#include <assert.h>
38
39#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
40# define WIN32_NATIVE
8453c125 41# if defined (_MSC_VER) && !defined(_WIN32_WINNT)
56fb3ddc
RJ
42# define _WIN32_WINNT 0x0502
43# endif
49521af8
EFL
44# include <winsock2.h>
45# include <windows.h>
46# include <io.h>
47# include <stdio.h>
48# include <conio.h>
49#else
50# include <sys/time.h>
51# include <sys/socket.h>
98c573a9
JS
52# ifndef NO_SYS_SELECT_H
53# include <sys/select.h>
54# endif
49521af8
EFL
55# include <unistd.h>
56#endif
57
d7e357fb
JS
58/* Specification. */
59#include "poll.h"
60
49521af8
EFL
61#ifdef HAVE_SYS_IOCTL_H
62# include <sys/ioctl.h>
63#endif
64#ifdef HAVE_SYS_FILIO_H
65# include <sys/filio.h>
66#endif
67
68#include <time.h>
69
70#ifndef INFTIM
71# define INFTIM (-1)
72#endif
73
74/* BeOS does not have MSG_PEEK. */
75#ifndef MSG_PEEK
76# define MSG_PEEK 0
77#endif
78
79#ifdef WIN32_NATIVE
80
7c00bc39 81#define IsConsoleHandle(h) (((long) (intptr_t) (h) & 3) == 3)
49521af8
EFL
82
83static BOOL
84IsSocketHandle (HANDLE h)
85{
86 WSANETWORKEVENTS ev;
87
88 if (IsConsoleHandle (h))
89 return FALSE;
90
91 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
92 WSAEnumNetworkEvents instead distinguishes the two correctly. */
93 ev.lNetworkEvents = 0xDEADBEEF;
94 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
95 return ev.lNetworkEvents != 0xDEADBEEF;
96}
97
98/* Declare data structures for ntdll functions. */
99typedef struct _FILE_PIPE_LOCAL_INFORMATION {
100 ULONG NamedPipeType;
101 ULONG NamedPipeConfiguration;
102 ULONG MaximumInstances;
103 ULONG CurrentInstances;
104 ULONG InboundQuota;
105 ULONG ReadDataAvailable;
106 ULONG OutboundQuota;
107 ULONG WriteQuotaAvailable;
108 ULONG NamedPipeState;
109 ULONG NamedPipeEnd;
110} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
111
112typedef struct _IO_STATUS_BLOCK
113{
114 union {
115 DWORD Status;
116 PVOID Pointer;
117 } u;
118 ULONG_PTR Information;
119} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
120
121typedef enum _FILE_INFORMATION_CLASS {
122 FilePipeLocalInformation = 24
123} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
124
125typedef DWORD (WINAPI *PNtQueryInformationFile)
126 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
127
128# ifndef PIPE_BUF
129# define PIPE_BUF 512
130# endif
131
132/* Compute revents values for file handle H. If some events cannot happen
133 for the handle, eliminate them from *P_SOUGHT. */
134
135static int
136win32_compute_revents (HANDLE h, int *p_sought)
137{
138 int i, ret, happened;
139 INPUT_RECORD *irbuffer;
140 DWORD avail, nbuffer;
141 BOOL bRet;
142 IO_STATUS_BLOCK iosb;
143 FILE_PIPE_LOCAL_INFORMATION fpli;
144 static PNtQueryInformationFile NtQueryInformationFile;
145 static BOOL once_only;
146
147 switch (GetFileType (h))
148 {
149 case FILE_TYPE_PIPE:
150 if (!once_only)
151 {
8d4679fe 152 NtQueryInformationFile = (PNtQueryInformationFile)(void (*)(void))
94238859 153 GetProcAddress (GetModuleHandleW (L"ntdll.dll"),
49521af8
EFL
154 "NtQueryInformationFile");
155 once_only = TRUE;
156 }
157
158 happened = 0;
159 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
160 {
161 if (avail)
162 happened |= *p_sought & (POLLIN | POLLRDNORM);
163 }
164 else if (GetLastError () == ERROR_BROKEN_PIPE)
165 happened |= POLLHUP;
166
167 else
168 {
169 /* It was the write-end of the pipe. Check if it is writable.
170 If NtQueryInformationFile fails, optimistically assume the pipe is
171 writable. This could happen on Win9x, where NtQueryInformationFile
172 is not available, or if we inherit a pipe that doesn't permit
173 FILE_READ_ATTRIBUTES access on the write end (I think this should
174 not happen since WinXP SP2; WINE seems fine too). Otherwise,
175 ensure that enough space is available for atomic writes. */
176 memset (&iosb, 0, sizeof (iosb));
177 memset (&fpli, 0, sizeof (fpli));
178
179 if (!NtQueryInformationFile
180 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
181 FilePipeLocalInformation)
182 || fpli.WriteQuotaAvailable >= PIPE_BUF
183 || (fpli.OutboundQuota < PIPE_BUF &&
184 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
185 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
186 }
187 return happened;
188
189 case FILE_TYPE_CHAR:
190 ret = WaitForSingleObject (h, 0);
191 if (!IsConsoleHandle (h))
192 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
193
194 nbuffer = avail = 0;
195 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
196 if (bRet)
197 {
198 /* Input buffer. */
199 *p_sought &= POLLIN | POLLRDNORM;
200 if (nbuffer == 0)
201 return POLLHUP;
202 if (!*p_sought)
203 return 0;
204
205 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
206 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
207 if (!bRet || avail == 0)
208 return POLLHUP;
209
210 for (i = 0; i < avail; i++)
211 if (irbuffer[i].EventType == KEY_EVENT)
212 return *p_sought;
213 return 0;
214 }
215 else
216 {
217 /* Screen buffer. */
218 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
219 return *p_sought;
220 }
221
222 default:
223 ret = WaitForSingleObject (h, 0);
224 if (ret == WAIT_OBJECT_0)
225 return *p_sought & ~(POLLPRI | POLLRDBAND);
226
227 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
228 }
229}
230
231/* Convert fd_sets returned by select into revents values. */
232
233static int
234win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
235{
236 int happened = 0;
237
238 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
239 happened |= (POLLIN | POLLRDNORM) & sought;
240
241 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
242 {
243 int r, error;
244
245 char data[64];
246 WSASetLastError (0);
247 r = recv (h, data, sizeof (data), MSG_PEEK);
248 error = WSAGetLastError ();
249 WSASetLastError (0);
250
251 if (r > 0 || error == WSAENOTCONN)
252 happened |= (POLLIN | POLLRDNORM) & sought;
253
254 /* Distinguish hung-up sockets from other errors. */
255 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
256 || error == WSAECONNABORTED || error == WSAENETRESET)
257 happened |= POLLHUP;
258
259 else
260 happened |= POLLERR;
261 }
262
263 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
264 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
265
266 if (lNetworkEvents & FD_OOB)
267 happened |= (POLLPRI | POLLRDBAND) & sought;
268
269 return happened;
270}
271
272#else /* !MinGW */
273
274/* Convert select(2) returned fd_sets into poll(2) revents values. */
275static int
276compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
277{
278 int happened = 0;
279 if (FD_ISSET (fd, rfds))
280 {
281 int r;
282 int socket_errno;
283
284# if defined __MACH__ && defined __APPLE__
285 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
286 for some kinds of descriptors. Detect if this descriptor is a
287 connected socket, a server socket, or something else using a
288 0-byte recv, and use ioctl(2) to detect POLLHUP. */
289 r = recv (fd, NULL, 0, MSG_PEEK);
290 socket_errno = (r < 0) ? errno : 0;
291 if (r == 0 || socket_errno == ENOTSOCK)
292 ioctl (fd, FIONREAD, &r);
293# else
294 char data[64];
295 r = recv (fd, data, sizeof (data), MSG_PEEK);
296 socket_errno = (r < 0) ? errno : 0;
297# endif
298 if (r == 0)
299 happened |= POLLHUP;
300
301 /* If the event happened on an unconnected server socket,
302 that's fine. */
303 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
304 happened |= (POLLIN | POLLRDNORM) & sought;
305
306 /* Distinguish hung-up sockets from other errors. */
307 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
308 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
309 happened |= POLLHUP;
310
a6772946
JS
311 /* some systems can't use recv() on non-socket, including HP NonStop */
312 else if (/* (r == -1) && */ socket_errno == ENOTSOCK)
313 happened |= (POLLIN | POLLRDNORM) & sought;
314
49521af8
EFL
315 else
316 happened |= POLLERR;
317 }
318
319 if (FD_ISSET (fd, wfds))
320 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
321
322 if (FD_ISSET (fd, efds))
323 happened |= (POLLPRI | POLLRDBAND) & sought;
324
325 return happened;
326}
327#endif /* !MinGW */
328
329int
f0bd6649 330poll (struct pollfd *pfd, nfds_t nfd, int timeout)
49521af8
EFL
331{
332#ifndef WIN32_NATIVE
333 fd_set rfds, wfds, efds;
334 struct timeval tv;
335 struct timeval *ptv;
336 int maxfd, rc;
337 nfds_t i;
338
339# ifdef _SC_OPEN_MAX
340 static int sc_open_max = -1;
341
342 if (nfd < 0
343 || (nfd > sc_open_max
344 && (sc_open_max != -1
345 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
346 {
347 errno = EINVAL;
348 return -1;
349 }
350# else /* !_SC_OPEN_MAX */
351# ifdef OPEN_MAX
352 if (nfd < 0 || nfd > OPEN_MAX)
353 {
354 errno = EINVAL;
355 return -1;
356 }
357# endif /* OPEN_MAX -- else, no check is needed */
358# endif /* !_SC_OPEN_MAX */
359
360 /* EFAULT is not necessary to implement, but let's do it in the
361 simplest case. */
32fde657 362 if (!pfd && nfd)
49521af8
EFL
363 {
364 errno = EFAULT;
365 return -1;
366 }
367
368 /* convert timeout number into a timeval structure */
369 if (timeout == 0)
370 {
371 ptv = &tv;
372 ptv->tv_sec = 0;
373 ptv->tv_usec = 0;
374 }
375 else if (timeout > 0)
376 {
377 ptv = &tv;
378 ptv->tv_sec = timeout / 1000;
379 ptv->tv_usec = (timeout % 1000) * 1000;
380 }
381 else if (timeout == INFTIM)
382 /* wait forever */
383 ptv = NULL;
384 else
385 {
386 errno = EINVAL;
387 return -1;
388 }
389
390 /* create fd sets and determine max fd */
391 maxfd = -1;
392 FD_ZERO (&rfds);
393 FD_ZERO (&wfds);
394 FD_ZERO (&efds);
395 for (i = 0; i < nfd; i++)
396 {
397 if (pfd[i].fd < 0)
398 continue;
399
400 if (pfd[i].events & (POLLIN | POLLRDNORM))
401 FD_SET (pfd[i].fd, &rfds);
402
403 /* see select(2): "the only exceptional condition detectable
404 is out-of-band data received on a socket", hence we push
405 POLLWRBAND events onto wfds instead of efds. */
406 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
407 FD_SET (pfd[i].fd, &wfds);
408 if (pfd[i].events & (POLLPRI | POLLRDBAND))
409 FD_SET (pfd[i].fd, &efds);
410 if (pfd[i].fd >= maxfd
411 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
412 | POLLRDNORM | POLLRDBAND
413 | POLLWRNORM | POLLWRBAND)))
414 {
415 maxfd = pfd[i].fd;
416 if (maxfd > FD_SETSIZE)
417 {
418 errno = EOVERFLOW;
419 return -1;
420 }
421 }
422 }
423
424 /* examine fd sets */
425 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
426 if (rc < 0)
427 return rc;
428
429 /* establish results */
430 rc = 0;
431 for (i = 0; i < nfd; i++)
432 if (pfd[i].fd < 0)
433 pfd[i].revents = 0;
434 else
435 {
436 int happened = compute_revents (pfd[i].fd, pfd[i].events,
437 &rfds, &wfds, &efds);
438 if (happened)
439 {
440 pfd[i].revents = happened;
441 rc++;
442 }
61b2a1ac
RB
443 else
444 {
445 pfd[i].revents = 0;
446 }
49521af8
EFL
447 }
448
449 return rc;
450#else
451 static struct timeval tv0;
452 static HANDLE hEvent;
453 WSANETWORKEVENTS ev;
454 HANDLE h, handle_array[FD_SETSIZE + 2];
e8dfcace
SH
455 DWORD ret, wait_timeout, nhandles, orig_timeout = 0;
456 ULONGLONG start = 0;
49521af8
EFL
457 fd_set rfds, wfds, xfds;
458 BOOL poll_again;
459 MSG msg;
460 int rc = 0;
461 nfds_t i;
462
463 if (nfd < 0 || timeout < -1)
464 {
465 errno = EINVAL;
466 return -1;
467 }
468
ef8b53e7
ET
469 if (timeout != INFTIM)
470 {
471 orig_timeout = timeout;
e8dfcace 472 start = GetTickCount64();
ef8b53e7
ET
473 }
474
49521af8
EFL
475 if (!hEvent)
476 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
477
f0bd6649 478restart:
49521af8
EFL
479 handle_array[0] = hEvent;
480 nhandles = 1;
481 FD_ZERO (&rfds);
482 FD_ZERO (&wfds);
483 FD_ZERO (&xfds);
484
485 /* Classify socket handles and create fd sets. */
486 for (i = 0; i < nfd; i++)
487 {
488 int sought = pfd[i].events;
489 pfd[i].revents = 0;
490 if (pfd[i].fd < 0)
491 continue;
492 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
493 | POLLPRI | POLLRDBAND)))
494 continue;
495
496 h = (HANDLE) _get_osfhandle (pfd[i].fd);
497 assert (h != NULL);
498 if (IsSocketHandle (h))
499 {
500 int requested = FD_CLOSE;
501
502 /* see above; socket handles are mapped onto select. */
503 if (sought & (POLLIN | POLLRDNORM))
504 {
505 requested |= FD_READ | FD_ACCEPT;
506 FD_SET ((SOCKET) h, &rfds);
507 }
508 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
509 {
510 requested |= FD_WRITE | FD_CONNECT;
511 FD_SET ((SOCKET) h, &wfds);
512 }
513 if (sought & (POLLPRI | POLLRDBAND))
514 {
515 requested |= FD_OOB;
516 FD_SET ((SOCKET) h, &xfds);
517 }
518
519 if (requested)
520 WSAEventSelect ((SOCKET) h, hEvent, requested);
521 }
522 else
523 {
524 /* Poll now. If we get an event, do not poll again. Also,
525 screen buffer handles are waitable, and they'll block until
526 a character is available. win32_compute_revents eliminates
527 bits for the "wrong" direction. */
528 pfd[i].revents = win32_compute_revents (h, &sought);
529 if (sought)
530 handle_array[nhandles++] = h;
531 if (pfd[i].revents)
532 timeout = 0;
533 }
534 }
535
536 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
537 {
538 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
539 no need to call select again. */
540 poll_again = FALSE;
541 wait_timeout = 0;
542 }
543 else
544 {
545 poll_again = TRUE;
546 if (timeout == INFTIM)
547 wait_timeout = INFINITE;
548 else
549 wait_timeout = timeout;
550 }
551
552 for (;;)
553 {
554 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
555 wait_timeout, QS_ALLINPUT);
556
557 if (ret == WAIT_OBJECT_0 + nhandles)
558 {
559 /* new input of some other kind */
560 BOOL bRet;
561 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
562 {
563 TranslateMessage (&msg);
564 DispatchMessage (&msg);
565 }
566 }
567 else
568 break;
569 }
570
571 if (poll_again)
572 select (0, &rfds, &wfds, &xfds, &tv0);
573
574 /* Place a sentinel at the end of the array. */
575 handle_array[nhandles] = NULL;
576 nhandles = 1;
577 for (i = 0; i < nfd; i++)
578 {
579 int happened;
580
581 if (pfd[i].fd < 0)
582 continue;
583 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
584 POLLOUT | POLLWRNORM | POLLWRBAND)))
585 continue;
586
587 h = (HANDLE) _get_osfhandle (pfd[i].fd);
588 if (h != handle_array[nhandles])
589 {
590 /* It's a socket. */
591 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
1c31596a 592 WSAEventSelect ((SOCKET) h, NULL, 0);
49521af8
EFL
593
594 /* If we're lucky, WSAEnumNetworkEvents already provided a way
595 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
596 if (FD_ISSET ((SOCKET) h, &rfds)
597 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
598 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
599 if (FD_ISSET ((SOCKET) h, &wfds))
600 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
601 if (FD_ISSET ((SOCKET) h, &xfds))
602 ev.lNetworkEvents |= FD_OOB;
603
604 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
605 ev.lNetworkEvents);
606 }
607 else
608 {
609 /* Not a socket. */
610 int sought = pfd[i].events;
611 happened = win32_compute_revents (h, &sought);
612 nhandles++;
613 }
614
615 if ((pfd[i].revents |= happened) != 0)
616 rc++;
617 }
618
ef8b53e7
ET
619 if (!rc && orig_timeout && timeout != INFTIM)
620 {
e8dfcace
SH
621 ULONGLONG elapsed = GetTickCount64() - start;
622 timeout = elapsed >= orig_timeout ? 0 : (int)(orig_timeout - elapsed);
ef8b53e7
ET
623 }
624
625 if (!rc && timeout)
f0bd6649 626 {
76e7c8a7 627 SleepEx (1, TRUE);
f0bd6649
EFL
628 goto restart;
629 }
630
49521af8
EFL
631 return rc;
632#endif
633}