poll.c
Upload User: kjfoods
Upload Date: 2020-07-06
Package Size: 29949k
Code Size: 4k
Category:

midi program

Development Platform:

Unix_Linux

  1. /*****************************************************************************
  2.  * poll.c: I/O event multiplexing
  3.  *****************************************************************************
  4.  * Copyright © 2007 Rémi Denis-Courmont
  5.  * $Id: cf9554a30ab687c453425985cf52f6a025b24820 $
  6.  *
  7.  * Author: Rémi Denis-Courmont
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) 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 General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. #ifdef HAVE_CONFIG_H
  24. # include "config.h"
  25. #endif
  26. #include <vlc_common.h>
  27. #include <stdlib.h>
  28. #include <vlc_network.h>
  29. #ifdef HAVE_POLL
  30. struct pollfd;
  31. int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
  32. {
  33.     (void)fds; (void)nfds; (void)timeout;
  34.     abort ();
  35. }
  36. #else /* !HAVE_POLL */
  37. #include <string.h>
  38. int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
  39. {
  40.     fd_set rdset, wrset, exset;
  41.     struct timeval tv = { 0, 0 };
  42.     int val;
  43. resume:
  44.     val = -1;
  45.     vlc_testcancel ();
  46.     FD_ZERO (&rdset);
  47.     FD_ZERO (&wrset);
  48.     FD_ZERO (&exset);
  49.     for (unsigned i = 0; i < nfds; i++)
  50.     {
  51.         int fd = fds[i].fd;
  52.         if (val < fd)
  53.             val = fd;
  54.         /* With POSIX, FD_SET & FD_ISSET are not defined if fd is negative or
  55.  * bigger or equal than FD_SETSIZE. That is one of the reasons why VLC
  56.  * uses poll() rather than select(). Most POSIX systems implement
  57.  * fd_set has a bit field with no sanity checks. This is especially bad
  58.  * on systems (such as BSD) that have no process open files limit by
  59.  * default, such that it is quite feasible to get fd >= FD_SETSIZE.
  60.  * The next instructions will result in a buffer overflow if run on
  61.  * a POSIX system, and the later FD_ISSET will do undefined memory
  62.  * access.
  63.  *
  64.  * With Winsock, fd_set is a table of integers. This is awfully slow.
  65.  * However, FD_SET and FD_ISSET silently and safely discard
  66.  * overflows. If it happens we will loose socket events. Note that
  67.  * most (if not all) Winsock SOCKET handles are actually bigger than
  68.  * FD_SETSIZE in terms of absolute value - they are not POSIX file
  69.  * descriptors. From Vista, there is a much nicer WSAPoll(), but Mingw
  70.  * is yet to support it.
  71.  *
  72.  * With BeOS, the situation is unknown (FIXME: document).
  73.  */
  74.         if (fds[i].events & POLLIN)
  75.             FD_SET (fd, &rdset);
  76.         if (fds[i].events & POLLOUT)
  77.             FD_SET (fd, &wrset);
  78.         if (fds[i].events & POLLPRI)
  79.             FD_SET (fd, &exset);
  80.     }
  81. #ifndef HAVE_ALERTABLE_SELECT
  82. # warning FIXME! Fix cancellation and remove this crap.
  83.     if ((timeout < 0) || (timeout > 50))
  84.     {
  85.         tv.tv_sec = 0;
  86.         tv.tv_usec = 50000;
  87.     }
  88.     else
  89. #endif
  90.     if (timeout >= 0)
  91.     {
  92.         div_t d = div (timeout, 1000);
  93.         tv.tv_sec = d.quot;
  94.         tv.tv_usec = d.rem * 1000;
  95.     }
  96.     val = select (val + 1, &rdset, &wrset, &exset,
  97.                   /*(timeout >= 0) ?*/ &tv /*: NULL*/);
  98. #ifndef HAVE_ALERTABLE_SELECT
  99.     if (val == 0)
  100.     {
  101.         if (timeout > 0)
  102.             timeout -= (timeout > 50) ? 50 : timeout;
  103.         if (timeout != 0)
  104.             goto resume;
  105.     }
  106. #endif
  107.     if (val == -1)
  108.         return -1;
  109.     for (unsigned i = 0; i < nfds; i++)
  110.     {
  111.         int fd = fds[i].fd;
  112.         fds[i].revents = (FD_ISSET (fd, &rdset) ? POLLIN : 0)
  113.                        | (FD_ISSET (fd, &wrset) ? POLLOUT : 0)
  114.                        | (FD_ISSET (fd, &exset) ? POLLPRI : 0);
  115.     }
  116.     return val;
  117. }
  118. #endif /* !HAVE_POLL */