1 /* Guts of both `select' and `poll' for Hurd.
2 Copyright (C) 1991-2017 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 <http://www.gnu.org/licenses/>. */
19 #include <sys/types.h>
28 /* All user select types. */
29 #define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
31 /* Used to record that a particular select rpc returned. Must be distinct
32 from SELECT_ALL (which better not have the high bit set). */
33 #define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
35 /* Check the first NFDS descriptors either in POLLFDS (if nonnnull) or in
36 each of READFDS, WRITEFDS, EXCEPTFDS that is nonnull. If TIMEOUT is not
37 NULL, time out after waiting the interval specified therein. Returns
38 the number of ready descriptors, or -1 for errors. */
40 _hurd_select (int nfds
,
41 struct pollfd
*pollfds
,
42 fd_set
*readfds
, fd_set
*writefds
, fd_set
*exceptfds
,
43 const struct timespec
*timeout
, const sigset_t
*sigmask
)
49 fd_set rfds
, wfds
, xfds
;
51 mach_msg_timeout_t to
= 0;
54 struct hurd_userlink ulink
;
58 mach_port_t reply_port
;
62 union typeword
/* Use this to avoid unkosher casts. */
67 assert (sizeof (union typeword
) == sizeof (mach_msg_type_t
));
68 assert (sizeof (uint32_t) == sizeof (mach_msg_type_t
));
70 if (nfds
< 0 || (pollfds
== NULL
&& nfds
> FD_SETSIZE
))
78 if (timeout
->tv_sec
< 0 || timeout
->tv_nsec
< 0)
84 to
= (timeout
->tv_sec
* 1000 +
85 (timeout
->tv_nsec
+ 999999) / 1000000);
88 if (sigmask
&& __sigprocmask (SIG_SETMASK
, sigmask
, &oset
))
93 /* Collect interesting descriptors from the user's `pollfd' array.
94 We do a first pass that reads the user's array before taking
95 any locks. The second pass then only touches our own stack,
96 and gets the port references. */
98 for (i
= 0; i
< nfds
; ++i
)
99 if (pollfds
[i
].fd
>= 0)
102 if (pollfds
[i
].events
& POLLIN
)
104 if (pollfds
[i
].events
& POLLOUT
)
105 type
|= SELECT_WRITE
;
106 if (pollfds
[i
].events
& POLLPRI
)
109 d
[i
].io_port
= pollfds
[i
].fd
;
116 __mutex_lock (&_hurd_dtable_lock
);
118 for (i
= 0; i
< nfds
; ++i
)
121 const int fd
= (int) d
[i
].io_port
;
123 if (fd
< _hurd_dtablesize
)
125 d
[i
].cell
= _hurd_dtable
[fd
];
126 d
[i
].io_port
= _hurd_port_get (&d
[i
].cell
->port
, &d
[i
].ulink
);
127 if (d
[i
].io_port
!= MACH_PORT_NULL
)
131 /* If one descriptor is bogus, we fail completely. */
134 _hurd_port_free (&d
[i
].cell
->port
,
135 &d
[i
].ulink
, d
[i
].io_port
);
139 __mutex_unlock (&_hurd_dtable_lock
);
145 __sigprocmask (SIG_SETMASK
, &oset
, NULL
);
151 firstfd
= i
== 0 ? lastfd
: 0;
155 /* Collect interested descriptors from the user's fd_set arguments.
156 Use local copies so we can't crash from user bogosity. */
162 if (writefds
== NULL
)
166 if (exceptfds
== NULL
)
172 __mutex_lock (&_hurd_dtable_lock
);
174 if (nfds
> _hurd_dtablesize
)
175 nfds
= _hurd_dtablesize
;
177 /* Collect the ports for interesting FDs. */
178 firstfd
= lastfd
= -1;
179 for (i
= 0; i
< nfds
; ++i
)
182 if (readfds
!= NULL
&& FD_ISSET (i
, &rfds
))
184 if (writefds
!= NULL
&& FD_ISSET (i
, &wfds
))
185 type
|= SELECT_WRITE
;
186 if (exceptfds
!= NULL
&& FD_ISSET (i
, &xfds
))
191 d
[i
].cell
= _hurd_dtable
[i
];
192 d
[i
].io_port
= _hurd_port_get (&d
[i
].cell
->port
, &d
[i
].ulink
);
193 if (d
[i
].io_port
== MACH_PORT_NULL
)
195 /* If one descriptor is bogus, we fail completely. */
198 _hurd_port_free (&d
[i
].cell
->port
, &d
[i
].ulink
,
208 __mutex_unlock (&_hurd_dtable_lock
);
214 __sigprocmask (SIG_SETMASK
, &oset
, NULL
);
224 /* Send them all io_select request messages. */
227 /* But not if there were no ports to deal with at all.
228 We are just a pure timeout. */
229 portset
= __mach_reply_port ();
232 portset
= MACH_PORT_NULL
;
234 for (i
= firstfd
; i
<= lastfd
; ++i
)
237 int type
= d
[i
].type
;
238 d
[i
].reply_port
= __mach_reply_port ();
239 err
= __io_select (d
[i
].io_port
, d
[i
].reply_port
,
240 /* Poll only if there's a single descriptor. */
241 (firstfd
== lastfd
) ? to
: 0,
245 case MACH_RCV_TIMED_OUT
:
246 /* No immediate response. This is normal. */
248 if (firstfd
== lastfd
)
249 /* When there's a single descriptor, we don't need a
250 portset, so just pretend we have one, but really
251 use the single reply port. */
252 portset
= d
[i
].reply_port
;
254 /* We've got multiple reply ports, so we need a port set to
257 /* We will wait again for a reply later. */
258 if (portset
== MACH_PORT_NULL
)
259 /* Create the portset to receive all the replies on. */
260 err
= __mach_port_allocate (__mach_task_self (),
261 MACH_PORT_RIGHT_PORT_SET
,
264 /* Put this reply port in the port set. */
265 __mach_port_move_member (__mach_task_self (),
266 d
[i
].reply_port
, portset
);
271 /* No other error should happen. Callers of select
272 don't expect to see errors, so we simulate
273 readiness of the erring object and the next call
274 hopefully will get the error again. */
279 /* We got an answer. */
280 if ((type
& SELECT_ALL
) == 0)
281 /* Bogus answer; treat like an error, as a fake positive. */
284 /* This port is already ready already. */
286 d
[i
].type
|= SELECT_RETURNED
;
290 _hurd_port_free (&d
[i
].cell
->port
, &d
[i
].ulink
, d
[i
].io_port
);
294 /* Now wait for reply messages. */
295 if (!err
&& got
== 0)
297 /* Now wait for io_select_reply messages on PORT,
298 timing out as appropriate. */
302 mach_msg_header_t head
;
303 #ifdef MACH_MSG_TRAILER_MINIMUM_SIZE
306 mach_msg_header_t head
;
312 mach_msg_header_t head
;
316 mach_msg_trailer_t trailer
;
321 mach_msg_header_t head
;
322 union typeword err_type
;
327 mach_msg_header_t head
;
328 union typeword err_type
;
330 union typeword result_type
;
335 mach_msg_option_t options
= (timeout
== NULL
? 0 : MACH_RCV_TIMEOUT
);
337 while ((msgerr
= __mach_msg (&msg
.head
,
338 MACH_RCV_MSG
| MACH_RCV_INTERRUPT
| options
,
339 0, sizeof msg
, portset
, to
,
340 MACH_PORT_NULL
)) == MACH_MSG_SUCCESS
)
342 /* We got a message. Decode it. */
343 #define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
344 #ifdef MACH_MSG_TYPE_BIT
345 const union typeword inttype
=
347 { MACH_MSG_TYPE_INTEGER_T
, sizeof (integer_t
) * 8, 1, 1, 0, 0 }
350 if (msg
.head
.msgh_id
== IO_SELECT_REPLY_MSGID
&&
351 msg
.head
.msgh_size
>= sizeof msg
.error
&&
352 !(msg
.head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
) &&
353 #ifdef MACH_MSG_TYPE_BIT
354 msg
.error
.err_type
.word
== inttype
.word
358 /* This is a properly formatted message so far.
359 See if it is a success or a failure. */
360 if (msg
.error
.err
== EINTR
&&
361 msg
.head
.msgh_size
== sizeof msg
.error
)
363 /* EINTR response; poll for further responses
364 and then return quickly. */
369 msg
.head
.msgh_size
!= sizeof msg
.success
||
370 #ifdef MACH_MSG_TYPE_BIT
371 msg
.success
.result_type
.word
!= inttype
.word
||
373 (msg
.success
.result
& SELECT_ALL
) == 0)
375 /* Error or bogus reply. Simulate readiness. */
376 __mach_msg_destroy (&msg
.head
);
377 msg
.success
.result
= SELECT_ALL
;
380 /* Look up the respondent's reply port and record its
385 for (i
= firstfd
; i
<= lastfd
; ++i
)
387 && d
[i
].reply_port
== msg
.head
.msgh_local_port
)
389 d
[i
].type
&= msg
.success
.result
;
390 d
[i
].type
|= SELECT_RETURNED
;
397 if (msg
.head
.msgh_remote_port
!= MACH_PORT_NULL
)
398 __mach_port_deallocate (__mach_task_self (),
399 msg
.head
.msgh_remote_port
);
404 /* Poll for another message. */
406 options
|= MACH_RCV_TIMEOUT
;
410 if (msgerr
== MACH_RCV_INTERRUPTED
)
411 /* Interruption on our side (e.g. signal reception). */
415 /* At least one descriptor is known to be ready now, so we will
421 for (i
= firstfd
; i
<= lastfd
; ++i
)
423 __mach_port_destroy (__mach_task_self (), d
[i
].reply_port
);
424 if (firstfd
== -1 || (firstfd
!= lastfd
&& portset
!= MACH_PORT_NULL
))
425 /* Destroy PORTSET, but only if it's not actually the reply port for a
426 single descriptor (in which case it's destroyed in the previous loop;
427 not doing it here is just a bit more efficient). */
428 __mach_port_destroy (__mach_task_self (), portset
);
433 __sigprocmask (SIG_SETMASK
, &oset
, NULL
);
434 return __hurd_fail (err
);
438 /* Fill in the `revents' members of the user's array. */
439 for (i
= 0; i
< nfds
; ++i
)
441 int type
= d
[i
].type
;
442 int_fast16_t revents
= 0;
444 if (type
& SELECT_RETURNED
)
446 if (type
& SELECT_READ
)
448 if (type
& SELECT_WRITE
)
450 if (type
& SELECT_URG
)
454 pollfds
[i
].revents
= revents
;
458 /* Below we recalculate GOT to include an increment for each operation
459 allowed on each fd. */
462 /* Set the user bitarrays. We only ever have to clear bits, as all
463 desired ones are initially set. */
465 for (i
= firstfd
; i
<= lastfd
; ++i
)
467 int type
= d
[i
].type
;
469 if ((type
& SELECT_RETURNED
) == 0)
472 if (type
& SELECT_READ
)
476 if (type
& SELECT_WRITE
)
479 FD_CLR (i
, writefds
);
480 if (type
& SELECT_URG
)
483 FD_CLR (i
, exceptfds
);
487 if (sigmask
&& __sigprocmask (SIG_SETMASK
, &oset
, NULL
))