1 /* Guts of both `select' and `poll' for Hurd.
2 Copyright (C) 1991,92,93,94,95,96,97,98,99,2001
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 #include <sys/types.h>
30 /* All user select types. */
31 #define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
33 /* Used to record that a particular select rpc returned. Must be distinct
34 from SELECT_ALL (which better not have the high bit set). */
35 #define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
37 /* Check the first NFDS descriptors either in POLLFDS (if nonnnull) or in
38 each of READFDS, WRITEFDS, EXCEPTFDS that is nonnull. If TIMEOUT is not
39 NULL, time out after waiting the interval specified therein. Returns
40 the number of ready descriptors, or -1 for errors. */
42 _hurd_select (int nfds
,
43 struct pollfd
*pollfds
,
44 fd_set
*readfds
, fd_set
*writefds
, fd_set
*exceptfds
,
45 const struct timespec
*timeout
, const sigset_t
*sigmask
)
51 fd_set rfds
, wfds
, xfds
;
53 mach_msg_timeout_t to
= (timeout
!= NULL
?
54 (timeout
->tv_sec
* 1000 +
55 timeout
->tv_nsec
/ 1000000) :
59 struct hurd_userlink ulink
;
63 mach_port_t reply_port
;
67 union typeword
/* Use this to avoid unkosher casts. */
72 assert (sizeof (union typeword
) == sizeof (mach_msg_type_t
));
73 assert (sizeof (uint32_t) == sizeof (mach_msg_type_t
));
75 if (sigmask
&& __sigprocmask (SIG_SETMASK
, sigmask
, &oset
))
80 /* Collect interesting descriptors from the user's `pollfd' array.
81 We do a first pass that reads the user's array before taking
82 any locks. The second pass then only touches our own stack,
83 and gets the port references. */
85 for (i
= 0; i
< nfds
; ++i
)
86 if (pollfds
[i
].fd
>= 0)
89 if (pollfds
[i
].events
& POLLIN
)
91 if (pollfds
[i
].events
& POLLOUT
)
93 if (pollfds
[i
].events
& POLLPRI
)
96 d
[i
].io_port
= pollfds
[i
].fd
;
103 __mutex_lock (&_hurd_dtable_lock
);
105 for (i
= 0; i
< nfds
; ++i
)
108 const int fd
= (int) d
[i
].io_port
;
110 if (fd
< _hurd_dtablesize
)
112 d
[i
].cell
= _hurd_dtable
[fd
];
113 d
[i
].io_port
= _hurd_port_get (&d
[i
].cell
->port
, &d
[i
].ulink
);
114 if (d
[i
].io_port
!= MACH_PORT_NULL
)
118 /* If one descriptor is bogus, we fail completely. */
121 _hurd_port_free (&d
[i
].cell
->port
,
122 &d
[i
].ulink
, d
[i
].io_port
);
126 __mutex_unlock (&_hurd_dtable_lock
);
132 __sigprocmask (SIG_SETMASK
, &oset
, NULL
);
138 firstfd
= i
== 0 ? lastfd
: 0;
142 /* Collect interested descriptors from the user's fd_set arguments.
143 Use local copies so we can't crash from user bogosity. */
149 if (writefds
== NULL
)
153 if (exceptfds
== NULL
)
159 __mutex_lock (&_hurd_dtable_lock
);
161 if (nfds
> _hurd_dtablesize
)
162 nfds
= _hurd_dtablesize
;
164 /* Collect the ports for interesting FDs. */
165 firstfd
= lastfd
= -1;
166 for (i
= 0; i
< nfds
; ++i
)
169 if (readfds
!= NULL
&& FD_ISSET (i
, &rfds
))
171 if (writefds
!= NULL
&& FD_ISSET (i
, &wfds
))
172 type
|= SELECT_WRITE
;
173 if (exceptfds
!= NULL
&& FD_ISSET (i
, &xfds
))
178 d
[i
].cell
= _hurd_dtable
[i
];
179 d
[i
].io_port
= _hurd_port_get (&d
[i
].cell
->port
, &d
[i
].ulink
);
180 if (d
[i
].io_port
== MACH_PORT_NULL
)
182 /* If one descriptor is bogus, we fail completely. */
185 _hurd_port_free (&d
[i
].cell
->port
, &d
[i
].ulink
,
195 __mutex_unlock (&_hurd_dtable_lock
);
201 __sigprocmask (SIG_SETMASK
, &oset
, NULL
);
211 /* Send them all io_select request messages. */
214 /* But not if there were no ports to deal with at all.
215 We are just a pure timeout. */
216 portset
= __mach_reply_port ();
219 portset
= MACH_PORT_NULL
;
221 for (i
= firstfd
; i
<= lastfd
; ++i
)
224 int type
= d
[i
].type
;
225 d
[i
].reply_port
= __mach_reply_port ();
226 err
= __io_select (d
[i
].io_port
, d
[i
].reply_port
,
227 /* Poll only if there's a single descriptor. */
228 (firstfd
== lastfd
) ? to
: 0,
232 case MACH_RCV_TIMED_OUT
:
233 /* No immediate response. This is normal. */
235 if (firstfd
== lastfd
)
236 /* When there's a single descriptor, we don't need a
237 portset, so just pretend we have one, but really
238 use the single reply port. */
239 portset
= d
[i
].reply_port
;
241 /* We've got multiple reply ports, so we need a port set to
244 /* We will wait again for a reply later. */
245 if (portset
== MACH_PORT_NULL
)
246 /* Create the portset to receive all the replies on. */
247 err
= __mach_port_allocate (__mach_task_self (),
248 MACH_PORT_RIGHT_PORT_SET
,
251 /* Put this reply port in the port set. */
252 __mach_port_move_member (__mach_task_self (),
253 d
[i
].reply_port
, portset
);
258 /* No other error should happen. Callers of select
259 don't expect to see errors, so we simulate
260 readiness of the erring object and the next call
261 hopefully will get the error again. */
266 /* We got an answer. */
267 if ((type
& SELECT_ALL
) == 0)
268 /* Bogus answer; treat like an error, as a fake positive. */
271 /* This port is already ready already. */
273 d
[i
].type
|= SELECT_RETURNED
;
277 _hurd_port_free (&d
[i
].cell
->port
, &d
[i
].ulink
, d
[i
].io_port
);
281 /* Now wait for reply messages. */
282 if (!err
&& got
== 0)
284 /* Now wait for io_select_reply messages on PORT,
285 timing out as appropriate. */
289 mach_msg_header_t head
;
290 #ifdef MACH_MSG_TRAILER_MINIMUM_SIZE
293 mach_msg_header_t head
;
299 mach_msg_header_t head
;
303 mach_msg_trailer_t trailer
;
308 mach_msg_header_t head
;
309 union typeword err_type
;
314 mach_msg_header_t head
;
315 union typeword err_type
;
317 union typeword result_type
;
322 mach_msg_option_t options
= (timeout
== NULL
? 0 : MACH_RCV_TIMEOUT
);
324 while ((msgerr
= __mach_msg (&msg
.head
,
325 MACH_RCV_MSG
| options
,
326 0, sizeof msg
, portset
, to
,
327 MACH_PORT_NULL
)) == MACH_MSG_SUCCESS
)
329 /* We got a message. Decode it. */
330 #define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
331 #ifdef MACH_MSG_TYPE_BIT
332 const union typeword inttype
=
334 { MACH_MSG_TYPE_INTEGER_T
, sizeof (integer_t
) * 8, 1, 1, 0, 0 }
337 if (msg
.head
.msgh_id
== IO_SELECT_REPLY_MSGID
&&
338 msg
.head
.msgh_size
>= sizeof msg
.error
&&
339 !(msg
.head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
) &&
340 #ifdef MACH_MSG_TYPE_BIT
341 msg
.error
.err_type
.word
== inttype
.word
345 /* This is a properly formatted message so far.
346 See if it is a success or a failure. */
347 if (msg
.error
.err
== EINTR
&&
348 msg
.head
.msgh_size
== sizeof msg
.error
)
350 /* EINTR response; poll for further responses
351 and then return quickly. */
356 msg
.head
.msgh_size
!= sizeof msg
.success
||
357 #ifdef MACH_MSG_TYPE_BIT
358 msg
.success
.result_type
.word
!= inttype
.word
||
360 (msg
.success
.result
& SELECT_ALL
) == 0)
362 /* Error or bogus reply. Simulate readiness. */
363 __mach_msg_destroy (&msg
.head
);
364 msg
.success
.result
= SELECT_ALL
;
367 /* Look up the respondent's reply port and record its
372 for (i
= firstfd
; i
<= lastfd
; ++i
)
374 && d
[i
].reply_port
== msg
.head
.msgh_local_port
)
376 d
[i
].type
&= msg
.success
.result
;
377 d
[i
].type
|= SELECT_RETURNED
;
384 if (msg
.head
.msgh_remote_port
!= MACH_PORT_NULL
)
385 __mach_port_deallocate (__mach_task_self (),
386 msg
.head
.msgh_remote_port
);
391 /* Poll for another message. */
393 options
|= MACH_RCV_TIMEOUT
;
397 if (err
== MACH_RCV_TIMED_OUT
)
398 /* This is the normal value for ERR. We might have timed out and
399 read no messages. Otherwise, after receiving the first message,
400 we poll for more messages. We receive with a timeout of 0 to
401 effect a poll, so ERR is MACH_RCV_TIMED_OUT when the poll finds no
406 /* At least one descriptor is known to be ready now, so we will
412 for (i
= firstfd
; i
<= lastfd
; ++i
)
414 __mach_port_destroy (__mach_task_self (), d
[i
].reply_port
);
415 if (firstfd
== -1 || (firstfd
!= lastfd
&& portset
!= MACH_PORT_NULL
))
416 /* Destroy PORTSET, but only if it's not actually the reply port for a
417 single descriptor (in which case it's destroyed in the previous loop;
418 not doing it here is just a bit more efficient). */
419 __mach_port_destroy (__mach_task_self (), portset
);
424 __sigprocmask (SIG_SETMASK
, &oset
, NULL
);
425 return __hurd_fail (err
);
429 /* Fill in the `revents' members of the user's array. */
430 for (i
= 0; i
< nfds
; ++i
)
432 int type
= d
[i
].type
;
433 int_fast16_t revents
= 0;
435 if (type
& SELECT_RETURNED
)
437 if (type
& SELECT_READ
)
439 if (type
& SELECT_WRITE
)
441 if (type
& SELECT_URG
)
445 pollfds
[i
].revents
= revents
;
449 /* Below we recalculate GOT to include an increment for each operation
450 allowed on each fd. */
453 /* Set the user bitarrays. We only ever have to clear bits, as all
454 desired ones are initially set. */
456 for (i
= firstfd
; i
<= lastfd
; ++i
)
458 int type
= d
[i
].type
;
460 if ((type
& SELECT_RETURNED
) == 0)
463 if (type
& SELECT_READ
)
467 if (type
& SELECT_WRITE
)
470 FD_CLR (i
, writefds
);
471 if (type
& SELECT_URG
)
474 FD_CLR (i
, exceptfds
);
478 if (sigmask
&& __sigprocmask (SIG_SETMASK
, &oset
, NULL
))