summaryrefslogtreecommitdiff
path: root/hurd/intr-msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'hurd/intr-msg.c')
-rw-r--r--hurd/intr-msg.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/hurd/intr-msg.c b/hurd/intr-msg.c
index ae997b2bb2..e75fca81fb 100644
--- a/hurd/intr-msg.c
+++ b/hurd/intr-msg.c
@@ -1,5 +1,5 @@
/* Replacement for mach_msg used in interruptible Hurd RPCs.
- Copyright (C) 95,96,97,98,99,2000,01 Free Software Foundation, Inc.
+ Copyright (C) 1995,96,97,98,99,2000,01,02 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,6 +25,9 @@
#include "intr-msg.h"
+#ifdef NDR_CHAR_ASCII /* OSF Mach flavors have different names. */
+# define mig_reply_header_t mig_reply_error_t
+#endif
error_t
_hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
@@ -40,7 +43,15 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
const mach_msg_option_t user_option = option;
const mach_msg_timeout_t user_timeout = timeout;
- struct clobber { int i[2]; };
+ struct clobber
+ {
+#ifdef NDR_CHAR_ASCII
+ NDR_record_t ndr;
+#else
+ mach_msg_type_t type;
+#endif
+ error_t err;
+ };
union msg
{
mach_msg_header_t header;
@@ -48,7 +59,11 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
struct
{
mach_msg_header_t header;
+#ifdef NDR_CHAR_ASCII
+ NDR_record_t ndr;
+#else
int type;
+#endif
int code;
} check;
struct
@@ -147,8 +162,12 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
the message buffer and we might need to clean up the port rights. */
case MACH_SEND_TIMED_OUT:
case MACH_SEND_INVALID_NOTIFY:
+#ifdef MACH_SEND_NO_NOTIFY
case MACH_SEND_NO_NOTIFY:
+#endif
+#ifdef MACH_SEND_NOTIFY_IN_PROGRESS
case MACH_SEND_NOTIFY_IN_PROGRESS:
+#endif
if (MACH_MSGH_BITS_REMOTE (msg->msgh_bits) == MACH_MSG_TYPE_MOVE_SEND)
{
__mach_port_deallocate (__mach_task_self (), msg->msgh_remote_port);
@@ -159,6 +178,7 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
}
if (msg->msgh_bits & MACH_MSGH_BITS_COMPLEX)
{
+#ifndef MACH_MSG_PORT_DESCRIPTOR
/* Check for MOVE_SEND rights in the message. These hold refs
that we need to release in case the message is in fact never
re-sent later. Since it might in fact be re-sent, we turn
@@ -228,6 +248,62 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
++(void **) ty;
}
}
+#else /* Untyped Mach IPC flavor. */
+ mach_msg_body_t *body = (void *) (msg + 1);
+ mach_msg_descriptor_t *desc = (void *) (body + 1);
+ mach_msg_descriptor_t *desc_end = desc + body->msgh_descriptor_count;
+ for (; desc < desc_end; ++desc)
+ switch (desc->type.type)
+ {
+ case MACH_MSG_PORT_DESCRIPTOR:
+ switch (desc->port.disposition)
+ {
+ case MACH_MSG_TYPE_MOVE_SEND:
+ __mach_port_deallocate (mach_task_self (),
+ desc->port.name);
+ desc->port.disposition = MACH_MSG_TYPE_COPY_SEND;
+ break;
+ case MACH_MSG_TYPE_COPY_SEND:
+ case MACH_MSG_TYPE_MOVE_RECEIVE:
+ break;
+ default:
+ assert (! "unexpected port type in interruptible RPC");
+ }
+ break;
+ case MACH_MSG_OOL_DESCRIPTOR:
+ if (desc->out_of_line.deallocate)
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) desc->out_of_line.address,
+ desc->out_of_line.size);
+ break;
+ case MACH_MSG_OOL_PORTS_DESCRIPTOR:
+ switch (desc->ool_ports.disposition)
+ {
+ case MACH_MSG_TYPE_MOVE_SEND:
+ {
+ mach_msg_size_t i;
+ const mach_port_t *ports = desc->ool_ports.address;
+ for (i = 0; i < desc->ool_ports.count; ++i)
+ __mach_port_deallocate (__mach_task_self (), ports[i]);
+ desc->ool_ports.disposition = MACH_MSG_TYPE_COPY_SEND;
+ break;
+ }
+ case MACH_MSG_TYPE_COPY_SEND:
+ case MACH_MSG_TYPE_MOVE_RECEIVE:
+ break;
+ default:
+ assert (! "unexpected port type in interruptible RPC");
+ }
+ if (desc->ool_ports.deallocate)
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) desc->ool_ports.address,
+ desc->ool_ports.count
+ * sizeof (mach_port_t));
+ break;
+ default:
+ assert (! "unexpected descriptor type in interruptible RPC");
+ }
+#endif
}
break;
@@ -285,6 +361,7 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
case MACH_MSG_SUCCESS:
{
/* We got a reply. Was it EINTR? */
+#ifdef MACH_MSG_TYPE_BIT
const union
{
mach_msg_type_t t;
@@ -292,10 +369,13 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
} check =
{ t: { MACH_MSG_TYPE_INTEGER_T, sizeof (integer_t) * 8,
1, TRUE, FALSE, FALSE, 0 } };
+#endif
if (m->reply.RetCode == EINTR &&
m->header.msgh_size == sizeof m->reply &&
+#ifdef MACH_MSG_TYPE_BIT
m->check.type == check.i &&
+#endif
!(m->header.msgh_bits & MACH_MSGH_BITS_COMPLEX))
{
/* It is indeed EINTR. Is the interrupt for us? */