]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/bsd/poll.c
Update copyright notices with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / bsd / poll.c
1 /* Copyright (C) 1994-2013 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 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.
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 Lesser General Public License for more details.
13
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/>. */
17
18 #include <alloca.h>
19 #include <sys/poll.h>
20 #include <sys/types.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <sys/time.h>
24 #include <sys/param.h>
25 #include <unistd.h>
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
34 __poll (fds, nfds, timeout)
35 struct pollfd *fds;
36 nfds_t nfds;
37 int timeout;
38 {
39 static int max_fd_size;
40 struct timeval tv;
41 fd_set *rset, *wset, *xset;
42 struct pollfd *f;
43 int ready;
44 int maxfd = 0;
45 int bytes;
46
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);
60
61 for (f = fds; f < &fds[nfds]; ++f)
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 }
102
103 tv.tv_sec = timeout / 1000;
104 tv.tv_usec = (timeout % 1000) * 1000;
105
106 while (1)
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 }
171 /* Try again. */
172 continue;
173 }
174
175 break;
176 }
177
178 if (ready > 0)
179 for (f = fds; f < &fds[nfds]; ++f)
180 {
181 if (f->fd >= 0)
182 {
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;
189 }
190 }
191
192 return ready;
193 }
194 #ifndef __poll
195 libc_hidden_def (__poll)
196 weak_alias (__poll, poll)
197 #endif