Back to index

glibc  2.9
Functions
poll.c File Reference
#include <alloca.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/param.h>
#include <unistd.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int __poll (struct pollfd *fds, nfds_t nfds, int timeout)

Function Documentation

int __poll ( struct pollfd fds,
nfds_t  nfds,
int  timeout 
)

Definition at line 36 of file poll.c.

{
  static int max_fd_size;
  struct timeval tv;
  fd_set *rset, *wset, *xset;
  struct pollfd *f;
  int ready;
  int maxfd = 0;
  int bytes;

  if (!max_fd_size)
    max_fd_size = __getdtablesize ();

  bytes = howmany (max_fd_size, __NFDBITS);
  rset = alloca (bytes);
  wset = alloca (bytes);
  xset = alloca (bytes);

  /* We can't call FD_ZERO, since FD_ZERO only works with sets
     of exactly __FD_SETSIZE size.  */
  __bzero (rset, bytes);
  __bzero (wset, bytes);
  __bzero (xset, bytes);

  for (f = fds; f < &fds[nfds]; ++f)
    {
      f->revents = 0;
      if (f->fd >= 0)
       {
         if (f->fd >= max_fd_size)
           {
             /* The user provides a file descriptor number which is higher
               than the maximum we got from the `getdtablesize' call.
               Maybe this is ok so enlarge the arrays.  */
             fd_set *nrset, *nwset, *nxset;
             int nbytes;

             max_fd_size = roundup (f->fd, __NFDBITS);
             nbytes = howmany (max_fd_size, __NFDBITS);

             nrset = alloca (nbytes);
             nwset = alloca (nbytes);
             nxset = alloca (nbytes);

             __bzero ((char *) nrset + bytes, nbytes - bytes);
             __bzero ((char *) nwset + bytes, nbytes - bytes);
             __bzero ((char *) nxset + bytes, nbytes - bytes);

             rset = memcpy (nrset, rset, bytes);
             wset = memcpy (nwset, wset, bytes);
             xset = memcpy (nxset, xset, bytes);

             bytes = nbytes;
           }

         if (f->events & POLLIN)
           FD_SET (f->fd, rset);
         if (f->events & POLLOUT)
           FD_SET (f->fd, wset);
         if (f->events & POLLPRI)
           FD_SET (f->fd, xset);
         if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
           maxfd = f->fd;
       }
    }

  tv.tv_sec = timeout / 1000;
  tv.tv_usec = (timeout % 1000) * 1000;

  while (1)
    {
      ready = __select (maxfd + 1, rset, wset, xset,
                     timeout == -1 ? NULL : &tv);

      /* It might be that one or more of the file descriptors is invalid.
        We now try to find and mark them and then try again.  */
      if (ready == -1 && errno == EBADF)
       {
         fd_set *sngl_rset = alloca (bytes);
         fd_set *sngl_wset = alloca (bytes);
         fd_set *sngl_xset = alloca (bytes);
         struct timeval sngl_tv;

         /* Clear the original set.  */
         __bzero (rset, bytes);
         __bzero (wset, bytes);
         __bzero (xset, bytes);

         /* This means we don't wait for input.  */
         sngl_tv.tv_sec = 0;
         sngl_tv.tv_usec = 0;

         maxfd = -1;

         /* Reset the return value.  */
         ready = 0;

         for (f = fds; f < &fds[nfds]; ++f)
           if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
              && (f->revents & POLLNVAL) == 0)
             {
              int n;

              __bzero (sngl_rset, bytes);
              __bzero (sngl_wset, bytes);
              __bzero (sngl_xset, bytes);

              if (f->events & POLLIN)
                FD_SET (f->fd, sngl_rset);
              if (f->events & POLLOUT)
                FD_SET (f->fd, sngl_wset);
              if (f->events & POLLPRI)
                FD_SET (f->fd, sngl_xset);

              n = __select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
                           &sngl_tv);
              if (n != -1)
                {
                  /* This descriptor is ok.  */
                  if (f->events & POLLIN)
                    FD_SET (f->fd, rset);
                  if (f->events & POLLOUT)
                    FD_SET (f->fd, wset);
                  if (f->events & POLLPRI)
                    FD_SET (f->fd, xset);
                  if (f->fd > maxfd)
                    maxfd = f->fd;
                  if (n > 0)
                    /* Count it as being available.  */
                    ++ready;
                }
              else if (errno == EBADF)
                f->revents |= POLLNVAL;
             }
         /* Try again.  */
         continue;
       }

      break;
    }

  if (ready > 0)
    for (f = fds; f < &fds[nfds]; ++f)
      {
       if (f->fd >= 0)
         {
           if (FD_ISSET (f->fd, rset))
             f->revents |= POLLIN;
           if (FD_ISSET (f->fd, wset))
             f->revents |= POLLOUT;
           if (FD_ISSET (f->fd, xset))
             f->revents |= POLLPRI;
         }
      }

  return ready;
}

Here is the call graph for this function:

Here is the caller graph for this function: