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, see
18 <http://www.gnu.org/licenses/>. */
20 #include <sys/types.h>
29 /* All user select types. */
30 #define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
32 /* Used to record that a particular select rpc returned. Must be distinct
33 from SELECT_ALL (which better not have the high bit set). */
34 #define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
36 /* Check the first NFDS descriptors either in POLLFDS (if nonnnull) or in
37 each of READFDS, WRITEFDS, EXCEPTFDS that is nonnull. If TIMEOUT is not
38 NULL, time out after waiting the interval specified therein. Returns
39 the number of ready descriptors, or -1 for errors. */
41 _hurd_select (int nfds,
42 struct pollfd *pollfds,
43 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
44 const struct timespec *timeout, const sigset_t *sigmask)
50 fd_set rfds, wfds, xfds;
52 mach_msg_timeout_t to = (timeout != NULL ?
53 (timeout->tv_sec * 1000 +
54 (timeout->tv_nsec + 999999) / 1000000) :
58 struct hurd_userlink ulink;
62 mach_port_t reply_port;
66 union typeword /* Use this to avoid unkosher casts. */
71 assert (sizeof (union typeword) == sizeof (mach_msg_type_t));
72 assert (sizeof (uint32_t) == sizeof (mach_msg_type_t));
74 if (sigmask && __sigprocmask (SIG_SETMASK, sigmask, &oset))
79 /* Collect interesting descriptors from the user's `pollfd' array.
80 We do a first pass that reads the user's array before taking
81 any locks. The second pass then only touches our own stack,
82 and gets the port references. */
84 for (i = 0; i < nfds; ++i)
85 if (pollfds[i].fd >= 0)
88 if (pollfds[i].events & POLLIN)
90 if (pollfds[i].events & POLLOUT)
92 if (pollfds[i].events & POLLPRI)
95 d[i].io_port = pollfds[i].fd;
102 __mutex_lock (&_hurd_dtable_lock);
104 for (i = 0; i < nfds; ++i)
107 const int fd = (int) d[i].io_port;
109 if (fd < _hurd_dtablesize)
111 d[i].cell = _hurd_dtable[fd];
112 d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
113 if (d[i].io_port != MACH_PORT_NULL)
117 /* If one descriptor is bogus, we fail completely. */
120 _hurd_port_free (&d[i].cell->port,
121 &d[i].ulink, d[i].io_port);
125 __mutex_unlock (&_hurd_dtable_lock);
131 __sigprocmask (SIG_SETMASK, &oset, NULL);
137 firstfd = i == 0 ? lastfd : 0;
141 /* Collect interested descriptors from the user's fd_set arguments.
142 Use local copies so we can't crash from user bogosity. */
148 if (writefds == NULL)
152 if (exceptfds == NULL)
158 __mutex_lock (&_hurd_dtable_lock);
160 if (nfds > _hurd_dtablesize)
161 nfds = _hurd_dtablesize;
163 /* Collect the ports for interesting FDs. */
164 firstfd = lastfd = -1;
165 for (i = 0; i < nfds; ++i)
168 if (readfds != NULL && FD_ISSET (i, &rfds))
170 if (writefds != NULL && FD_ISSET (i, &wfds))
171 type |= SELECT_WRITE;
172 if (exceptfds != NULL && FD_ISSET (i, &xfds))
177 d[i].cell = _hurd_dtable[i];
178 d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
179 if (d[i].io_port == MACH_PORT_NULL)
181 /* If one descriptor is bogus, we fail completely. */
184 _hurd_port_free (&d[i].cell->port, &d[i].ulink,
194 __mutex_unlock (&_hurd_dtable_lock);
200 __sigprocmask (SIG_SETMASK, &oset, NULL);
210 /* Send them all io_select request messages. */
213 /* But not if there were no ports to deal with at all.
214 We are just a pure timeout. */
215 portset = __mach_reply_port ();
218 portset = MACH_PORT_NULL;
220 for (i = firstfd; i <= lastfd; ++i)
223 int type = d[i].type;
224 d[i].reply_port = __mach_reply_port ();
225 err = __io_select (d[i].io_port, d[i].reply_port,
226 /* Poll only if there's a single descriptor. */
227 (firstfd == lastfd) ? to : 0,
231 case MACH_RCV_TIMED_OUT:
232 /* No immediate response. This is normal. */
234 if (firstfd == lastfd)
235 /* When there's a single descriptor, we don't need a
236 portset, so just pretend we have one, but really
237 use the single reply port. */
238 portset = d[i].reply_port;
240 /* We've got multiple reply ports, so we need a port set to
243 /* We will wait again for a reply later. */
244 if (portset == MACH_PORT_NULL)
245 /* Create the portset to receive all the replies on. */
246 err = __mach_port_allocate (__mach_task_self (),
247 MACH_PORT_RIGHT_PORT_SET,
250 /* Put this reply port in the port set. */
251 __mach_port_move_member (__mach_task_self (),
252 d[i].reply_port, portset);
257 /* No other error should happen. Callers of select
258 don't expect to see errors, so we simulate
259 readiness of the erring object and the next call
260 hopefully will get the error again. */
265 /* We got an answer. */
266 if ((type & SELECT_ALL) == 0)
267 /* Bogus answer; treat like an error, as a fake positive. */
270 /* This port is already ready already. */
272 d[i].type |= SELECT_RETURNED;
276 _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
280 /* Now wait for reply messages. */
281 if (!err && got == 0)
283 /* Now wait for io_select_reply messages on PORT,
284 timing out as appropriate. */
288 mach_msg_header_t head;
289 #ifdef MACH_MSG_TRAILER_MINIMUM_SIZE
292 mach_msg_header_t head;
298 mach_msg_header_t head;
302 mach_msg_trailer_t trailer;
307 mach_msg_header_t head;
308 union typeword err_type;
313 mach_msg_header_t head;
314 union typeword err_type;
316 union typeword result_type;
321 mach_msg_option_t options = (timeout == NULL ? 0 : MACH_RCV_TIMEOUT);
323 while ((msgerr = __mach_msg (&msg.head,
324 MACH_RCV_MSG | options,
325 0, sizeof msg, portset, to,
326 MACH_PORT_NULL)) == MACH_MSG_SUCCESS)
328 /* We got a message. Decode it. */
329 #define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
330 #ifdef MACH_MSG_TYPE_BIT
331 const union typeword inttype =
333 { MACH_MSG_TYPE_INTEGER_T, sizeof (integer_t) * 8, 1, 1, 0, 0 }
336 if (msg.head.msgh_id == IO_SELECT_REPLY_MSGID &&
337 msg.head.msgh_size >= sizeof msg.error &&
338 !(msg.head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
339 #ifdef MACH_MSG_TYPE_BIT
340 msg.error.err_type.word == inttype.word
344 /* This is a properly formatted message so far.
345 See if it is a success or a failure. */
346 if (msg.error.err == EINTR &&
347 msg.head.msgh_size == sizeof msg.error)
349 /* EINTR response; poll for further responses
350 and then return quickly. */
355 msg.head.msgh_size != sizeof msg.success ||
356 #ifdef MACH_MSG_TYPE_BIT
357 msg.success.result_type.word != inttype.word ||
359 (msg.success.result & SELECT_ALL) == 0)
361 /* Error or bogus reply. Simulate readiness. */
362 __mach_msg_destroy (&msg.head);
363 msg.success.result = SELECT_ALL;
366 /* Look up the respondent's reply port and record its
371 for (i = firstfd; i <= lastfd; ++i)
373 && d[i].reply_port == msg.head.msgh_local_port)
375 d[i].type &= msg.success.result;
376 d[i].type |= SELECT_RETURNED;
383 if (msg.head.msgh_remote_port != MACH_PORT_NULL)
384 __mach_port_deallocate (__mach_task_self (),
385 msg.head.msgh_remote_port);
390 /* Poll for another message. */
392 options |= MACH_RCV_TIMEOUT;
396 if (err == MACH_RCV_TIMED_OUT)
397 /* This is the normal value for ERR. We might have timed out and
398 read no messages. Otherwise, after receiving the first message,
399 we poll for more messages. We receive with a timeout of 0 to
400 effect a poll, so ERR is MACH_RCV_TIMED_OUT when the poll finds no
405 /* At least one descriptor is known to be ready now, so we will
411 for (i = firstfd; i <= lastfd; ++i)
413 __mach_port_destroy (__mach_task_self (), d[i].reply_port);
414 if (firstfd == -1 || (firstfd != lastfd && portset != MACH_PORT_NULL))
415 /* Destroy PORTSET, but only if it's not actually the reply port for a
416 single descriptor (in which case it's destroyed in the previous loop;
417 not doing it here is just a bit more efficient). */
418 __mach_port_destroy (__mach_task_self (), portset);
423 __sigprocmask (SIG_SETMASK, &oset, NULL);
424 return __hurd_fail (err);
428 /* Fill in the `revents' members of the user's array. */
429 for (i = 0; i < nfds; ++i)
431 int type = d[i].type;
432 int_fast16_t revents = 0;
434 if (type & SELECT_RETURNED)
436 if (type & SELECT_READ)
438 if (type & SELECT_WRITE)
440 if (type & SELECT_URG)
444 pollfds[i].revents = revents;
448 /* Below we recalculate GOT to include an increment for each operation
449 allowed on each fd. */
452 /* Set the user bitarrays. We only ever have to clear bits, as all
453 desired ones are initially set. */
455 for (i = firstfd; i <= lastfd; ++i)
457 int type = d[i].type;
459 if ((type & SELECT_RETURNED) == 0)
462 if (type & SELECT_READ)
466 if (type & SELECT_WRITE)
469 FD_CLR (i, writefds);
470 if (type & SELECT_URG)
473 FD_CLR (i, exceptfds);
477 if (sigmask && __sigprocmask (SIG_SETMASK, &oset, NULL))