poll.c
Go to the documentation of this file.
00001 /* Copyright (C) 1994, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public License as
00006    published by the Free Software Foundation; either version 2 of the
00007    License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public
00015    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00016    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.  */
00018 
00019 /*
00020  * $Id: poll.c,v 1.1 2002-12-05 01:50:22 rtv Exp $
00021  *
00022  * taken from glibc, modified slightly for standalone compilation, and used as
00023  * a fallback implementation when poll() is not available. - BPG
00024  */
00025 
00026 #include "replace.h"
00027 
00028 //#include <alloca.h>
00029 #include <sys/types.h>
00030 #include <errno.h>
00031 #include <string.h>
00032 #include <sys/time.h>
00033 #include <sys/param.h>
00034 #include <unistd.h>
00035 
00036 /* Poll the file descriptors described by the NFDS structures starting at
00037    FDS.  If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
00038    an event to occur; if TIMEOUT is -1, block until an event occurs.
00039    Returns the number of file descriptors with events, zero if timed out,
00040    or -1 for errors.  */
00041 
00042 int
00043 poll(struct pollfd* fds, unsigned long int nfds, int timeout)
00044 {
00045   static int max_fd_size;
00046   struct timeval tv;
00047   fd_set *rset, *wset, *xset;
00048   struct pollfd *f;
00049   int ready;
00050   int maxfd = 0;
00051   int bytes;
00052 
00053   if (!max_fd_size)
00054     max_fd_size = getdtablesize ();
00055 
00056   bytes = howmany (max_fd_size, NFDBITS);
00057   rset = alloca (bytes);
00058   wset = alloca (bytes);
00059   xset = alloca (bytes);
00060 
00061   /* We can't call FD_ZERO, since FD_ZERO only works with sets
00062      of exactly FD_SETSIZE size.  */
00063   bzero (rset, bytes);
00064   bzero (wset, bytes);
00065   bzero (xset, bytes);
00066 
00067   for (f = fds; f < &fds[nfds]; ++f)
00068     {
00069       f->revents = 0;
00070       if (f->fd >= 0)
00071         {
00072           if (f->fd >= max_fd_size)
00073             {
00074               /* The user provides a file descriptor number which is higher
00075                  than the maximum we got from the `getdtablesize' call.
00076                  Maybe this is ok so enlarge the arrays.  */
00077               fd_set *nrset, *nwset, *nxset;
00078               int nbytes;
00079 
00080               max_fd_size = roundup (f->fd, NFDBITS);
00081               nbytes = howmany (max_fd_size, NFDBITS);
00082 
00083               nrset = alloca (nbytes);
00084               nwset = alloca (nbytes);
00085               nxset = alloca (nbytes);
00086 
00087               bzero ((char *) nrset + bytes, nbytes - bytes);
00088               bzero ((char *) nwset + bytes, nbytes - bytes);
00089               bzero ((char *) nxset + bytes, nbytes - bytes);
00090 
00091               rset = memcpy (nrset, rset, bytes);
00092               wset = memcpy (nwset, wset, bytes);
00093               xset = memcpy (nxset, xset, bytes);
00094 
00095               bytes = nbytes;
00096             }
00097 
00098           if (f->events & POLLIN)
00099             FD_SET (f->fd, rset);
00100           if (f->events & POLLOUT)
00101             FD_SET (f->fd, wset);
00102           if (f->events & POLLPRI)
00103             FD_SET (f->fd, xset);
00104           if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
00105             maxfd = f->fd;
00106         }
00107     }
00108 
00109   tv.tv_sec = timeout / 1000;
00110   tv.tv_usec = (timeout % 1000) * 1000;
00111 
00112   while (1)
00113     {
00114       ready = select (maxfd + 1, rset, wset, xset,
00115                         timeout == -1 ? NULL : &tv);
00116 
00117       /* It might be that one or more of the file descriptors is invalid.
00118          We now try to find and mark them and then try again.  */
00119       if (ready == -1 && errno == EBADF)
00120         {
00121           fd_set *sngl_rset = alloca (bytes);
00122           fd_set *sngl_wset = alloca (bytes);
00123           fd_set *sngl_xset = alloca (bytes);
00124           struct timeval sngl_tv;
00125 
00126           /* Clear the original set.  */
00127           bzero (rset, bytes);
00128           bzero (wset, bytes);
00129           bzero (xset, bytes);
00130 
00131           /* This means we don't wait for input.  */
00132           sngl_tv.tv_sec = 0;
00133           sngl_tv.tv_usec = 0;
00134 
00135           maxfd = -1;
00136 
00137           /* Reset the return value.  */
00138           ready = 0;
00139 
00140           for (f = fds; f < &fds[nfds]; ++f)
00141             if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
00142                 && (f->revents & POLLNVAL) == 0)
00143               {
00144                 int n;
00145 
00146                 bzero (sngl_rset, bytes);
00147                 bzero (sngl_wset, bytes);
00148                 bzero (sngl_xset, bytes);
00149 
00150                 if (f->events & POLLIN)
00151                   FD_SET (f->fd, sngl_rset);
00152                 if (f->events & POLLOUT)
00153                   FD_SET (f->fd, sngl_wset);
00154                 if (f->events & POLLPRI)
00155                   FD_SET (f->fd, sngl_xset);
00156 
00157                 n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
00158                               &sngl_tv);
00159                 if (n != -1)
00160                   {
00161                     /* This descriptor is ok.  */
00162                     if (f->events & POLLIN)
00163                       FD_SET (f->fd, rset);
00164                     if (f->events & POLLOUT)
00165                       FD_SET (f->fd, wset);
00166                     if (f->events & POLLPRI)
00167                       FD_SET (f->fd, xset);
00168                     if (f->fd > maxfd)
00169                       maxfd = f->fd;
00170                     if (n > 0)
00171                       /* Count it as being available.  */
00172                       ++ready;
00173                   }
00174                 else if (errno == EBADF)
00175                   f->revents |= POLLNVAL;
00176               }
00177           /* Try again.  */
00178           continue;
00179         }
00180 
00181       break;
00182     }
00183 
00184   if (ready > 0)
00185     for (f = fds; f < &fds[nfds]; ++f)
00186       {
00187         if (f->fd >= 0)
00188           {
00189             if (FD_ISSET (f->fd, rset))
00190               f->revents |= POLLIN;
00191             if (FD_ISSET (f->fd, wset))
00192               f->revents |= POLLOUT;
00193             if (FD_ISSET (f->fd, xset))
00194               f->revents |= POLLPRI;
00195           }
00196       }
00197 
00198   return ready;
00199 }


stage
Author(s): Richard Vaughan , Brian Gerkey , Reed Hedges , Andrew Howard , Toby Collett , Pooya Karimian , Jeremy Asher , Alex Couture-Beil , Geoff Biggs , Rich Mattes , Abbas Sadat
autogenerated on Thu Aug 27 2015 15:20:57