poll.c
Go to the documentation of this file.
1 /* Copyright (C) 1994, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
2  This file is part of the GNU C Library.
3 
4  The GNU C Library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public License as
6  published by the Free Software Foundation; either version 2 of the
7  License, or (at your option) any later version.
8 
9  The GNU C Library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public
15  License along with the GNU C Library; see the file COPYING.LIB. If not,
16  write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  Boston, MA 02111-1307, USA. */
18 
19 /*
20  * $Id: poll.c,v 1.1 2002-12-05 01:50:22 rtv Exp $
21  *
22  * taken from glibc, modified slightly for standalone compilation, and used as
23  * a fallback implementation when poll() is not available. - BPG
24  */
25 
26 #include "replace.h"
27 
28 //#include <alloca.h>
29 #include <sys/types.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <sys/time.h>
33 #include <sys/param.h>
34 #include <unistd.h>
35 
36 /* Poll the file descriptors described by the NFDS structures starting at
37  FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
38  an event to occur; if TIMEOUT is -1, block until an event occurs.
39  Returns the number of file descriptors with events, zero if timed out,
40  or -1 for errors. */
41 
42 int
43 poll(struct pollfd* fds, unsigned long int nfds, int timeout)
44 {
45  static int max_fd_size;
46  struct timeval tv;
47  fd_set *rset, *wset, *xset;
48  struct pollfd *f;
49  int ready;
50  int maxfd = 0;
51  int bytes;
52 
53  if (!max_fd_size)
54  max_fd_size = getdtablesize ();
55 
56  bytes = howmany (max_fd_size, NFDBITS);
57  rset = alloca (bytes);
58  wset = alloca (bytes);
59  xset = alloca (bytes);
60 
61  /* We can't call FD_ZERO, since FD_ZERO only works with sets
62  of exactly FD_SETSIZE size. */
63  bzero (rset, bytes);
64  bzero (wset, bytes);
65  bzero (xset, bytes);
66 
67  for (f = fds; f < &fds[nfds]; ++f)
68  {
69  f->revents = 0;
70  if (f->fd >= 0)
71  {
72  if (f->fd >= max_fd_size)
73  {
74  /* The user provides a file descriptor number which is higher
75  than the maximum we got from the `getdtablesize' call.
76  Maybe this is ok so enlarge the arrays. */
77  fd_set *nrset, *nwset, *nxset;
78  int nbytes;
79 
80  max_fd_size = roundup (f->fd, NFDBITS);
81  nbytes = howmany (max_fd_size, NFDBITS);
82 
83  nrset = alloca (nbytes);
84  nwset = alloca (nbytes);
85  nxset = alloca (nbytes);
86 
87  bzero ((char *) nrset + bytes, nbytes - bytes);
88  bzero ((char *) nwset + bytes, nbytes - bytes);
89  bzero ((char *) nxset + bytes, nbytes - bytes);
90 
91  rset = memcpy (nrset, rset, bytes);
92  wset = memcpy (nwset, wset, bytes);
93  xset = memcpy (nxset, xset, bytes);
94 
95  bytes = nbytes;
96  }
97 
98  if (f->events & POLLIN)
99  FD_SET (f->fd, rset);
100  if (f->events & POLLOUT)
101  FD_SET (f->fd, wset);
102  if (f->events & POLLPRI)
103  FD_SET (f->fd, xset);
104  if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
105  maxfd = f->fd;
106  }
107  }
108 
109  tv.tv_sec = timeout / 1000;
110  tv.tv_usec = (timeout % 1000) * 1000;
111 
112  while (1)
113  {
114  ready = select (maxfd + 1, rset, wset, xset,
115  timeout == -1 ? NULL : &tv);
116 
117  /* It might be that one or more of the file descriptors is invalid.
118  We now try to find and mark them and then try again. */
119  if (ready == -1 && errno == EBADF)
120  {
121  fd_set *sngl_rset = alloca (bytes);
122  fd_set *sngl_wset = alloca (bytes);
123  fd_set *sngl_xset = alloca (bytes);
124  struct timeval sngl_tv;
125 
126  /* Clear the original set. */
127  bzero (rset, bytes);
128  bzero (wset, bytes);
129  bzero (xset, bytes);
130 
131  /* This means we don't wait for input. */
132  sngl_tv.tv_sec = 0;
133  sngl_tv.tv_usec = 0;
134 
135  maxfd = -1;
136 
137  /* Reset the return value. */
138  ready = 0;
139 
140  for (f = fds; f < &fds[nfds]; ++f)
141  if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
142  && (f->revents & POLLNVAL) == 0)
143  {
144  int n;
145 
146  bzero (sngl_rset, bytes);
147  bzero (sngl_wset, bytes);
148  bzero (sngl_xset, bytes);
149 
150  if (f->events & POLLIN)
151  FD_SET (f->fd, sngl_rset);
152  if (f->events & POLLOUT)
153  FD_SET (f->fd, sngl_wset);
154  if (f->events & POLLPRI)
155  FD_SET (f->fd, sngl_xset);
156 
157  n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
158  &sngl_tv);
159  if (n != -1)
160  {
161  /* This descriptor is ok. */
162  if (f->events & POLLIN)
163  FD_SET (f->fd, rset);
164  if (f->events & POLLOUT)
165  FD_SET (f->fd, wset);
166  if (f->events & POLLPRI)
167  FD_SET (f->fd, xset);
168  if (f->fd > maxfd)
169  maxfd = f->fd;
170  if (n > 0)
171  /* Count it as being available. */
172  ++ready;
173  }
174  else if (errno == EBADF)
175  f->revents |= POLLNVAL;
176  }
177  /* Try again. */
178  continue;
179  }
180 
181  break;
182  }
183 
184  if (ready > 0)
185  for (f = fds; f < &fds[nfds]; ++f)
186  {
187  if (f->fd >= 0)
188  {
189  if (FD_ISSET (f->fd, rset))
190  f->revents |= POLLIN;
191  if (FD_ISSET (f->fd, wset))
192  f->revents |= POLLOUT;
193  if (FD_ISSET (f->fd, xset))
194  f->revents |= POLLPRI;
195  }
196  }
197 
198  return ready;
199 }
#define POLLNVAL
Definition: replace.h:55
#define POLLPRI
Definition: replace.h:42
int poll(struct pollfd *fds, unsigned long int nfds, int timeout)
Definition: poll.c:43
#define POLLOUT
Definition: replace.h:43
#define POLLIN
Definition: replace.h:41
Definition: replace.h:61
int fd
Definition: replace.h:63
short int events
Definition: replace.h:64
short int revents
Definition: replace.h:65


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 Mon Jun 10 2019 15:06:09