1 /* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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 Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 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 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 #include <sys/types.h>
26 /* All user select types. */
27 #define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
29 /* Used to record that a particular select rpc returned. Must be distinct
30 from SELECT_ALL (which better not have the high bit set). */
31 #define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
33 /* Check the first NFDS descriptors each in READFDS (if not NULL) for read
34 readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS
35 (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out
36 after waiting the interval specified therein. Returns the number of ready
37 descriptors, or -1 for errors. */
39 __select (nfds, readfds, writefds, exceptfds, timeout)
44 struct timeval *timeout;
50 fd_set rfds, wfds, xfds;
52 mach_msg_timeout_t to = (timeout != NULL ?
53 (timeout->tv_sec * 1000 +
54 timeout->tv_usec / 1000) :
58 struct hurd_userlink ulink;
62 mach_port_t reply_port;
65 /* Use local copies so we can't crash from user bogosity. */
74 if (exceptfds == NULL)
80 __mutex_lock (&_hurd_dtable_lock);
82 if (nfds > _hurd_dtablesize)
83 nfds = _hurd_dtablesize;
85 /* Collect the ports for interesting FDs. */
86 firstfd = lastfd = -1;
87 for (i = 0; i < nfds; ++i)
90 if (readfds != NULL && FD_ISSET (i, &rfds))
92 if (writefds != NULL && FD_ISSET (i, &wfds))
94 if (exceptfds != NULL && FD_ISSET (i, &xfds))
99 d[i].cell = _hurd_dtable[i];
100 d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
101 if (d[i].io_port == MACH_PORT_NULL)
103 /* If one descriptor is bogus, we fail completely. */
105 _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
115 __mutex_unlock (&_hurd_dtable_lock);
121 /* Send them all io_select request messages. */
124 /* But not if there were no ports to deal with at all. */
125 portset = __mach_reply_port ();
130 portset = MACH_PORT_NULL;
132 for (i = firstfd; i <= lastfd; ++i)
135 int type = d[i].type;
136 d[i].reply_port = __mach_reply_port ();
137 err = __io_select (d[i].io_port, d[i].reply_port,
138 /* Poll only if there's a single descriptor. */
139 (firstfd == lastfd) ? to : 0,
143 case MACH_RCV_TIMED_OUT:
144 /* No immediate response. This is normal. */
146 if (firstfd == lastfd)
147 /* When there's a single descriptor, we don't need a
148 portset, so just pretend we have one, but really
149 use the single reply port. */
150 portset = d[i].reply_port;
152 /* We've got multiple reply ports, so we need a port set to
155 /* We will wait again for a reply later. */
156 if (portset == MACH_PORT_NULL)
157 /* Create the portset to receive all the replies on. */
158 err = __mach_port_allocate (__mach_task_self (),
159 MACH_PORT_RIGHT_PORT_SET,
162 /* Put this reply port in the port set. */
163 __mach_port_move_member (__mach_task_self (),
164 d[i].reply_port, portset);
169 /* No other error should happen. Callers of select
170 don't expect to see errors, so we simulate
171 readiness of the erring object and the next call
172 hopefully will get the error again. */
177 /* We got an answer. */
178 if ((type & SELECT_ALL) == 0)
179 /* Bogus answer; treat like an error, as a fake positive. */
182 /* This port is already ready already. */
184 d[i].type |= SELECT_RETURNED;
188 _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
192 /* Now wait for reply messages. */
193 if (!err && got == 0)
195 /* Now wait for io_select_reply messages on PORT,
196 timing out as appropriate. */
200 mach_msg_header_t head;
203 mach_msg_header_t head;
204 mach_msg_type_t err_type;
209 mach_msg_header_t head;
210 mach_msg_type_t err_type;
212 mach_msg_type_t result_type;
216 mach_msg_option_t options = (timeout == NULL ? 0 : MACH_RCV_TIMEOUT);
218 while ((msgerr = __mach_msg (&msg.head,
219 MACH_RCV_MSG | options,
220 0, sizeof msg, portset, to,
221 MACH_PORT_NULL)) == MACH_MSG_SUCCESS)
223 /* We got a message. Decode it. */
224 #define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
225 const mach_msg_type_t inttype =
226 { MACH_MSG_TYPE_INTEGER_T, sizeof (MACH_MSG_TYPE_INTEGER_T) * 8,
228 if (msg.head.msgh_id == IO_SELECT_REPLY_MSGID &&
229 msg.head.msgh_size >= sizeof msg.error &&
230 !(msg.head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
231 *(int *) &msg.error.err_type == *(int *) &inttype)
233 /* This is a properly formatted message so far.
234 See if it is a success or a failure. */
235 if (msg.error.err == EINTR &&
236 msg.head.msgh_size == sizeof msg.error)
238 /* EINTR response; poll for further responses
239 and then return quickly. */
244 msg.head.msgh_size != sizeof msg.success ||
245 *(int *) &msg.success.result_type != *(int *) &inttype ||
246 (msg.success.result & SELECT_ALL) == 0)
248 /* Error or bogus reply. Simulate readiness. */
249 __mach_msg_destroy (&msg.head);
250 msg.success.result = SELECT_ALL;
253 /* Look up the respondent's reply port and record its
258 for (i = firstfd; i <= lastfd; ++i)
260 && d[i].reply_port == msg.head.msgh_local_port)
262 d[i].type &= msg.success.result;
263 d[i].type |= SELECT_RETURNED;
270 if (msg.head.msgh_remote_port != MACH_PORT_NULL)
271 __mach_port_deallocate (__mach_task_self (),
272 msg.head.msgh_remote_port);
277 /* Poll for another message. */
279 options |= MACH_RCV_TIMEOUT;
283 if (err == MACH_RCV_TIMED_OUT)
284 /* This is the normal value for ERR. We might have timed out and
285 read no messages. Otherwise, after receiving the first message,
286 we poll for more messages. We receive with a timeout of 0 to
287 effect a poll, so ERR is MACH_RCV_TIMED_OUT when the poll finds no
292 /* At least one descriptor is known to be ready now, so we will
298 for (i = firstfd; i <= lastfd; ++i)
300 __mach_port_destroy (__mach_task_self (), d[i].reply_port);
301 if (firstfd == -1 || (firstfd != lastfd && portset != MACH_PORT_NULL))
302 /* Destroy PORTSET, but only if it's not actually the reply port for a
303 single descriptor (in which case it's destroyed in the previous loop;
304 not doing it here is just a bit more efficient). */
305 __mach_port_destroy (__mach_task_self (), portset);
308 return __hurd_fail (err);
310 /* Below we recalculate GOT to include an increment for each operation
311 allowed on each fd. */
314 /* Set the user bitarrays. We only ever have to clear bits, as all desired
315 ones are initially set. */
317 for (i = firstfd; i <= lastfd; ++i)
319 int type = d[i].type;
321 if ((type & SELECT_RETURNED) == 0)
324 if (type & SELECT_READ)
328 if (type & SELECT_WRITE)
331 FD_CLR (i, writefds);
332 if (type & SELECT_URG)
335 FD_CLR (i, exceptfds);
341 weak_alias (__select, select)