Blame hurd/intr-msg.c

Packit Service 82fcde
/* Replacement for mach_msg used in interruptible Hurd RPCs.
Packit Service 82fcde
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <mach.h>
Packit Service 82fcde
#include <mach/mig_errors.h>
Packit Service 82fcde
#include <mach/mig_support.h>
Packit Service 82fcde
#include <hurd/signal.h>
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
Packit Service 82fcde
#include "intr-msg.h"
Packit Service 82fcde
Packit Service 82fcde
#ifdef NDR_CHAR_ASCII		/* OSF Mach flavors have different names.  */
Packit Service 82fcde
# define mig_reply_header_t	mig_reply_error_t
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
error_t
Packit Service 82fcde
_hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
Packit Service 82fcde
			 mach_msg_option_t option,
Packit Service 82fcde
			 mach_msg_size_t send_size,
Packit Service 82fcde
			 mach_msg_size_t rcv_size,
Packit Service 82fcde
			 mach_port_t rcv_name,
Packit Service 82fcde
			 mach_msg_timeout_t timeout,
Packit Service 82fcde
			 mach_port_t notify)
Packit Service 82fcde
{
Packit Service 82fcde
  error_t err;
Packit Service 82fcde
  struct hurd_sigstate *ss;
Packit Service 82fcde
  const mach_msg_option_t user_option = option;
Packit Service 82fcde
  const mach_msg_timeout_t user_timeout = timeout;
Packit Service 82fcde
Packit Service 82fcde
  struct clobber
Packit Service 82fcde
  {
Packit Service 82fcde
#ifdef NDR_CHAR_ASCII
Packit Service 82fcde
    NDR_record_t ndr;
Packit Service 82fcde
#else
Packit Service 82fcde
    mach_msg_type_t type;
Packit Service 82fcde
#endif
Packit Service 82fcde
    error_t err;
Packit Service 82fcde
  };
Packit Service 82fcde
  union msg
Packit Service 82fcde
  {
Packit Service 82fcde
    mach_msg_header_t header;
Packit Service 82fcde
    mig_reply_header_t reply;
Packit Service 82fcde
    struct
Packit Service 82fcde
    {
Packit Service 82fcde
      mach_msg_header_t header;
Packit Service 82fcde
#ifdef NDR_CHAR_ASCII
Packit Service 82fcde
      NDR_record_t ndr;
Packit Service 82fcde
#else
Packit Service 82fcde
      int type;
Packit Service 82fcde
#endif
Packit Service 82fcde
      int code;
Packit Service 82fcde
    } check;
Packit Service 82fcde
    struct
Packit Service 82fcde
    {
Packit Service 82fcde
      mach_msg_header_t header;
Packit Service 82fcde
      struct clobber data;
Packit Service 82fcde
    } request;
Packit Service 82fcde
  };
Packit Service 82fcde
  union msg *const m = (void *) msg;
Packit Service 82fcde
  mach_msg_bits_t msgh_bits;
Packit Service 82fcde
  mach_port_t remote_port;
Packit Service 82fcde
  mach_msg_id_t msgid;
Packit Service 82fcde
  struct clobber save_data;
Packit Service 82fcde
Packit Service 82fcde
  if ((option & (MACH_SEND_MSG|MACH_RCV_MSG)) != (MACH_SEND_MSG|MACH_RCV_MSG)
Packit Service 82fcde
      || _hurd_msgport_thread == MACH_PORT_NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Either this is not an RPC (i.e., only a send or only a receive),
Packit Service 82fcde
	 so it can't be interruptible; or, the signal thread is not set up
Packit Service 82fcde
	 yet, so we cannot do the normal signal magic.  Do a normal,
Packit Service 82fcde
	 uninterruptible mach_msg call instead.  */
Packit Service 82fcde
      return __mach_msg (&m->header, option, send_size, rcv_size, rcv_name,
Packit Service 82fcde
			 timeout, notify);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  ss = _hurd_self_sigstate ();
Packit Service 82fcde
Packit Service 82fcde
  /* Save state that gets clobbered by an EINTR reply message.
Packit Service 82fcde
     We will need to restore it if we want to retry the RPC.  */
Packit Service 82fcde
  msgh_bits = m->header.msgh_bits;
Packit Service 82fcde
  remote_port = m->header.msgh_remote_port;
Packit Service 82fcde
  msgid = m->header.msgh_id;
Packit Service 82fcde
  assert (rcv_size >= sizeof m->request);
Packit Service 82fcde
  save_data = m->request.data;
Packit Service 82fcde
Packit Service 82fcde
  /* Tell the signal thread that we are doing an interruptible RPC on
Packit Service 82fcde
     this port.  If we get a signal and should return EINTR, the signal
Packit Service 82fcde
     thread will set this variable to MACH_PORT_NULL.  The RPC might
Packit Service 82fcde
     return EINTR when some other thread gets a signal, in which case we
Packit Service 82fcde
     want to restart our call.  */
Packit Service 82fcde
  ss->intr_port = m->header.msgh_remote_port;
Packit Service 82fcde
Packit Service 82fcde
  /* A signal may arrive here, after intr_port is set, but before the
Packit Service 82fcde
     mach_msg system call.  The signal handler might do an interruptible
Packit Service 82fcde
     RPC, and clobber intr_port; then it would not be set properly when we
Packit Service 82fcde
     actually did send the RPC, and a later signal wouldn't interrupt that
Packit Service 82fcde
     RPC.  So, _hurd_setup_sighandler saves intr_port in the sigcontext,
Packit Service 82fcde
     and sigreturn restores it.  */
Packit Service 82fcde
Packit Service 82fcde
 message:
Packit Service 82fcde
Packit Service 82fcde
  /* XXX
Packit Service 82fcde
     At all points here (once SS->intr_port is set), the signal thread
Packit Service 82fcde
     thinks we are "about to enter the syscall", and might mutate our
Packit Service 82fcde
     return-value register.  This is bogus.
Packit Service 82fcde
   */
Packit Service 82fcde
Packit Service 82fcde
  if (ss->cancel)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* We have been cancelled.  Don't do an RPC at all.  */
Packit Service 82fcde
      ss->intr_port = MACH_PORT_NULL;
Packit Service 82fcde
      ss->cancel = 0;
Packit Service 82fcde
      return EINTR;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Note that the signal trampoline code might modify our OPTION!  */
Packit Service 82fcde
  err = INTR_MSG_TRAP (msg, option, send_size,
Packit Service 82fcde
		       rcv_size, rcv_name, timeout, notify);
Packit Service 82fcde
Packit Service 82fcde
  switch (err)
Packit Service 82fcde
    {
Packit Service 82fcde
    case MACH_RCV_TIMED_OUT:
Packit Service 82fcde
      if (user_option & MACH_RCV_TIMEOUT)
Packit Service 82fcde
	/* The real user RPC timed out.  */
Packit Service 82fcde
	break;
Packit Service 82fcde
      else
Packit Service 82fcde
	/* The operation was supposedly interrupted, but still has
Packit Service 82fcde
	   not returned.  Declare it interrupted.  */
Packit Service 82fcde
	goto interrupted;
Packit Service 82fcde
Packit Service 82fcde
    case MACH_SEND_INTERRUPTED: /* RPC didn't get out.  */
Packit Service 82fcde
      if (!(option & MACH_SEND_MSG))
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Oh yes, it did!  Since we were not doing a message send,
Packit Service 82fcde
	     this return code cannot have come from the kernel!
Packit Service 82fcde
	     Instead, it was the signal thread mutating our state to tell
Packit Service 82fcde
	     us not to enter this RPC.  However, we are already in the receive!
Packit Service 82fcde
	     Since the signal thread thought we weren't in the RPC yet,
Packit Service 82fcde
	     it didn't do an interrupt_operation.
Packit Service 82fcde
	     XXX */
Packit Service 82fcde
	  goto retry_receive;
Packit Service 82fcde
	}
Packit Service 82fcde
      /* FALLTHROUGH */
Packit Service 82fcde
Packit Service 82fcde
      /* These are the other codes that mean a pseudo-receive modified
Packit Service 82fcde
	 the message buffer and we might need to clean up the port rights.  */
Packit Service 82fcde
    case MACH_SEND_TIMED_OUT:
Packit Service 82fcde
    case MACH_SEND_INVALID_NOTIFY:
Packit Service 82fcde
#ifdef MACH_SEND_NO_NOTIFY
Packit Service 82fcde
    case MACH_SEND_NO_NOTIFY:
Packit Service 82fcde
#endif
Packit Service 82fcde
#ifdef MACH_SEND_NOTIFY_IN_PROGRESS
Packit Service 82fcde
    case MACH_SEND_NOTIFY_IN_PROGRESS:
Packit Service 82fcde
#endif
Packit Service 82fcde
      if (MACH_MSGH_BITS_REMOTE (msg->msgh_bits) == MACH_MSG_TYPE_MOVE_SEND)
Packit Service 82fcde
	{
Packit Service 82fcde
	  __mach_port_deallocate (__mach_task_self (), msg->msgh_remote_port);
Packit Service 82fcde
	  msg->msgh_bits
Packit Service 82fcde
	    = (MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND,
Packit Service 82fcde
			       MACH_MSGH_BITS_LOCAL (msg->msgh_bits))
Packit Service 82fcde
	       | MACH_MSGH_BITS_OTHER (msg->msgh_bits));
Packit Service 82fcde
	}
Packit Service 82fcde
      if (msg->msgh_bits & MACH_MSGH_BITS_COMPLEX)
Packit Service 82fcde
	{
Packit Service 82fcde
#ifndef MACH_MSG_PORT_DESCRIPTOR
Packit Service 82fcde
	  /* Check for MOVE_SEND rights in the message.  These hold refs
Packit Service 82fcde
	     that we need to release in case the message is in fact never
Packit Service 82fcde
	     re-sent later.  Since it might in fact be re-sent, we turn
Packit Service 82fcde
	     these into COPY_SEND's after deallocating the extra user ref;
Packit Service 82fcde
	     the caller is responsible for still holding a ref to go with
Packit Service 82fcde
	     the original COPY_SEND right, so the resend copies it again.  */
Packit Service 82fcde
Packit Service 82fcde
	  mach_msg_type_long_t *ty = (void *) (msg + 1);
Packit Service 82fcde
	  while ((void *) ty < (void *) msg + msg->msgh_size)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      mach_msg_type_name_t name;
Packit Service 82fcde
	      mach_msg_type_size_t size;
Packit Service 82fcde
	      mach_msg_type_number_t number;
Packit Service 82fcde
Packit Service 82fcde
	      inline void clean_ports (mach_port_t *ports, int dealloc)
Packit Service 82fcde
		{
Packit Service 82fcde
		  mach_msg_type_number_t i;
Packit Service 82fcde
		  switch (name)
Packit Service 82fcde
		    {
Packit Service 82fcde
		    case MACH_MSG_TYPE_MOVE_SEND:
Packit Service 82fcde
		      for (i = 0; i < number; i++)
Packit Service 82fcde
			__mach_port_deallocate (__mach_task_self (), *ports++);
Packit Service 82fcde
		      if (ty->msgtl_header.msgt_longform)
Packit Service 82fcde
			ty->msgtl_name = MACH_MSG_TYPE_COPY_SEND;
Packit Service 82fcde
		      else
Packit Service 82fcde
			ty->msgtl_header.msgt_name = MACH_MSG_TYPE_COPY_SEND;
Packit Service 82fcde
		      break;
Packit Service 82fcde
		    case MACH_MSG_TYPE_COPY_SEND:
Packit Service 82fcde
		    case MACH_MSG_TYPE_MOVE_RECEIVE:
Packit Service 82fcde
		      break;
Packit Service 82fcde
		    default:
Packit Service 82fcde
		      if (MACH_MSG_TYPE_PORT_ANY (name))
Packit Service 82fcde
			assert (! "unexpected port type in interruptible RPC");
Packit Service 82fcde
		    }
Packit Service 82fcde
		  if (dealloc)
Packit Service 82fcde
		    __vm_deallocate (__mach_task_self (),
Packit Service 82fcde
				     (vm_address_t) ports,
Packit Service 82fcde
				     number * sizeof (mach_port_t));
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      if (ty->msgtl_header.msgt_longform)
Packit Service 82fcde
		{
Packit Service 82fcde
		  name = ty->msgtl_name;
Packit Service 82fcde
		  size = ty->msgtl_size;
Packit Service 82fcde
		  number = ty->msgtl_number;
Packit Service 82fcde
		  ty = (void *) ty + sizeof (mach_msg_type_long_t);
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		{
Packit Service 82fcde
		  name = ty->msgtl_header.msgt_name;
Packit Service 82fcde
		  size = ty->msgtl_header.msgt_size;
Packit Service 82fcde
		  number = ty->msgtl_header.msgt_number;
Packit Service 82fcde
		  ty = (void *) ty + sizeof (mach_msg_type_t);
Packit Service 82fcde
		}
Packit Service 82fcde
Packit Service 82fcde
	      if (ty->msgtl_header.msgt_inline)
Packit Service 82fcde
		{
Packit Service 82fcde
		  clean_ports ((void *) ty, 0);
Packit Service 82fcde
		  /* calculate length of data in bytes, rounding up */
Packit Service 82fcde
		  ty = (void *) ty + (((((number * size) + 7) >> 3)
Packit Service 82fcde
				       + sizeof (mach_msg_type_t) - 1)
Packit Service 82fcde
				      &~ (sizeof (mach_msg_type_t) - 1));
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		{
Packit Service 82fcde
		  clean_ports (*(void **) ty,
Packit Service 82fcde
			       ty->msgtl_header.msgt_deallocate);
Packit Service 82fcde
		  ty = (void *) ty + sizeof (void *);
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
#else  /* Untyped Mach IPC flavor. */
Packit Service 82fcde
	  mach_msg_body_t *body = (void *) (msg + 1);
Packit Service 82fcde
	  mach_msg_descriptor_t *desc = (void *) (body + 1);
Packit Service 82fcde
	  mach_msg_descriptor_t *desc_end = desc + body->msgh_descriptor_count;
Packit Service 82fcde
	  for (; desc < desc_end; ++desc)
Packit Service 82fcde
	    switch (desc->type.type)
Packit Service 82fcde
	      {
Packit Service 82fcde
	      case MACH_MSG_PORT_DESCRIPTOR:
Packit Service 82fcde
		switch (desc->port.disposition)
Packit Service 82fcde
		  {
Packit Service 82fcde
		  case MACH_MSG_TYPE_MOVE_SEND:
Packit Service 82fcde
		    __mach_port_deallocate (mach_task_self (),
Packit Service 82fcde
					    desc->port.name);
Packit Service 82fcde
		    desc->port.disposition = MACH_MSG_TYPE_COPY_SEND;
Packit Service 82fcde
		    break;
Packit Service 82fcde
		  case MACH_MSG_TYPE_COPY_SEND:
Packit Service 82fcde
		  case MACH_MSG_TYPE_MOVE_RECEIVE:
Packit Service 82fcde
		    break;
Packit Service 82fcde
		  default:
Packit Service 82fcde
		    assert (! "unexpected port type in interruptible RPC");
Packit Service 82fcde
		  }
Packit Service 82fcde
		break;
Packit Service 82fcde
	      case MACH_MSG_OOL_DESCRIPTOR:
Packit Service 82fcde
		if (desc->out_of_line.deallocate)
Packit Service 82fcde
		  __vm_deallocate (__mach_task_self (),
Packit Service 82fcde
				   (vm_address_t) desc->out_of_line.address,
Packit Service 82fcde
				   desc->out_of_line.size);
Packit Service 82fcde
		break;
Packit Service 82fcde
	      case MACH_MSG_OOL_PORTS_DESCRIPTOR:
Packit Service 82fcde
		switch (desc->ool_ports.disposition)
Packit Service 82fcde
		  {
Packit Service 82fcde
		  case MACH_MSG_TYPE_MOVE_SEND:
Packit Service 82fcde
		    {
Packit Service 82fcde
		      mach_msg_size_t i;
Packit Service 82fcde
		      const mach_port_t *ports = desc->ool_ports.address;
Packit Service 82fcde
		      for (i = 0; i < desc->ool_ports.count; ++i)
Packit Service 82fcde
			__mach_port_deallocate (__mach_task_self (), ports[i]);
Packit Service 82fcde
		      desc->ool_ports.disposition = MACH_MSG_TYPE_COPY_SEND;
Packit Service 82fcde
		      break;
Packit Service 82fcde
		    }
Packit Service 82fcde
		  case MACH_MSG_TYPE_COPY_SEND:
Packit Service 82fcde
		  case MACH_MSG_TYPE_MOVE_RECEIVE:
Packit Service 82fcde
		    break;
Packit Service 82fcde
		  default:
Packit Service 82fcde
		    assert (! "unexpected port type in interruptible RPC");
Packit Service 82fcde
		  }
Packit Service 82fcde
		if (desc->ool_ports.deallocate)
Packit Service 82fcde
		  __vm_deallocate (__mach_task_self (),
Packit Service 82fcde
				   (vm_address_t) desc->ool_ports.address,
Packit Service 82fcde
				   desc->ool_ports.count
Packit Service 82fcde
				   * sizeof (mach_port_t));
Packit Service 82fcde
		break;
Packit Service 82fcde
	      default:
Packit Service 82fcde
		assert (! "unexpected descriptor type in interruptible RPC");
Packit Service 82fcde
	      }
Packit Service 82fcde
#endif
Packit Service 82fcde
	}
Packit Service 82fcde
      break;
Packit Service 82fcde
Packit Service 82fcde
    case EINTR:
Packit Service 82fcde
      /* Either the process was stopped and continued,
Packit Service 82fcde
	 or the server doesn't support interrupt_operation.  */
Packit Service 82fcde
      if (ss->intr_port != MACH_PORT_NULL)
Packit Service 82fcde
	/* If this signal was for us and it should interrupt calls, the
Packit Service 82fcde
	   signal thread will have cleared SS->intr_port.
Packit Service 82fcde
	   Since it's not cleared, the signal was for another thread,
Packit Service 82fcde
	   or SA_RESTART is set.  Restart the interrupted call.  */
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Make sure we have a valid reply port.  The one we were using
Packit Service 82fcde
	     may have been destroyed by interruption.  */
Packit Service 82fcde
	  m->header.msgh_local_port = rcv_name = __mig_get_reply_port ();
Packit Service 82fcde
	  m->header.msgh_bits = msgh_bits;
Packit Service 82fcde
	  option = user_option;
Packit Service 82fcde
	  timeout = user_timeout;
Packit Service 82fcde
	  goto message;
Packit Service 82fcde
	}
Packit Service 82fcde
      /* FALLTHROUGH */
Packit Service 82fcde
Packit Service 82fcde
    case MACH_RCV_PORT_DIED:
Packit Service 82fcde
      /* Server didn't respond to interrupt_operation,
Packit Service 82fcde
	 so the signal thread destroyed the reply port.  */
Packit Service 82fcde
      /* FALLTHROUGH */
Packit Service 82fcde
Packit Service 82fcde
    interrupted:
Packit Service 82fcde
      err = EINTR;
Packit Service 82fcde
Packit Service 82fcde
      /* The EINTR return indicates cancellation, so clear the flag.  */
Packit Service 82fcde
      ss->cancel = 0;
Packit Service 82fcde
      break;
Packit Service 82fcde
Packit Service 82fcde
    case MACH_RCV_INTERRUPTED:	/* RPC sent; no reply.  */
Packit Service 82fcde
      option &= ~MACH_SEND_MSG;	/* Don't send again.  */
Packit Service 82fcde
    retry_receive:
Packit Service 82fcde
      if (ss->intr_port == MACH_PORT_NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* This signal or cancellation was for us.  We need to wait for
Packit Service 82fcde
             the reply, but not hang forever.  */
Packit Service 82fcde
	  option |= MACH_RCV_TIMEOUT;
Packit Service 82fcde
	  /* Never decrease the user's timeout.  */
Packit Service 82fcde
	  if (!(user_option & MACH_RCV_TIMEOUT)
Packit Service 82fcde
	      || timeout > _hurd_interrupted_rpc_timeout)
Packit Service 82fcde
	    timeout = _hurd_interrupted_rpc_timeout;
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  option = user_option;
Packit Service 82fcde
	  timeout = user_timeout;
Packit Service 82fcde
	}
Packit Service 82fcde
      goto message;		/* Retry the receive.  */
Packit Service 82fcde
Packit Service 82fcde
    case MACH_MSG_SUCCESS:
Packit Service 82fcde
      {
Packit Service 82fcde
	/* We got a reply.  Was it EINTR?  */
Packit Service 82fcde
#ifdef MACH_MSG_TYPE_BIT
Packit Service 82fcde
	const union
Packit Service 82fcde
	{
Packit Service 82fcde
	  mach_msg_type_t t;
Packit Service 82fcde
	  int i;
Packit Service 82fcde
	} check =
Packit Service 82fcde
	  { t: { MACH_MSG_TYPE_INTEGER_T, sizeof (integer_t) * 8,
Packit Service 82fcde
		 1, TRUE, FALSE, FALSE, 0 } };
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
        if (m->reply.RetCode == EINTR &&
Packit Service 82fcde
	    m->header.msgh_size == sizeof m->reply &&
Packit Service 82fcde
#ifdef MACH_MSG_TYPE_BIT
Packit Service 82fcde
	    m->check.type == check.i &&
Packit Service 82fcde
#endif
Packit Service 82fcde
	    !(m->header.msgh_bits & MACH_MSGH_BITS_COMPLEX))
Packit Service 82fcde
	  {
Packit Service 82fcde
	    /* It is indeed EINTR.  Is the interrupt for us?  */
Packit Service 82fcde
	    if (ss->intr_port != MACH_PORT_NULL)
Packit Service 82fcde
	      {
Packit Service 82fcde
		/* Nope; repeat the RPC.
Packit Service 82fcde
		   XXX Resources moved? */
Packit Service 82fcde
Packit Service 82fcde
		assert (m->header.msgh_id == msgid + 100);
Packit Service 82fcde
Packit Service 82fcde
		/* We know we have a valid reply port, because we just
Packit Service 82fcde
		   received the EINTR reply on it.  Restore it and the
Packit Service 82fcde
		   other fields in the message header needed for send,
Packit Service 82fcde
		   since the header now reflects receipt of the reply.  */
Packit Service 82fcde
		m->header.msgh_local_port = rcv_name;
Packit Service 82fcde
		m->header.msgh_remote_port = remote_port;
Packit Service 82fcde
		m->header.msgh_id = msgid;
Packit Service 82fcde
		m->header.msgh_bits = msgh_bits;
Packit Service 82fcde
		/* Restore the two words clobbered by the reply data.  */
Packit Service 82fcde
		m->request.data = save_data;
Packit Service 82fcde
Packit Service 82fcde
		/* Restore the original mach_msg options.
Packit Service 82fcde
		   OPTION may have had MACH_RCV_TIMEOUT added,
Packit Service 82fcde
		   and/or MACH_SEND_MSG removed.  */
Packit Service 82fcde
		option = user_option;
Packit Service 82fcde
		timeout = user_timeout;
Packit Service 82fcde
Packit Service 82fcde
		/* Now we are ready to repeat the original message send.  */
Packit Service 82fcde
		goto message;
Packit Service 82fcde
	      }
Packit Service 82fcde
	    else
Packit Service 82fcde
	      /* The EINTR return indicates cancellation,
Packit Service 82fcde
		 so clear the flag.  */
Packit Service 82fcde
	      ss->cancel = 0;
Packit Service 82fcde
	  }
Packit Service 82fcde
      }
Packit Service 82fcde
      break;
Packit Service 82fcde
Packit Service 82fcde
    default:			/* Quiet -Wswitch-enum.  */
Packit Service 82fcde
      break;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  ss->intr_port = MACH_PORT_NULL;
Packit Service 82fcde
Packit Service 82fcde
  return err;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (_hurd_intr_rpc_mach_msg)