This is the mail archive of the libc-alpha@cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

poll emulation



 I'm working on a program that needs to be able to run on 2.0.x and
2.2.x kernels so although I'm using poll internally I need the
emulation to work as full as possible.
 At the moment everything fails if you have an fd in your poll set
that is invalid (select return -1 and sets errno == EBADF, where poll
will just set a flag in the poll structure for that fd).
 So here is an addition to the poll emulation inside glibc, this was
written as an add on to glibc-2.0.x so I'll have to do a little more
work to generate a patch against 2.1.x but you'll get the idea and
hopefully someone will be able to tell me it will go in/it'll never go 
in.

/* Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

/* Poll the file descriptors described by the NFDS structures starting at
   FDS.  If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
   an event to occur; if TIMEOUT is -1, block until an event occurs.
   Returns the number of file descriptors with events, zero if timed out,
   or -1 for errors.  */

int
poll (fds, nfds, timeout)
     struct pollfd *fds;
     unsigned long int nfds;
     int timeout;
{
 struct timeval tv;
 fd_set rset, wset, xset;
 struct pollfd *f;
 int ready;
 int maxfd = 0;
 
 FD_ZERO (&rset);
 FD_ZERO (&wset);
 FD_ZERO (&xset);
 
 for (f = fds; f < &fds[nfds]; ++f)
   if (f->fd != -1)
   {
    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;
 
 ready = select (maxfd + 1, &rset, &wset, &xset,
                 timeout == -1 ? NULL : &tv);
 if ((ready == -1) && (errno == EBADF))
 {
  ready = 0;
  
  FD_ZERO (&rset);
  FD_ZERO (&wset);
  FD_ZERO (&xset);

  maxfd = -1;
  
  for (f = fds; f < &fds[nfds]; ++f)
    if (f->fd != -1)
    {
     fd_set sngl_rset, sngl_wset, sngl_xset;
     
     FD_ZERO (&sngl_rset);
     FD_ZERO (&sngl_wset);
     FD_ZERO (&sngl_xset);
     
     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);
     if (f->events & (POLLIN|POLLOUT|POLLPRI))
     {
      struct timeval singl_tv;

      singl_tv.tv_sec = 0;
      singl_tv.tv_usec = 0;

      if (select(f->fd, &rset, &wset, &xset, &singl_tv) != -1)
      {
       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;
       ++ready;
      }
      else if (errno == EBADF)
        f->revents |= POLLNVAL;
     }
    }

  if (ready)
  { /* Linux alters the tv struct... but it shouldn't matter here ...
     * as we're going to be a little bit out anyway as we've just eaten
     * more than a couple of cpu cycles above */
   ready = select (maxfd + 1, &rset, &wset, &xset,
                   timeout == -1 ? NULL : &tv);
  }
 }
 
 if (ready > 0)
   for (f = fds; f < &fds[nfds]; ++f)
   {
    f->revents = 0;
    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;
}
#endif


-- 
James Antill -- james@and.org
If you go to the Third World and find 100 people who have never tasted ketchup
before, you find out two things: one is that people don't actually like tomato
ketchup, the other is that they dislike all ketchups equally. -- Rob Young.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]