Add a generic scalb implementation
[glibc.git] / hurd / hurdselect.c
blobb140dab6c3031f5e17a6fd602ee7fb6bafc16bc8
1 /* Guts of both `select' and `poll' for Hurd.
2 Copyright (C) 1991-2020 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 Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <sys/time.h>
20 #include <sys/types.h>
21 #include <sys/poll.h>
22 #include <hurd.h>
23 #include <hurd/fd.h>
24 #include <hurd/io_request.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <stdint.h>
29 #include <limits.h>
30 #include <time.h>
32 /* All user select types. */
33 #define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
35 /* Used to record that a particular select rpc returned. Must be distinct
36 from SELECT_ALL (which better not have the high bit set). */
37 #define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
38 #define SELECT_ERROR (SELECT_RETURNED << 1)
40 /* Check the first NFDS descriptors either in POLLFDS (if nonnnull) or in
41 each of READFDS, WRITEFDS, EXCEPTFDS that is nonnull. If TIMEOUT is not
42 NULL, time out after waiting the interval specified therein. Returns
43 the number of ready descriptors, or -1 for errors. */
44 int
45 _hurd_select (int nfds,
46 struct pollfd *pollfds,
47 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
48 const struct timespec *timeout, const sigset_t *sigmask)
50 int i;
51 mach_port_t portset;
52 int got, ready;
53 error_t err;
54 fd_set rfds, wfds, xfds;
55 int firstfd, lastfd;
56 mach_msg_id_t reply_msgid;
57 mach_msg_timeout_t to;
58 struct timespec ts;
59 struct
61 struct hurd_userlink ulink;
62 struct hurd_fd *cell;
63 mach_port_t io_port;
64 int type;
65 mach_port_t reply_port;
66 int error;
67 } d[nfds];
68 sigset_t oset;
70 union typeword /* Use this to avoid unkosher casts. */
72 mach_msg_type_t type;
73 uint32_t word;
75 assert (sizeof (union typeword) == sizeof (mach_msg_type_t));
76 assert (sizeof (uint32_t) == sizeof (mach_msg_type_t));
78 if (nfds < 0 || (pollfds == NULL && nfds > FD_SETSIZE))
80 errno = EINVAL;
81 return -1;
84 #define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
85 #define IO_SELECT_TIMEOUT_REPLY_MSGID (21031 + 100) /* XXX */
87 if (timeout == NULL)
88 reply_msgid = IO_SELECT_REPLY_MSGID;
89 else
91 struct timespec now;
93 if (timeout->tv_sec < 0 || ! valid_nanoseconds (timeout->tv_nsec))
95 errno = EINVAL;
96 return -1;
99 err = __clock_gettime (CLOCK_REALTIME, &now);
100 if (err)
101 return -1;
103 ts.tv_sec = now.tv_sec + timeout->tv_sec;
104 ts.tv_nsec = now.tv_nsec + timeout->tv_nsec;
106 if (ts.tv_nsec >= 1000000000)
108 ts.tv_sec++;
109 ts.tv_nsec -= 1000000000;
112 if (ts.tv_sec < 0)
113 ts.tv_sec = LONG_MAX; /* XXX */
115 reply_msgid = IO_SELECT_TIMEOUT_REPLY_MSGID;
118 if (sigmask && __sigprocmask (SIG_SETMASK, sigmask, &oset))
119 return -1;
121 if (pollfds)
123 int error = 0;
124 /* Collect interesting descriptors from the user's `pollfd' array.
125 We do a first pass that reads the user's array before taking
126 any locks. The second pass then only touches our own stack,
127 and gets the port references. */
129 for (i = 0; i < nfds; ++i)
130 if (pollfds[i].fd >= 0)
132 int type = 0;
133 if (pollfds[i].events & POLLIN)
134 type |= SELECT_READ;
135 if (pollfds[i].events & POLLOUT)
136 type |= SELECT_WRITE;
137 if (pollfds[i].events & POLLPRI)
138 type |= SELECT_URG;
140 d[i].io_port = pollfds[i].fd;
141 d[i].type = type;
143 else
144 d[i].type = 0;
146 HURD_CRITICAL_BEGIN;
147 __mutex_lock (&_hurd_dtable_lock);
149 for (i = 0; i < nfds; ++i)
150 if (d[i].type != 0)
152 const int fd = (int) d[i].io_port;
154 if (fd < _hurd_dtablesize)
156 d[i].cell = _hurd_dtable[fd];
157 if (d[i].cell != NULL)
159 d[i].io_port = _hurd_port_get (&d[i].cell->port,
160 &d[i].ulink);
161 if (d[i].io_port != MACH_PORT_NULL)
162 continue;
166 /* Bogus descriptor, make it EBADF already. */
167 d[i].error = EBADF;
168 d[i].type = SELECT_ERROR;
169 error = 1;
172 __mutex_unlock (&_hurd_dtable_lock);
173 HURD_CRITICAL_END;
175 if (error)
177 /* Set timeout to 0. */
178 err = __clock_gettime (CLOCK_REALTIME, &ts);
179 if (err)
181 /* Really bad luck. */
182 err = errno;
183 HURD_CRITICAL_BEGIN;
184 __mutex_lock (&_hurd_dtable_lock);
185 while (i-- > 0)
186 if (d[i].type & ~SELECT_ERROR != 0)
187 _hurd_port_free (&d[i].cell->port, &d[i].ulink,
188 d[i].io_port);
189 __mutex_unlock (&_hurd_dtable_lock);
190 HURD_CRITICAL_END;
191 errno = err;
192 return -1;
194 reply_msgid = IO_SELECT_TIMEOUT_REPLY_MSGID;
197 lastfd = i - 1;
198 firstfd = i == 0 ? lastfd : 0;
200 else
202 /* Collect interested descriptors from the user's fd_set arguments.
203 Use local copies so we can't crash from user bogosity. */
205 if (readfds == NULL)
206 FD_ZERO (&rfds);
207 else
208 rfds = *readfds;
209 if (writefds == NULL)
210 FD_ZERO (&wfds);
211 else
212 wfds = *writefds;
213 if (exceptfds == NULL)
214 FD_ZERO (&xfds);
215 else
216 xfds = *exceptfds;
218 HURD_CRITICAL_BEGIN;
219 __mutex_lock (&_hurd_dtable_lock);
221 /* Collect the ports for interesting FDs. */
222 firstfd = lastfd = -1;
223 for (i = 0; i < nfds; ++i)
225 int type = 0;
226 if (readfds != NULL && FD_ISSET (i, &rfds))
227 type |= SELECT_READ;
228 if (writefds != NULL && FD_ISSET (i, &wfds))
229 type |= SELECT_WRITE;
230 if (exceptfds != NULL && FD_ISSET (i, &xfds))
231 type |= SELECT_URG;
232 d[i].type = type;
233 if (type)
235 if (i < _hurd_dtablesize)
237 d[i].cell = _hurd_dtable[i];
238 if (d[i].cell != NULL)
239 d[i].io_port = _hurd_port_get (&d[i].cell->port,
240 &d[i].ulink);
242 if (i >= _hurd_dtablesize || d[i].cell == NULL ||
243 d[i].io_port == MACH_PORT_NULL)
245 /* If one descriptor is bogus, we fail completely. */
246 while (i-- > 0)
247 if (d[i].type != 0)
248 _hurd_port_free (&d[i].cell->port, &d[i].ulink,
249 d[i].io_port);
250 break;
252 lastfd = i;
253 if (firstfd == -1)
254 firstfd = i;
258 __mutex_unlock (&_hurd_dtable_lock);
259 HURD_CRITICAL_END;
261 if (i < nfds)
263 if (sigmask)
264 __sigprocmask (SIG_SETMASK, &oset, NULL);
265 errno = EBADF;
266 return -1;
269 if (nfds > _hurd_dtablesize)
270 nfds = _hurd_dtablesize;
274 err = 0;
275 got = 0;
277 /* Send them all io_select request messages. */
279 if (firstfd == -1)
280 /* But not if there were no ports to deal with at all.
281 We are just a pure timeout. */
282 portset = __mach_reply_port ();
283 else
285 portset = MACH_PORT_NULL;
287 for (i = firstfd; i <= lastfd; ++i)
288 if (!(d[i].type & ~SELECT_ERROR))
289 d[i].reply_port = MACH_PORT_NULL;
290 else
292 int type = d[i].type;
293 d[i].reply_port = __mach_reply_port ();
294 if (timeout == NULL)
295 err = __io_select_request (d[i].io_port, d[i].reply_port, type);
296 else
297 err = __io_select_timeout_request (d[i].io_port, d[i].reply_port,
298 ts, type);
299 if (!err)
301 if (firstfd == lastfd)
302 /* When there's a single descriptor, we don't need a
303 portset, so just pretend we have one, but really
304 use the single reply port. */
305 portset = d[i].reply_port;
306 else if (got == 0)
307 /* We've got multiple reply ports, so we need a port set to
308 multiplex them. */
310 /* We will wait again for a reply later. */
311 if (portset == MACH_PORT_NULL)
312 /* Create the portset to receive all the replies on. */
313 err = __mach_port_allocate (__mach_task_self (),
314 MACH_PORT_RIGHT_PORT_SET,
315 &portset);
316 if (! err)
317 /* Put this reply port in the port set. */
318 __mach_port_move_member (__mach_task_self (),
319 d[i].reply_port, portset);
322 else
324 /* No error should happen, but record it for later
325 processing. */
326 d[i].error = err;
327 d[i].type |= SELECT_ERROR;
328 ++got;
330 _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
334 /* GOT is the number of replies (or errors), while READY is the number of
335 replies with at least one type bit set. */
336 ready = 0;
338 /* Now wait for reply messages. */
339 if (!err && got == 0)
341 /* Now wait for io_select_reply messages on PORT,
342 timing out as appropriate. */
344 union
346 mach_msg_header_t head;
347 #ifdef MACH_MSG_TRAILER_MINIMUM_SIZE
348 struct
350 mach_msg_header_t head;
351 NDR_record_t ndr;
352 error_t err;
353 } error;
354 struct
356 mach_msg_header_t head;
357 NDR_record_t ndr;
358 error_t err;
359 int result;
360 mach_msg_trailer_t trailer;
361 } success;
362 #else
363 struct
365 mach_msg_header_t head;
366 union typeword err_type;
367 error_t err;
368 } error;
369 struct
371 mach_msg_header_t head;
372 union typeword err_type;
373 error_t err;
374 union typeword result_type;
375 int result;
376 } success;
377 #endif
378 } msg;
379 mach_msg_option_t options;
380 error_t msgerr;
382 /* We rely on servers to implement the timeout, but when there are none,
383 do it on the client side. */
384 if (timeout != NULL && firstfd == -1)
386 options = MACH_RCV_TIMEOUT;
387 to = timeout->tv_sec * 1000 + (timeout->tv_nsec + 999999) / 1000000;
389 else
391 options = 0;
392 to = MACH_MSG_TIMEOUT_NONE;
395 while ((msgerr = __mach_msg (&msg.head,
396 MACH_RCV_MSG | MACH_RCV_INTERRUPT | options,
397 0, sizeof msg, portset, to,
398 MACH_PORT_NULL)) == MACH_MSG_SUCCESS)
400 /* We got a message. Decode it. */
401 #ifdef MACH_MSG_TYPE_BIT
402 const union typeword inttype =
403 { type:
404 { MACH_MSG_TYPE_INTEGER_T, sizeof (integer_t) * 8, 1, 1, 0, 0 }
406 #endif
407 if (msg.head.msgh_id == reply_msgid
408 && msg.head.msgh_size >= sizeof msg.error
409 && !(msg.head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
410 #ifdef MACH_MSG_TYPE_BIT
411 && msg.error.err_type.word == inttype.word
412 #endif
415 /* This is a properly formatted message so far.
416 See if it is a success or a failure. */
417 if (msg.error.err == EINTR
418 && msg.head.msgh_size == sizeof msg.error)
420 /* EINTR response; poll for further responses
421 and then return quickly. */
422 err = EINTR;
423 goto poll;
425 /* Keep in mind msg.success.result can be 0 if a timeout
426 occurred. */
427 if (msg.error.err
428 #ifdef MACH_MSG_TYPE_BIT
429 || msg.success.result_type.word != inttype.word
430 #endif
431 || msg.head.msgh_size != sizeof msg.success)
433 /* Error or bogus reply. */
434 if (!msg.error.err)
435 msg.error.err = EIO;
436 __mach_msg_destroy (&msg.head);
439 /* Look up the respondent's reply port and record its
440 readiness. */
442 int had = got;
443 if (firstfd != -1)
444 for (i = firstfd; i <= lastfd; ++i)
445 if (d[i].type
446 && d[i].reply_port == msg.head.msgh_local_port)
448 if (msg.error.err)
450 d[i].error = msg.error.err;
451 d[i].type = SELECT_ERROR;
452 ++ready;
454 else
456 d[i].type &= msg.success.result;
457 if (d[i].type)
458 ++ready;
461 d[i].type |= SELECT_RETURNED;
462 ++got;
464 assert (got > had);
468 if (msg.head.msgh_remote_port != MACH_PORT_NULL)
469 __mach_port_deallocate (__mach_task_self (),
470 msg.head.msgh_remote_port);
472 if (got)
473 poll:
475 /* Poll for another message. */
476 to = 0;
477 options |= MACH_RCV_TIMEOUT;
481 if (msgerr == MACH_RCV_INTERRUPTED)
482 /* Interruption on our side (e.g. signal reception). */
483 err = EINTR;
485 if (ready)
486 /* At least one descriptor is known to be ready now, so we will
487 return success. */
488 err = 0;
491 if (firstfd != -1)
492 for (i = firstfd; i <= lastfd; ++i)
493 if (d[i].reply_port != MACH_PORT_NULL)
494 __mach_port_destroy (__mach_task_self (), d[i].reply_port);
495 if (firstfd == -1 || (firstfd != lastfd && portset != MACH_PORT_NULL))
496 /* Destroy PORTSET, but only if it's not actually the reply port for a
497 single descriptor (in which case it's destroyed in the previous loop;
498 not doing it here is just a bit more efficient). */
499 __mach_port_destroy (__mach_task_self (), portset);
501 if (err)
503 if (sigmask)
504 __sigprocmask (SIG_SETMASK, &oset, NULL);
505 return __hurd_fail (err);
508 if (pollfds)
509 /* Fill in the `revents' members of the user's array. */
510 for (i = 0; i < nfds; ++i)
512 int type = d[i].type;
513 int_fast16_t revents = 0;
515 if (type & SELECT_ERROR)
516 switch (d[i].error)
518 case EPIPE:
519 revents = POLLHUP;
520 break;
521 case EBADF:
522 revents = POLLNVAL;
523 break;
524 default:
525 revents = POLLERR;
526 break;
528 else
529 if (type & SELECT_RETURNED)
531 if (type & SELECT_READ)
532 revents |= POLLIN;
533 if (type & SELECT_WRITE)
534 revents |= POLLOUT;
535 if (type & SELECT_URG)
536 revents |= POLLPRI;
539 pollfds[i].revents = revents;
541 else
543 /* Below we recalculate READY to include an increment for each operation
544 allowed on each fd. */
545 ready = 0;
547 /* Set the user bitarrays. We only ever have to clear bits, as all
548 desired ones are initially set. */
549 if (firstfd != -1)
550 for (i = firstfd; i <= lastfd; ++i)
552 int type = d[i].type;
554 if ((type & SELECT_RETURNED) == 0)
555 type = 0;
557 /* Callers of select don't expect to see errors, so we simulate
558 readiness of the erring object and the next call hopefully
559 will get the error again. */
560 if (type & SELECT_ERROR)
562 type = 0;
563 if (readfds != NULL && FD_ISSET (i, readfds))
564 type |= SELECT_READ;
565 if (writefds != NULL && FD_ISSET (i, writefds))
566 type |= SELECT_WRITE;
567 if (exceptfds != NULL && FD_ISSET (i, exceptfds))
568 type |= SELECT_URG;
571 if (type & SELECT_READ)
572 ready++;
573 else if (readfds)
574 FD_CLR (i, readfds);
575 if (type & SELECT_WRITE)
576 ready++;
577 else if (writefds)
578 FD_CLR (i, writefds);
579 if (type & SELECT_URG)
580 ready++;
581 else if (exceptfds)
582 FD_CLR (i, exceptfds);
586 if (sigmask && __sigprocmask (SIG_SETMASK, &oset, NULL))
587 return -1;
589 return ready;