Update.
[glibc.git] / hurd / hurdselect.c
blobc3dfb5211928baf32b9a367310ed9c33662388ea
1 /* Guts of both `select' and `poll' for Hurd.
2 Copyright (C) 1991,92,93,94,95,96,97,98,99,2001
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 #include <sys/types.h>
22 #include <sys/poll.h>
23 #include <hurd.h>
24 #include <hurd/fd.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <stdint.h>
30 /* All user select types. */
31 #define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
33 /* Used to record that a particular select rpc returned. Must be distinct
34 from SELECT_ALL (which better not have the high bit set). */
35 #define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
37 /* Check the first NFDS descriptors either in POLLFDS (if nonnnull) or in
38 each of READFDS, WRITEFDS, EXCEPTFDS that is nonnull. If TIMEOUT is not
39 NULL, time out after waiting the interval specified therein. Returns
40 the number of ready descriptors, or -1 for errors. */
41 int
42 _hurd_select (int nfds,
43 struct pollfd *pollfds,
44 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
45 const struct timespec *timeout, const sigset_t *sigmask)
47 int i;
48 mach_port_t portset;
49 int got;
50 error_t err;
51 fd_set rfds, wfds, xfds;
52 int firstfd, lastfd;
53 mach_msg_timeout_t to = (timeout != NULL ?
54 (timeout->tv_sec * 1000 +
55 timeout->tv_nsec / 1000000) :
56 0);
57 struct
59 struct hurd_userlink ulink;
60 struct hurd_fd *cell;
61 mach_port_t io_port;
62 int type;
63 mach_port_t reply_port;
64 } d[nfds];
65 sigset_t oset;
67 if (sigmask && __sigprocmask (SIG_SETMASK, sigmask, &oset))
68 return -1;
70 if (pollfds)
72 /* Collect interesting descriptors from the user's `pollfd' array.
73 We do a first pass that reads the user's array before taking
74 any locks. The second pass then only touches our own stack,
75 and gets the port references. */
77 for (i = 0; i < nfds; ++i)
78 if (pollfds[i].fd >= 0)
80 int type = 0;
81 if (pollfds[i].events & POLLIN)
82 type |= SELECT_READ;
83 if (pollfds[i].events & POLLOUT)
84 type |= SELECT_WRITE;
85 if (pollfds[i].events & POLLPRI)
86 type |= SELECT_URG;
88 d[i].io_port = pollfds[i].fd;
89 d[i].type = type;
91 else
92 d[i].type = 0;
94 HURD_CRITICAL_BEGIN;
95 __mutex_lock (&_hurd_dtable_lock);
97 for (i = 0; i < nfds; ++i)
98 if (d[i].type != 0)
100 const int fd = (int) d[i].io_port;
102 if (fd < _hurd_dtablesize)
104 d[i].cell = _hurd_dtable[fd];
105 d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
106 if (d[i].io_port != MACH_PORT_NULL)
107 continue;
110 /* If one descriptor is bogus, we fail completely. */
111 while (i-- > 0)
112 if (d[i].type != 0)
113 _hurd_port_free (&d[i].cell->port,
114 &d[i].ulink, d[i].io_port);
115 break;
118 __mutex_unlock (&_hurd_dtable_lock);
119 HURD_CRITICAL_END;
121 if (i < nfds)
123 if (sigmask)
124 __sigprocmask (SIG_SETMASK, &oset, NULL);
125 errno = EBADF;
126 return -1;
129 lastfd = i - 1;
130 firstfd = i == 0 ? lastfd : 0;
132 else
134 /* Collect interested descriptors from the user's fd_set arguments.
135 Use local copies so we can't crash from user bogosity. */
137 if (readfds == NULL)
138 FD_ZERO (&rfds);
139 else
140 rfds = *readfds;
141 if (writefds == NULL)
142 FD_ZERO (&wfds);
143 else
144 wfds = *writefds;
145 if (exceptfds == NULL)
146 FD_ZERO (&xfds);
147 else
148 xfds = *exceptfds;
150 HURD_CRITICAL_BEGIN;
151 __mutex_lock (&_hurd_dtable_lock);
153 if (nfds > _hurd_dtablesize)
154 nfds = _hurd_dtablesize;
156 /* Collect the ports for interesting FDs. */
157 firstfd = lastfd = -1;
158 for (i = 0; i < nfds; ++i)
160 int type = 0;
161 if (readfds != NULL && FD_ISSET (i, &rfds))
162 type |= SELECT_READ;
163 if (writefds != NULL && FD_ISSET (i, &wfds))
164 type |= SELECT_WRITE;
165 if (exceptfds != NULL && FD_ISSET (i, &xfds))
166 type |= SELECT_URG;
167 d[i].type = type;
168 if (type)
170 d[i].cell = _hurd_dtable[i];
171 d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
172 if (d[i].io_port == MACH_PORT_NULL)
174 /* If one descriptor is bogus, we fail completely. */
175 while (i-- > 0)
176 if (d[i].type != 0)
177 _hurd_port_free (&d[i].cell->port, &d[i].ulink,
178 d[i].io_port);
179 break;
181 lastfd = i;
182 if (firstfd == -1)
183 firstfd = i;
187 __mutex_unlock (&_hurd_dtable_lock);
188 HURD_CRITICAL_END;
190 if (i < nfds)
192 if (sigmask)
193 __sigprocmask (SIG_SETMASK, &oset, NULL);
194 errno = EBADF;
195 return -1;
200 err = 0;
201 got = 0;
203 /* Send them all io_select request messages. */
205 if (firstfd == -1)
206 /* But not if there were no ports to deal with at all.
207 We are just a pure timeout. */
208 portset = __mach_reply_port ();
209 else
211 portset = MACH_PORT_NULL;
213 for (i = firstfd; i <= lastfd; ++i)
214 if (d[i].type)
216 int type = d[i].type;
217 d[i].reply_port = __mach_reply_port ();
218 err = __io_select (d[i].io_port, d[i].reply_port,
219 /* Poll only if there's a single descriptor. */
220 (firstfd == lastfd) ? to : 0,
221 &type);
222 switch (err)
224 case MACH_RCV_TIMED_OUT:
225 /* No immediate response. This is normal. */
226 err = 0;
227 if (firstfd == lastfd)
228 /* When there's a single descriptor, we don't need a
229 portset, so just pretend we have one, but really
230 use the single reply port. */
231 portset = d[i].reply_port;
232 else if (got == 0)
233 /* We've got multiple reply ports, so we need a port set to
234 multiplex them. */
236 /* We will wait again for a reply later. */
237 if (portset == MACH_PORT_NULL)
238 /* Create the portset to receive all the replies on. */
239 err = __mach_port_allocate (__mach_task_self (),
240 MACH_PORT_RIGHT_PORT_SET,
241 &portset);
242 if (! err)
243 /* Put this reply port in the port set. */
244 __mach_port_move_member (__mach_task_self (),
245 d[i].reply_port, portset);
247 break;
249 default:
250 /* No other error should happen. Callers of select
251 don't expect to see errors, so we simulate
252 readiness of the erring object and the next call
253 hopefully will get the error again. */
254 type = SELECT_ALL;
255 /* FALLTHROUGH */
257 case 0:
258 /* We got an answer. */
259 if ((type & SELECT_ALL) == 0)
260 /* Bogus answer; treat like an error, as a fake positive. */
261 type = SELECT_ALL;
263 /* This port is already ready already. */
264 d[i].type &= type;
265 d[i].type |= SELECT_RETURNED;
266 ++got;
267 break;
269 _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
273 /* Now wait for reply messages. */
274 if (!err && got == 0)
276 /* Now wait for io_select_reply messages on PORT,
277 timing out as appropriate. */
279 union
281 mach_msg_header_t head;
282 struct
284 mach_msg_header_t head;
285 mach_msg_type_t err_type;
286 error_t err;
287 } error;
288 struct
290 mach_msg_header_t head;
291 mach_msg_type_t err_type;
292 error_t err;
293 mach_msg_type_t result_type;
294 int result;
295 } success;
296 } msg;
297 mach_msg_option_t options = (timeout == NULL ? 0 : MACH_RCV_TIMEOUT);
298 error_t msgerr;
299 while ((msgerr = __mach_msg (&msg.head,
300 MACH_RCV_MSG | options,
301 0, sizeof msg, portset, to,
302 MACH_PORT_NULL)) == MACH_MSG_SUCCESS)
304 /* We got a message. Decode it. */
305 #define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
306 const mach_msg_type_t inttype =
307 { MACH_MSG_TYPE_INTEGER_T, sizeof (MACH_MSG_TYPE_INTEGER_T) * 8,
308 1, 1, 0, 0 };
309 if (msg.head.msgh_id == IO_SELECT_REPLY_MSGID &&
310 msg.head.msgh_size >= sizeof msg.error &&
311 !(msg.head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
312 *(int *) &msg.error.err_type == *(int *) &inttype)
314 /* This is a properly formatted message so far.
315 See if it is a success or a failure. */
316 if (msg.error.err == EINTR &&
317 msg.head.msgh_size == sizeof msg.error)
319 /* EINTR response; poll for further responses
320 and then return quickly. */
321 err = EINTR;
322 goto poll;
324 if (msg.error.err ||
325 msg.head.msgh_size != sizeof msg.success ||
326 *(int *) &msg.success.result_type != *(int *) &inttype ||
327 (msg.success.result & SELECT_ALL) == 0)
329 /* Error or bogus reply. Simulate readiness. */
330 __mach_msg_destroy (&msg.head);
331 msg.success.result = SELECT_ALL;
334 /* Look up the respondent's reply port and record its
335 readiness. */
337 int had = got;
338 if (firstfd != -1)
339 for (i = firstfd; i <= lastfd; ++i)
340 if (d[i].type
341 && d[i].reply_port == msg.head.msgh_local_port)
343 d[i].type &= msg.success.result;
344 d[i].type |= SELECT_RETURNED;
345 ++got;
347 assert (got > had);
351 if (msg.head.msgh_remote_port != MACH_PORT_NULL)
352 __mach_port_deallocate (__mach_task_self (),
353 msg.head.msgh_remote_port);
355 if (got)
356 poll:
358 /* Poll for another message. */
359 to = 0;
360 options |= MACH_RCV_TIMEOUT;
364 if (err == MACH_RCV_TIMED_OUT)
365 /* This is the normal value for ERR. We might have timed out and
366 read no messages. Otherwise, after receiving the first message,
367 we poll for more messages. We receive with a timeout of 0 to
368 effect a poll, so ERR is MACH_RCV_TIMED_OUT when the poll finds no
369 message waiting. */
370 err = 0;
372 if (got)
373 /* At least one descriptor is known to be ready now, so we will
374 return success. */
375 err = 0;
378 if (firstfd != -1)
379 for (i = firstfd; i <= lastfd; ++i)
380 if (d[i].type)
381 __mach_port_destroy (__mach_task_self (), d[i].reply_port);
382 if (firstfd == -1 || (firstfd != lastfd && portset != MACH_PORT_NULL))
383 /* Destroy PORTSET, but only if it's not actually the reply port for a
384 single descriptor (in which case it's destroyed in the previous loop;
385 not doing it here is just a bit more efficient). */
386 __mach_port_destroy (__mach_task_self (), portset);
388 if (err)
390 if (sigmask)
391 __sigprocmask (SIG_SETMASK, &oset, NULL);
392 return __hurd_fail (err);
395 if (pollfds)
396 /* Fill in the `revents' members of the user's array. */
397 for (i = 0; i < nfds; ++i)
399 int type = d[i].type;
400 int_fast16_t revents = 0;
402 if (type & SELECT_RETURNED)
404 if (type & SELECT_READ)
405 revents |= POLLIN;
406 if (type & SELECT_WRITE)
407 revents |= POLLOUT;
408 if (type & SELECT_URG)
409 revents |= POLLPRI;
412 pollfds[i].revents = revents;
414 else
416 /* Below we recalculate GOT to include an increment for each operation
417 allowed on each fd. */
418 got = 0;
420 /* Set the user bitarrays. We only ever have to clear bits, as all
421 desired ones are initially set. */
422 if (firstfd != -1)
423 for (i = firstfd; i <= lastfd; ++i)
425 int type = d[i].type;
427 if ((type & SELECT_RETURNED) == 0)
428 type = 0;
430 if (type & SELECT_READ)
431 got++;
432 else if (readfds)
433 FD_CLR (i, readfds);
434 if (type & SELECT_WRITE)
435 got++;
436 else if (writefds)
437 FD_CLR (i, writefds);
438 if (type & SELECT_URG)
439 got++;
440 else if (exceptfds)
441 FD_CLR (i, exceptfds);
445 if (sigmask && __sigprocmask (SIG_SETMASK, &oset, NULL))
446 return -1;
448 return got;