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