]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/bsd/poll.c
1 /* Copyright (C) 1994-2013 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
20 #include <sys/types.h>
24 #include <sys/param.h>
27 /* Poll the file descriptors described by the NFDS structures starting at
28 FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
29 an event to occur; if TIMEOUT is -1, block until an event occurs.
30 Returns the number of file descriptors with events, zero if timed out,
34 __poll (fds
, nfds
, timeout
)
39 static int max_fd_size
;
41 fd_set
*rset
, *wset
, *xset
;
48 max_fd_size
= __getdtablesize ();
50 bytes
= howmany (max_fd_size
, __NFDBITS
);
51 rset
= alloca (bytes
);
52 wset
= alloca (bytes
);
53 xset
= alloca (bytes
);
55 /* We can't call FD_ZERO, since FD_ZERO only works with sets
56 of exactly __FD_SETSIZE size. */
57 __bzero (rset
, bytes
);
58 __bzero (wset
, bytes
);
59 __bzero (xset
, bytes
);
61 for (f
= fds
; f
< &fds
[nfds
]; ++f
)
66 if (f
->fd
>= max_fd_size
)
68 /* The user provides a file descriptor number which is higher
69 than the maximum we got from the `getdtablesize' call.
70 Maybe this is ok so enlarge the arrays. */
71 fd_set
*nrset
, *nwset
, *nxset
;
74 max_fd_size
= roundup (f
->fd
, __NFDBITS
);
75 nbytes
= howmany (max_fd_size
, __NFDBITS
);
77 nrset
= alloca (nbytes
);
78 nwset
= alloca (nbytes
);
79 nxset
= alloca (nbytes
);
81 __bzero ((char *) nrset
+ bytes
, nbytes
- bytes
);
82 __bzero ((char *) nwset
+ bytes
, nbytes
- bytes
);
83 __bzero ((char *) nxset
+ bytes
, nbytes
- bytes
);
85 rset
= memcpy (nrset
, rset
, bytes
);
86 wset
= memcpy (nwset
, wset
, bytes
);
87 xset
= memcpy (nxset
, xset
, bytes
);
92 if (f
->events
& POLLIN
)
94 if (f
->events
& POLLOUT
)
96 if (f
->events
& POLLPRI
)
98 if (f
->fd
> maxfd
&& (f
->events
& (POLLIN
|POLLOUT
|POLLPRI
)))
103 tv
.tv_sec
= timeout
/ 1000;
104 tv
.tv_usec
= (timeout
% 1000) * 1000;
108 ready
= __select (maxfd
+ 1, rset
, wset
, xset
,
109 timeout
== -1 ? NULL
: &tv
);
111 /* It might be that one or more of the file descriptors is invalid.
112 We now try to find and mark them and then try again. */
113 if (ready
== -1 && errno
== EBADF
)
115 fd_set
*sngl_rset
= alloca (bytes
);
116 fd_set
*sngl_wset
= alloca (bytes
);
117 fd_set
*sngl_xset
= alloca (bytes
);
118 struct timeval sngl_tv
;
120 /* Clear the original set. */
121 __bzero (rset
, bytes
);
122 __bzero (wset
, bytes
);
123 __bzero (xset
, bytes
);
125 /* This means we don't wait for input. */
131 /* Reset the return value. */
134 for (f
= fds
; f
< &fds
[nfds
]; ++f
)
135 if (f
->fd
!= -1 && (f
->events
& (POLLIN
|POLLOUT
|POLLPRI
))
136 && (f
->revents
& POLLNVAL
) == 0)
140 __bzero (sngl_rset
, bytes
);
141 __bzero (sngl_wset
, bytes
);
142 __bzero (sngl_xset
, bytes
);
144 if (f
->events
& POLLIN
)
145 FD_SET (f
->fd
, sngl_rset
);
146 if (f
->events
& POLLOUT
)
147 FD_SET (f
->fd
, sngl_wset
);
148 if (f
->events
& POLLPRI
)
149 FD_SET (f
->fd
, sngl_xset
);
151 n
= __select (f
->fd
+ 1, sngl_rset
, sngl_wset
, sngl_xset
,
155 /* This descriptor is ok. */
156 if (f
->events
& POLLIN
)
157 FD_SET (f
->fd
, rset
);
158 if (f
->events
& POLLOUT
)
159 FD_SET (f
->fd
, wset
);
160 if (f
->events
& POLLPRI
)
161 FD_SET (f
->fd
, xset
);
165 /* Count it as being available. */
168 else if (errno
== EBADF
)
169 f
->revents
|= POLLNVAL
;
179 for (f
= fds
; f
< &fds
[nfds
]; ++f
)
183 if (FD_ISSET (f
->fd
, rset
))
184 f
->revents
|= POLLIN
;
185 if (FD_ISSET (f
->fd
, wset
))
186 f
->revents
|= POLLOUT
;
187 if (FD_ISSET (f
->fd
, xset
))
188 f
->revents
|= POLLPRI
;
195 libc_hidden_def (__poll
)
196 weak_alias (__poll
, poll
)