1 /* Guts of both `select' and `poll' for Hurd.
2 Copyright (C) 1991-2019 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/>. */
20 #include <sys/types.h>
24 #include <hurd/io_request.h>
31 /* All user select types. */
32 #define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
34 /* Used to record that a particular select rpc returned. Must be distinct
35 from SELECT_ALL (which better not have the high bit set). */
36 #define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
37 #define SELECT_ERROR (SELECT_RETURNED << 1)
39 /* Check the first NFDS descriptors either in POLLFDS (if nonnnull) or in
40 each of READFDS, WRITEFDS, EXCEPTFDS that is nonnull. If TIMEOUT is not
41 NULL, time out after waiting the interval specified therein. Returns
42 the number of ready descriptors, or -1 for errors. */
44 _hurd_select (int nfds
,
45 struct pollfd
*pollfds
,
46 fd_set
*readfds
, fd_set
*writefds
, fd_set
*exceptfds
,
47 const struct timespec
*timeout
, const sigset_t
*sigmask
)
53 fd_set rfds
, wfds
, xfds
;
55 mach_msg_id_t reply_msgid
;
56 mach_msg_timeout_t to
;
60 struct hurd_userlink ulink
;
64 mach_port_t reply_port
;
69 union typeword
/* Use this to avoid unkosher casts. */
74 assert (sizeof (union typeword
) == sizeof (mach_msg_type_t
));
75 assert (sizeof (uint32_t) == sizeof (mach_msg_type_t
));
77 if (nfds
< 0 || (pollfds
== NULL
&& nfds
> FD_SETSIZE
))
83 #define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
84 #define IO_SELECT_TIMEOUT_REPLY_MSGID (21031 + 100) /* XXX */
87 reply_msgid
= IO_SELECT_REPLY_MSGID
;
92 if (timeout
->tv_sec
< 0 || timeout
->tv_nsec
< 0 ||
93 timeout
->tv_nsec
>= 1000000000)
99 err
= __gettimeofday(&now
, NULL
);
103 ts
.tv_sec
= now
.tv_sec
+ timeout
->tv_sec
;
104 ts
.tv_nsec
= now
.tv_usec
* 1000 + timeout
->tv_nsec
;
106 if (ts
.tv_nsec
>= 1000000000)
109 ts
.tv_nsec
-= 1000000000;
113 ts
.tv_sec
= LONG_MAX
; /* XXX */
115 reply_msgid
= IO_SELECT_TIMEOUT_REPLY_MSGID
;
118 if (sigmask
&& __sigprocmask (SIG_SETMASK
, sigmask
, &oset
))
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)
133 if (pollfds
[i
].events
& POLLIN
)
135 if (pollfds
[i
].events
& POLLOUT
)
136 type
|= SELECT_WRITE
;
137 if (pollfds
[i
].events
& POLLPRI
)
140 d
[i
].io_port
= pollfds
[i
].fd
;
147 __mutex_lock (&_hurd_dtable_lock
);
149 for (i
= 0; i
< nfds
; ++i
)
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
,
161 if (d
[i
].io_port
!= MACH_PORT_NULL
)
166 /* Bogus descriptor, make it EBADF already. */
168 d
[i
].type
= SELECT_ERROR
;
172 __mutex_unlock (&_hurd_dtable_lock
);
177 /* Set timeout to 0. */
179 err
= __gettimeofday(&now
, NULL
);
182 /* Really bad luck. */
185 __mutex_lock (&_hurd_dtable_lock
);
187 if (d
[i
].type
& ~SELECT_ERROR
!= 0)
188 _hurd_port_free (&d
[i
].cell
->port
, &d
[i
].ulink
,
190 __mutex_unlock (&_hurd_dtable_lock
);
195 ts
.tv_sec
= now
.tv_sec
;
196 ts
.tv_nsec
= now
.tv_usec
* 1000;
197 reply_msgid
= IO_SELECT_TIMEOUT_REPLY_MSGID
;
201 firstfd
= i
== 0 ? lastfd
: 0;
205 /* Collect interested descriptors from the user's fd_set arguments.
206 Use local copies so we can't crash from user bogosity. */
212 if (writefds
== NULL
)
216 if (exceptfds
== NULL
)
222 __mutex_lock (&_hurd_dtable_lock
);
224 /* Collect the ports for interesting FDs. */
225 firstfd
= lastfd
= -1;
226 for (i
= 0; i
< nfds
; ++i
)
229 if (readfds
!= NULL
&& FD_ISSET (i
, &rfds
))
231 if (writefds
!= NULL
&& FD_ISSET (i
, &wfds
))
232 type
|= SELECT_WRITE
;
233 if (exceptfds
!= NULL
&& FD_ISSET (i
, &xfds
))
238 if (i
< _hurd_dtablesize
)
240 d
[i
].cell
= _hurd_dtable
[i
];
241 if (d
[i
].cell
!= NULL
)
242 d
[i
].io_port
= _hurd_port_get (&d
[i
].cell
->port
,
245 if (i
>= _hurd_dtablesize
|| d
[i
].cell
== NULL
||
246 d
[i
].io_port
== MACH_PORT_NULL
)
248 /* If one descriptor is bogus, we fail completely. */
251 _hurd_port_free (&d
[i
].cell
->port
, &d
[i
].ulink
,
261 __mutex_unlock (&_hurd_dtable_lock
);
267 __sigprocmask (SIG_SETMASK
, &oset
, NULL
);
272 if (nfds
> _hurd_dtablesize
)
273 nfds
= _hurd_dtablesize
;
280 /* Send them all io_select request messages. */
283 /* But not if there were no ports to deal with at all.
284 We are just a pure timeout. */
285 portset
= __mach_reply_port ();
288 portset
= MACH_PORT_NULL
;
290 for (i
= firstfd
; i
<= lastfd
; ++i
)
291 if (!(d
[i
].type
& ~SELECT_ERROR
))
292 d
[i
].reply_port
= MACH_PORT_NULL
;
295 int type
= d
[i
].type
;
296 d
[i
].reply_port
= __mach_reply_port ();
298 err
= __io_select_request (d
[i
].io_port
, d
[i
].reply_port
, type
);
300 err
= __io_select_timeout_request (d
[i
].io_port
, d
[i
].reply_port
,
304 if (firstfd
== lastfd
)
305 /* When there's a single descriptor, we don't need a
306 portset, so just pretend we have one, but really
307 use the single reply port. */
308 portset
= d
[i
].reply_port
;
310 /* We've got multiple reply ports, so we need a port set to
313 /* We will wait again for a reply later. */
314 if (portset
== MACH_PORT_NULL
)
315 /* Create the portset to receive all the replies on. */
316 err
= __mach_port_allocate (__mach_task_self (),
317 MACH_PORT_RIGHT_PORT_SET
,
320 /* Put this reply port in the port set. */
321 __mach_port_move_member (__mach_task_self (),
322 d
[i
].reply_port
, portset
);
327 /* No error should happen, but record it for later
330 d
[i
].type
|= SELECT_ERROR
;
333 _hurd_port_free (&d
[i
].cell
->port
, &d
[i
].ulink
, d
[i
].io_port
);
337 /* GOT is the number of replies (or errors), while READY is the number of
338 replies with at least one type bit set. */
341 /* Now wait for reply messages. */
342 if (!err
&& got
== 0)
344 /* Now wait for io_select_reply messages on PORT,
345 timing out as appropriate. */
349 mach_msg_header_t head
;
350 #ifdef MACH_MSG_TRAILER_MINIMUM_SIZE
353 mach_msg_header_t head
;
359 mach_msg_header_t head
;
363 mach_msg_trailer_t trailer
;
368 mach_msg_header_t head
;
369 union typeword err_type
;
374 mach_msg_header_t head
;
375 union typeword err_type
;
377 union typeword result_type
;
382 mach_msg_option_t options
;
385 /* We rely on servers to implement the timeout, but when there are none,
386 do it on the client side. */
387 if (timeout
!= NULL
&& firstfd
== -1)
389 options
= MACH_RCV_TIMEOUT
;
390 to
= timeout
->tv_sec
* 1000 + (timeout
->tv_nsec
+ 999999) / 1000000;
395 to
= MACH_MSG_TIMEOUT_NONE
;
398 while ((msgerr
= __mach_msg (&msg
.head
,
399 MACH_RCV_MSG
| MACH_RCV_INTERRUPT
| options
,
400 0, sizeof msg
, portset
, to
,
401 MACH_PORT_NULL
)) == MACH_MSG_SUCCESS
)
403 /* We got a message. Decode it. */
404 #ifdef MACH_MSG_TYPE_BIT
405 const union typeword inttype
=
407 { MACH_MSG_TYPE_INTEGER_T
, sizeof (integer_t
) * 8, 1, 1, 0, 0 }
410 if (msg
.head
.msgh_id
== reply_msgid
411 && msg
.head
.msgh_size
>= sizeof msg
.error
412 && !(msg
.head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
)
413 #ifdef MACH_MSG_TYPE_BIT
414 && msg
.error
.err_type
.word
== inttype
.word
418 /* This is a properly formatted message so far.
419 See if it is a success or a failure. */
420 if (msg
.error
.err
== EINTR
421 && msg
.head
.msgh_size
== sizeof msg
.error
)
423 /* EINTR response; poll for further responses
424 and then return quickly. */
428 /* Keep in mind msg.success.result can be 0 if a timeout
431 #ifdef MACH_MSG_TYPE_BIT
432 || msg
.success
.result_type
.word
!= inttype
.word
434 || msg
.head
.msgh_size
!= sizeof msg
.success
)
436 /* Error or bogus reply. */
439 __mach_msg_destroy (&msg
.head
);
442 /* Look up the respondent's reply port and record its
447 for (i
= firstfd
; i
<= lastfd
; ++i
)
449 && d
[i
].reply_port
== msg
.head
.msgh_local_port
)
453 d
[i
].error
= msg
.error
.err
;
454 d
[i
].type
= SELECT_ERROR
;
459 d
[i
].type
&= msg
.success
.result
;
464 d
[i
].type
|= SELECT_RETURNED
;
471 if (msg
.head
.msgh_remote_port
!= MACH_PORT_NULL
)
472 __mach_port_deallocate (__mach_task_self (),
473 msg
.head
.msgh_remote_port
);
478 /* Poll for another message. */
480 options
|= MACH_RCV_TIMEOUT
;
484 if (msgerr
== MACH_RCV_INTERRUPTED
)
485 /* Interruption on our side (e.g. signal reception). */
489 /* At least one descriptor is known to be ready now, so we will
495 for (i
= firstfd
; i
<= lastfd
; ++i
)
496 if (d
[i
].reply_port
!= MACH_PORT_NULL
)
497 __mach_port_destroy (__mach_task_self (), d
[i
].reply_port
);
498 if (firstfd
== -1 || (firstfd
!= lastfd
&& portset
!= MACH_PORT_NULL
))
499 /* Destroy PORTSET, but only if it's not actually the reply port for a
500 single descriptor (in which case it's destroyed in the previous loop;
501 not doing it here is just a bit more efficient). */
502 __mach_port_destroy (__mach_task_self (), portset
);
507 __sigprocmask (SIG_SETMASK
, &oset
, NULL
);
508 return __hurd_fail (err
);
512 /* Fill in the `revents' members of the user's array. */
513 for (i
= 0; i
< nfds
; ++i
)
515 int type
= d
[i
].type
;
516 int_fast16_t revents
= 0;
518 if (type
& SELECT_ERROR
)
532 if (type
& SELECT_RETURNED
)
534 if (type
& SELECT_READ
)
536 if (type
& SELECT_WRITE
)
538 if (type
& SELECT_URG
)
542 pollfds
[i
].revents
= revents
;
546 /* Below we recalculate READY to include an increment for each operation
547 allowed on each fd. */
550 /* Set the user bitarrays. We only ever have to clear bits, as all
551 desired ones are initially set. */
553 for (i
= firstfd
; i
<= lastfd
; ++i
)
555 int type
= d
[i
].type
;
557 if ((type
& SELECT_RETURNED
) == 0)
560 /* Callers of select don't expect to see errors, so we simulate
561 readiness of the erring object and the next call hopefully
562 will get the error again. */
563 if (type
& SELECT_ERROR
)
566 if (readfds
!= NULL
&& FD_ISSET (i
, readfds
))
568 if (writefds
!= NULL
&& FD_ISSET (i
, writefds
))
569 type
|= SELECT_WRITE
;
570 if (exceptfds
!= NULL
&& FD_ISSET (i
, exceptfds
))
574 if (type
& SELECT_READ
)
578 if (type
& SELECT_WRITE
)
581 FD_CLR (i
, writefds
);
582 if (type
& SELECT_URG
)
585 FD_CLR (i
, exceptfds
);
589 if (sigmask
&& __sigprocmask (SIG_SETMASK
, &oset
, NULL
))