summaryrefslogtreecommitdiff
path: root/sysdeps/mach/hurd/select.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/hurd/select.c')
-rw-r--r--sysdeps/mach/hurd/select.c191
1 files changed, 102 insertions, 89 deletions
diff --git a/sysdeps/mach/hurd/select.c b/sysdeps/mach/hurd/select.c
index 60bb489612..aa99944e84 100644
--- a/sysdeps/mach/hurd/select.c
+++ b/sysdeps/mach/hurd/select.c
@@ -117,67 +117,76 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
return -1;
/* Send them all io_select request messages. */
- err = 0;
- got = 0;
- portset = MACH_PORT_NULL;
- for (i = firstfd; i <= lastfd; ++i)
- if (d[i].type)
- {
- int type = d[i].type;
- d[i].reply_port = __mach_reply_port ();
- err = __io_select (d[i].io_port, d[i].reply_port,
- /* Poll only when there's a single descriptor. */
- (firstfd == lastfd) ? to : 0,
- &type);
- switch (err)
+
+ if (firstfd == -1)
+ /* But not if there were no ports to deal with at all. */
+ portset = __mach_reply_port ();
+ else
+ {
+ err = 0;
+ got = 0;
+ portset = MACH_PORT_NULL;
+
+ for (i = firstfd; i <= lastfd; ++i)
+ if (d[i].type)
{
- case MACH_RCV_TIMED_OUT:
- /* No immediate response. This is normal. */
- err = 0;
- if (firstfd == lastfd)
- /* When there's a single descriptor, we don't need a portset,
- so just pretend we have one, but really use the single reply
- port. */
- portset = d[i].reply_port;
- else if (got == 0)
- /* We've got multiple reply ports, so we need a port set to
- multiplex them. */
+ int type = d[i].type;
+ d[i].reply_port = __mach_reply_port ();
+ err = __io_select (d[i].io_port, d[i].reply_port,
+ /* Poll only if there's a single descriptor. */
+ (firstfd == lastfd) ? to : 0,
+ &type);
+ switch (err)
{
- /* We will wait again for a reply later. */
- if (portset == MACH_PORT_NULL)
- /* Create the portset to receive all the replies on. */
- err = __mach_port_allocate (__mach_task_self (),
- MACH_PORT_RIGHT_PORT_SET,
- &portset);
- if (! err)
- /* Put this reply port in the port set. */
- __mach_port_move_member (__mach_task_self (),
- d[i].reply_port, portset);
+ case MACH_RCV_TIMED_OUT:
+ /* No immediate response. This is normal. */
+ err = 0;
+ if (firstfd == lastfd)
+ /* When there's a single descriptor, we don't need a
+ portset, so just pretend we have one, but really
+ use the single reply port. */
+ portset = d[i].reply_port;
+ else if (got == 0)
+ /* We've got multiple reply ports, so we need a port set to
+ multiplex them. */
+ {
+ /* We will wait again for a reply later. */
+ if (portset == MACH_PORT_NULL)
+ /* Create the portset to receive all the replies on. */
+ err = __mach_port_allocate (__mach_task_self (),
+ MACH_PORT_RIGHT_PORT_SET,
+ &portset);
+ if (! err)
+ /* Put this reply port in the port set. */
+ __mach_port_move_member (__mach_task_self (),
+ d[i].reply_port, portset);
+ }
+ break;
+
+ default:
+ /* No other error should happen. Callers of select
+ don't expect to see errors, so we simulate
+ readiness of the erring object and the next call
+ hopefully will get the error again. */
+ type = SELECT_ALL;
+ /* FALLTHROUGH */
+
+ case 0:
+ /* We got an answer. */
+ if ((type & SELECT_ALL) == 0)
+ /* Bogus answer; treat like an error, as a fake positive. */
+ type = SELECT_ALL;
+
+ /* This port is already ready already. */
+ d[i].type &= type;
+ d[i].type |= SELECT_RETURNED;
+ ++got;
+ break;
}
- break;
-
- default:
- /* No other error should happen. Callers of select don't
- expect to see errors, so we simulate readiness of the erring
- object and the next call hopefully will get the error again. */
- type = SELECT_ALL;
- /* FALLTHROUGH */
-
- case 0:
- /* We got an answer. */
- if ((type & SELECT_ALL) == 0)
- /* Bogus answer; treat like an error, as a fake positive. */
- type = SELECT_ALL;
-
- /* This port is already ready already. */
- d[i].type &= type;
- d[i].type |= SELECT_RETURNED;
- ++got;
- break;
+ _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
}
- _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
- }
-
+ }
+
/* Now wait for reply messages. */
if (!err && got == 0)
{
@@ -234,7 +243,7 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
(msg.success.result & SELECT_ALL) == 0)
{
/* Error or bogus reply. Simulate readiness. */
- __mach_msg_destroy (&msg);
+ __mach_msg_destroy (&msg.head);
msg.success.result = SELECT_ALL;
}
@@ -242,13 +251,15 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
readiness. */
{
int had = got;
- for (i = firstfd; i <= lastfd; ++i)
- if (d[i].type && d[i].reply_port == msg.head.msgh_local_port)
- {
- d[i].type &= msg.success.result;
- d[i].type |= SELECT_RETURNED;
- ++got;
- }
+ if (firstfd != -1)
+ for (i = firstfd; i <= lastfd; ++i)
+ if (d[i].type
+ && d[i].reply_port == msg.head.msgh_local_port)
+ {
+ d[i].type &= msg.success.result;
+ d[i].type |= SELECT_RETURNED;
+ ++got;
+ }
assert (got > had);
}
}
@@ -280,10 +291,11 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
err = 0;
}
- for (i = firstfd; i <= lastfd; ++i)
- if (d[i].type)
- __mach_port_destroy (__mach_task_self (), d[i].reply_port);
- if (firstfd != lastfd && portset != MACH_PORT_NULL)
+ if (firstfd != -1)
+ for (i = firstfd; i <= lastfd; ++i)
+ if (d[i].type)
+ __mach_port_destroy (__mach_task_self (), d[i].reply_port);
+ if (firstfd == -1 || (firstfd != lastfd && portset != MACH_PORT_NULL))
/* Destroy PORTSET, but only if it's not actually the reply port for a
single descriptor (in which case it's destroyed in the previous loop;
not doing it here is just a bit more efficient). */
@@ -298,26 +310,27 @@ DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
/* Set the user bitarrays. We only ever have to clear bits, as all desired
ones are initially set. */
- for (i = firstfd; i <= lastfd; ++i)
- {
- int type = d[i].type;
-
- if ((type & SELECT_RETURNED) == 0)
- type = 0;
-
- if (type & SELECT_READ)
- got++;
- else if (readfds)
- FD_CLR (i, readfds);
- if (type & SELECT_WRITE)
- got++;
- else if (writefds)
- FD_CLR (i, writefds);
- if (type & SELECT_URG)
- got++;
- else if (exceptfds)
- FD_CLR (i, exceptfds);
- }
+ if (firstfd != -1)
+ for (i = firstfd; i <= lastfd; ++i)
+ {
+ int type = d[i].type;
+
+ if ((type & SELECT_RETURNED) == 0)
+ type = 0;
+
+ if (type & SELECT_READ)
+ got++;
+ else if (readfds)
+ FD_CLR (i, readfds);
+ if (type & SELECT_WRITE)
+ got++;
+ else if (writefds)
+ FD_CLR (i, writefds);
+ if (type & SELECT_URG)
+ got++;
+ else if (exceptfds)
+ FD_CLR (i, exceptfds);
+ }
return got;
}