]>
Commit | Line | Data |
---|---|---|
568035b7 | 1 | /* Copyright (C) 1994-2013 Free Software Foundation, Inc. |
df4ef2ab | 2 | This file is part of the GNU C Library. |
28f540f4 | 3 | |
df4ef2ab | 4 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
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. | |
28f540f4 | 8 | |
df4ef2ab UD |
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 | |
41bdb6e2 | 12 | Lesser General Public License for more details. |
28f540f4 | 13 | |
41bdb6e2 | 14 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
15 | License along with the GNU C Library; if not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
28f540f4 | 17 | |
ba9234d9 | 18 | #include <alloca.h> |
28f540f4 RM |
19 | #include <sys/poll.h> |
20 | #include <sys/types.h> | |
21 | #include <errno.h> | |
22 | #include <string.h> | |
23 | #include <sys/time.h> | |
ba9234d9 UD |
24 | #include <sys/param.h> |
25 | #include <unistd.h> | |
28f540f4 RM |
26 | |
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, | |
31 | or -1 for errors. */ | |
32 | ||
33 | int | |
bfc73ba2 | 34 | __poll (fds, nfds, timeout) |
28f540f4 | 35 | struct pollfd *fds; |
3eee1304 | 36 | nfds_t nfds; |
28f540f4 RM |
37 | int timeout; |
38 | { | |
ba9234d9 | 39 | static int max_fd_size; |
28f540f4 | 40 | struct timeval tv; |
ba9234d9 | 41 | fd_set *rset, *wset, *xset; |
28f540f4 RM |
42 | struct pollfd *f; |
43 | int ready; | |
44 | int maxfd = 0; | |
ba9234d9 | 45 | int bytes; |
28f540f4 | 46 | |
ba9234d9 UD |
47 | if (!max_fd_size) |
48 | max_fd_size = __getdtablesize (); | |
49 | ||
50 | bytes = howmany (max_fd_size, __NFDBITS); | |
51 | rset = alloca (bytes); | |
52 | wset = alloca (bytes); | |
53 | xset = alloca (bytes); | |
54 | ||
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); | |
28f540f4 RM |
60 | |
61 | for (f = fds; f < &fds[nfds]; ++f) | |
62acd376 UD |
62 | { |
63 | f->revents = 0; | |
64 | if (f->fd >= 0) | |
65 | { | |
66 | if (f->fd >= max_fd_size) | |
67 | { | |
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; | |
72 | int nbytes; | |
73 | ||
74 | max_fd_size = roundup (f->fd, __NFDBITS); | |
75 | nbytes = howmany (max_fd_size, __NFDBITS); | |
76 | ||
77 | nrset = alloca (nbytes); | |
78 | nwset = alloca (nbytes); | |
79 | nxset = alloca (nbytes); | |
80 | ||
81 | __bzero ((char *) nrset + bytes, nbytes - bytes); | |
82 | __bzero ((char *) nwset + bytes, nbytes - bytes); | |
83 | __bzero ((char *) nxset + bytes, nbytes - bytes); | |
84 | ||
85 | rset = memcpy (nrset, rset, bytes); | |
86 | wset = memcpy (nwset, wset, bytes); | |
87 | xset = memcpy (nxset, xset, bytes); | |
88 | ||
89 | bytes = nbytes; | |
90 | } | |
91 | ||
92 | if (f->events & POLLIN) | |
93 | FD_SET (f->fd, rset); | |
94 | if (f->events & POLLOUT) | |
95 | FD_SET (f->fd, wset); | |
96 | if (f->events & POLLPRI) | |
97 | FD_SET (f->fd, xset); | |
98 | if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) | |
99 | maxfd = f->fd; | |
100 | } | |
101 | } | |
28f540f4 RM |
102 | |
103 | tv.tv_sec = timeout / 1000; | |
522548fb | 104 | tv.tv_usec = (timeout % 1000) * 1000; |
28f540f4 | 105 | |
b02f5013 | 106 | while (1) |
62acd376 UD |
107 | { |
108 | ready = __select (maxfd + 1, rset, wset, xset, | |
109 | timeout == -1 ? NULL : &tv); | |
110 | ||
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) | |
114 | { | |
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; | |
119 | ||
120 | /* Clear the original set. */ | |
121 | __bzero (rset, bytes); | |
122 | __bzero (wset, bytes); | |
123 | __bzero (xset, bytes); | |
124 | ||
125 | /* This means we don't wait for input. */ | |
126 | sngl_tv.tv_sec = 0; | |
127 | sngl_tv.tv_usec = 0; | |
128 | ||
129 | maxfd = -1; | |
130 | ||
131 | /* Reset the return value. */ | |
132 | ready = 0; | |
133 | ||
134 | for (f = fds; f < &fds[nfds]; ++f) | |
135 | if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI)) | |
136 | && (f->revents & POLLNVAL) == 0) | |
137 | { | |
138 | int n; | |
139 | ||
140 | __bzero (sngl_rset, bytes); | |
141 | __bzero (sngl_wset, bytes); | |
142 | __bzero (sngl_xset, bytes); | |
143 | ||
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); | |
150 | ||
151 | n = __select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset, | |
152 | &sngl_tv); | |
153 | if (n != -1) | |
154 | { | |
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); | |
162 | if (f->fd > maxfd) | |
163 | maxfd = f->fd; | |
164 | if (n > 0) | |
165 | /* Count it as being available. */ | |
166 | ++ready; | |
167 | } | |
168 | else if (errno == EBADF) | |
169 | f->revents |= POLLNVAL; | |
170 | } | |
b02f5013 UD |
171 | /* Try again. */ |
172 | continue; | |
62acd376 | 173 | } |
b02f5013 UD |
174 | |
175 | break; | |
62acd376 | 176 | } |
62acd376 | 177 | |
28f540f4 RM |
178 | if (ready > 0) |
179 | for (f = fds; f < &fds[nfds]; ++f) | |
180 | { | |
28f540f4 RM |
181 | if (f->fd >= 0) |
182 | { | |
ba9234d9 | 183 | if (FD_ISSET (f->fd, rset)) |
28f540f4 | 184 | f->revents |= POLLIN; |
ba9234d9 | 185 | if (FD_ISSET (f->fd, wset)) |
28f540f4 | 186 | f->revents |= POLLOUT; |
ba9234d9 | 187 | if (FD_ISSET (f->fd, xset)) |
28f540f4 RM |
188 | f->revents |= POLLPRI; |
189 | } | |
190 | } | |
191 | ||
192 | return ready; | |
193 | } | |
bfc73ba2 | 194 | #ifndef __poll |
37ba7d66 | 195 | libc_hidden_def (__poll) |
bfc73ba2 UD |
196 | weak_alias (__poll, poll) |
197 | #endif |