Update.
[glibc.git] / hurd / hurdselect.c
blobe65def59129bfb56987f301834a0f83854e130fe
1 /* Guts of both `select' and `poll' for Hurd.
2 Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <sys/types.h>
21 #include <sys/poll.h>
22 #include <hurd.h>
23 #include <hurd/fd.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <stdint.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. */
40 int
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)
46 int i;
47 mach_port_t portset;
48 int got;
49 error_t err;
50 fd_set rfds, wfds, xfds;
51 int firstfd, lastfd;
52 mach_msg_timeout_t to = (timeout != NULL ?
53 (timeout->tv_sec * 1000 +
54 timeout->tv_nsec / 1000000) :
55 0);
56 struct
58 struct hurd_userlink ulink;
59 struct hurd_fd *cell;
60 mach_port_t io_port;
61 int type;
62 mach_port_t reply_port;
63 } d[nfds];
64 sigset_t oset;
66 if (sigmask && __sigprocmask (SIG_SETMASK, sigmask, &oset))
67 return -1;
69 if (pollfds)
71 /* Collect interesting descriptors from the user's `pollfd' array.
72 We do a first pass that reads the user's array before taking
73 any locks. The second pass then only touches our own stack,
74 and gets the port references. */
76 for (i = 0; i < nfds; ++i)
77 if (pollfds[i].fd >= 0)
79 int type = 0;
80 if (pollfds[i].events & POLLIN)
81 type |= SELECT_READ;
82 if (pollfds[i].events & POLLOUT)
83 type |= SELECT_WRITE;
84 if (pollfds[i].events & POLLPRI)
85 type |= SELECT_URG;
87 d[i].io_port = pollfds[i].fd;
88 d[i].type = type;
90 else
91 d[i].type = 0;
93 HURD_CRITICAL_BEGIN;
94 __mutex_lock (&_hurd_dtable_lock);
96 for (i = 0; i < nfds; ++i)
97 if (d[i].type != 0)
99 const int fd = (int) d[i].io_port;
101 if (fd < _hurd_dtablesize)
103 d[i].cell = _hurd_dtable[fd];
104 d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
105 if (d[i].io_port != MACH_PORT_NULL)
106 continue;
109 /* If one descriptor is bogus, we fail completely. */
110 while (i-- > 0)
111 if (d[i].type != 0)
112 _hurd_port_free (&d[i].cell->port,
113 &d[i].ulink, d[i].io_port);
114 break;
117 __mutex_unlock (&_hurd_dtable_lock);
118 HURD_CRITICAL_END;
120 if (i < nfds)
122 if (sigmask)
123 __sigprocmask (SIG_SETMASK, &oset, NULL);
124 errno = EBADF;
125 return -1;
128 lastfd = i - 1;
129 firstfd = i == 0 ? lastfd : 0;
131 else
133 /* Collect interested descriptors from the user's fd_set arguments.
134 Use local copies so we can't crash from user bogosity. */
136 if (readfds == NULL)
137 FD_ZERO (&rfds);
138 else
139 rfds = *readfds;
140 if (writefds == NULL)
141 FD_ZERO (&wfds);
142 else
143 wfds = *writefds;
144 if (exceptfds == NULL)
145 FD_ZERO (&xfds);
146 else
147 xfds = *exceptfds;
149 HURD_CRITICAL_BEGIN;
150 __mutex_lock (&_hurd_dtable_lock);
152 if (nfds > _hurd_dtablesize)
153 nfds = _hurd_dtablesize;
155 /* Collect the ports for interesting FDs. */
156 firstfd = lastfd = -1;
157 for (i = 0; i < nfds; ++i)
159 int type = 0;
160 if (readfds != NULL && FD_ISSET (i, &rfds))
161 type |= SELECT_READ;
162 if (writefds != NULL && FD_ISSET (i, &wfds))
163 type |= SELECT_WRITE;
164 if (exceptfds != NULL && FD_ISSET (i, &xfds))
165 type |= SELECT_URG;
166 d[i].type = type;
167 if (type)
169 d[i].cell = _hurd_dtable[i];
170 d[i].io_port = _hurd_port_get (&d[i].cell->port, &d[i].ulink);
171 if (d[i].io_port == MACH_PORT_NULL)
173 /* If one descriptor is bogus, we fail completely. */
174 while (i-- > 0)
175 _hurd_port_free (&d[i].cell->port, &d[i].ulink,
176 d[i].io_port);
177 break;
179 lastfd = i;
180 if (firstfd == -1)
181 firstfd = i;
185 __mutex_unlock (&_hurd_dtable_lock);
186 HURD_CRITICAL_END;
188 if (i < nfds)
190 if (sigmask)
191 __sigprocmask (SIG_SETMASK, &oset, NULL);
192 errno = EBADF;
193 return -1;
198 err = 0;
199 got = 0;
201 /* Send them all io_select request messages. */
203 if (firstfd == -1)
204 /* But not if there were no ports to deal with at all.
205 We are just a pure timeout. */
206 portset = __mach_reply_port ();
207 else
209 portset = MACH_PORT_NULL;
211 for (i = firstfd; i <= lastfd; ++i)
212 if (d[i].type)
214 int type = d[i].type;
215 d[i].reply_port = __mach_reply_port ();
216 err = __io_select (d[i].io_port, d[i].reply_port,
217 /* Poll only if there's a single descriptor. */
218 (firstfd == lastfd) ? to : 0,
219 &type);
220 switch (err)
222 case MACH_RCV_TIMED_OUT:
223 /* No immediate response. This is normal. */
224 err = 0;
225 if (firstfd == lastfd)
226 /* When there's a single descriptor, we don't need a
227 portset, so just pretend we have one, but really
228 use the single reply port. */
229 portset = d[i].reply_port;
230 else if (got == 0)
231 /* We've got multiple reply ports, so we need a port set to
232 multiplex them. */
234 /* We will wait again for a reply later. */
235 if (portset == MACH_PORT_NULL)
236 /* Create the portset to receive all the replies on. */
237 err = __mach_port_allocate (__mach_task_self (),
238 MACH_PORT_RIGHT_PORT_SET,
239 &portset);
240 if (! err)
241 /* Put this reply port in the port set. */
242 __mach_port_move_member (__mach_task_self (),
243 d[i].reply_port, portset);
245 break;
247 default:
248 /* No other error should happen. Callers of select
249 don't expect to see errors, so we simulate
250 readiness of the erring object and the next call
251 hopefully will get the error again. */
252 type = SELECT_ALL;
253 /* FALLTHROUGH */
255 case 0:
256 /* We got an answer. */
257 if ((type & SELECT_ALL) == 0)
258 /* Bogus answer; treat like an error, as a fake positive. */
259 type = SELECT_ALL;
261 /* This port is already ready already. */
262 d[i].type &= type;
263 d[i].type |= SELECT_RETURNED;
264 ++got;
265 break;
267 _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
271 /* Now wait for reply messages. */
272 if (!err && got == 0)
274 /* Now wait for io_select_reply messages on PORT,
275 timing out as appropriate. */
277 union
279 mach_msg_header_t head;
280 struct
282 mach_msg_header_t head;
283 mach_msg_type_t err_type;
284 error_t err;
285 } error;
286 struct
288 mach_msg_header_t head;
289 mach_msg_type_t err_type;
290 error_t err;
291 mach_msg_type_t result_type;
292 int result;
293 } success;
294 } msg;
295 mach_msg_option_t options = (timeout == NULL ? 0 : MACH_RCV_TIMEOUT);
296 error_t msgerr;
297 while ((msgerr = __mach_msg (&msg.head,
298 MACH_RCV_MSG | options,
299 0, sizeof msg, portset, to,
300 MACH_PORT_NULL)) == MACH_MSG_SUCCESS)
302 /* We got a message. Decode it. */
303 #define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
304 const mach_msg_type_t inttype =
305 { MACH_MSG_TYPE_INTEGER_T, sizeof (MACH_MSG_TYPE_INTEGER_T) * 8,
306 1, 1, 0, 0 };
307 if (msg.head.msgh_id == IO_SELECT_REPLY_MSGID &&
308 msg.head.msgh_size >= sizeof msg.error &&
309 !(msg.head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
310 *(int *) &msg.error.err_type == *(int *) &inttype)
312 /* This is a properly formatted message so far.
313 See if it is a success or a failure. */
314 if (msg.error.err == EINTR &&
315 msg.head.msgh_size == sizeof msg.error)
317 /* EINTR response; poll for further responses
318 and then return quickly. */
319 err = EINTR;
320 goto poll;
322 if (msg.error.err ||
323 msg.head.msgh_size != sizeof msg.success ||
324 *(int *) &msg.success.result_type != *(int *) &inttype ||
325 (msg.success.result & SELECT_ALL) == 0)
327 /* Error or bogus reply. Simulate readiness. */
328 __mach_msg_destroy (&msg.head);
329 msg.success.result = SELECT_ALL;
332 /* Look up the respondent's reply port and record its
333 readiness. */
335 int had = got;
336 if (firstfd != -1)
337 for (i = firstfd; i <= lastfd; ++i)
338 if (d[i].type
339 && d[i].reply_port == msg.head.msgh_local_port)
341 d[i].type &= msg.success.result;
342 d[i].type |= SELECT_RETURNED;
343 ++got;
345 assert (got > had);
349 if (msg.head.msgh_remote_port != MACH_PORT_NULL)
350 __mach_port_deallocate (__mach_task_self (),
351 msg.head.msgh_remote_port);
353 if (got)
354 poll:
356 /* Poll for another message. */
357 to = 0;
358 options |= MACH_RCV_TIMEOUT;
362 if (err == MACH_RCV_TIMED_OUT)
363 /* This is the normal value for ERR. We might have timed out and
364 read no messages. Otherwise, after receiving the first message,
365 we poll for more messages. We receive with a timeout of 0 to
366 effect a poll, so ERR is MACH_RCV_TIMED_OUT when the poll finds no
367 message waiting. */
368 err = 0;
370 if (got)
371 /* At least one descriptor is known to be ready now, so we will
372 return success. */
373 err = 0;
376 if (firstfd != -1)
377 for (i = firstfd; i <= lastfd; ++i)
378 if (d[i].type)
379 __mach_port_destroy (__mach_task_self (), d[i].reply_port);
380 if (firstfd == -1 || (firstfd != lastfd && portset != MACH_PORT_NULL))
381 /* Destroy PORTSET, but only if it's not actually the reply port for a
382 single descriptor (in which case it's destroyed in the previous loop;
383 not doing it here is just a bit more efficient). */
384 __mach_port_destroy (__mach_task_self (), portset);
386 if (err)
388 if (sigmask)
389 __sigprocmask (SIG_SETMASK, &oset, NULL);
390 return __hurd_fail (err);
393 if (pollfds)
394 /* Fill in the `revents' members of the user's array. */
395 for (i = 0; i < nfds; ++i)
397 const int type = d[i].type;
398 int_fast16_t revents = 0;
400 if (type & SELECT_READ)
401 revents |= POLLIN;
402 if (type & SELECT_WRITE)
403 revents |= POLLOUT;
404 if (type & SELECT_URG)
405 revents |= POLLPRI;
407 pollfds[i].revents = revents;
409 else
411 /* Below we recalculate GOT to include an increment for each operation
412 allowed on each fd. */
413 got = 0;
415 /* Set the user bitarrays. We only ever have to clear bits, as all
416 desired ones are initially set. */
417 if (firstfd != -1)
418 for (i = firstfd; i <= lastfd; ++i)
420 int type = d[i].type;
422 if ((type & SELECT_RETURNED) == 0)
423 type = 0;
425 if (type & SELECT_READ)
426 got++;
427 else if (readfds)
428 FD_CLR (i, readfds);
429 if (type & SELECT_WRITE)
430 got++;
431 else if (writefds)
432 FD_CLR (i, writefds);
433 if (type & SELECT_URG)
434 got++;
435 else if (exceptfds)
436 FD_CLR (i, exceptfds);
440 if (sigmask && __sigprocmask (SIG_SETMASK, &oset, NULL))
441 return -1;
443 return got;