Blame mach/msgserver.c

Packit Service 82fcde
/* Copyright (C) 1993-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
/* Based on CMU's mach_msg_server.c revision 2.4 of 91/05/14, and thus
Packit Service 82fcde
   under the following copyright.  Rewritten by Roland McGrath (FSF)
Packit Service 82fcde
   93/12/06 to use stack space instead of malloc, and to handle
Packit Service 82fcde
   large messages with MACH_RCV_LARGE.  */
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Mach Operating System
Packit Service 82fcde
 * Copyright (c) 1991,1990 Carnegie Mellon University
Packit Service 82fcde
 * All Rights Reserved.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Permission to use, copy, modify and distribute this software and its
Packit Service 82fcde
 * documentation is hereby granted, provided that both the copyright
Packit Service 82fcde
 * notice and this permission notice appear in all copies of the
Packit Service 82fcde
 * software, derivative works or modified versions, and any portions
Packit Service 82fcde
 * thereof, and that both notices appear in supporting documentation.
Packit Service 82fcde
 *
Packit Service 82fcde
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
Packit Service 82fcde
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
Packit Service 82fcde
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Carnegie Mellon requests users of this software to return to
Packit Service 82fcde
 *
Packit Service 82fcde
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
Packit Service 82fcde
 *  School of Computer Science
Packit Service 82fcde
 *  Carnegie Mellon University
Packit Service 82fcde
 *  Pittsburgh PA 15213-3890
Packit Service 82fcde
 *
Packit Service 82fcde
 * any improvements or extensions that they make and grant Carnegie Mellon
Packit Service 82fcde
 * the rights to redistribute these changes.
Packit Service 82fcde
 */
Packit Service 82fcde
/*
Packit Service 82fcde
 * (pre-GNU) HISTORY
Packit Service 82fcde
 *
Packit Service 82fcde
 * Revision 2.4  91/05/14  17:53:22  mrt
Packit Service 82fcde
 * 	Correcting copyright
Packit Service 82fcde
 *
Packit Service 82fcde
 * Revision 2.3  91/02/14  14:17:47  mrt
Packit Service 82fcde
 * 	Added new Mach copyright
Packit Service 82fcde
 * 	[91/02/13  12:44:20  mrt]
Packit Service 82fcde
 *
Packit Service 82fcde
 * Revision 2.2  90/08/06  17:23:58  rpd
Packit Service 82fcde
 * 	Created.
Packit Service 82fcde
 *
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
#include <mach.h>
Packit Service 82fcde
#include <mach/mig_errors.h>
Packit Service 82fcde
#include <stdlib.h>		/* For malloc and free.  */
Packit Service 82fcde
#include <assert.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
mach_msg_return_t
Packit Service 82fcde
__mach_msg_server_timeout (boolean_t (*demux) (mach_msg_header_t *request,
Packit Service 82fcde
					       mach_msg_header_t *reply),
Packit Service 82fcde
			   mach_msg_size_t max_size,
Packit Service 82fcde
			   mach_port_t rcv_name,
Packit Service 82fcde
			   mach_msg_option_t option,
Packit Service 82fcde
			   mach_msg_timeout_t timeout)
Packit Service 82fcde
{
Packit Service 82fcde
  mig_reply_header_t *request, *reply;
Packit Service 82fcde
  mach_msg_return_t mr;
Packit Service 82fcde
Packit Service 82fcde
  if (max_size == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
#ifdef MACH_RCV_LARGE
Packit Service 82fcde
      option |= MACH_RCV_LARGE;
Packit Service 82fcde
      max_size = 2 * __vm_page_size; /* Generic.  Good? XXX */
Packit Service 82fcde
#else
Packit Service 82fcde
      max_size = 4 * __vm_page_size; /* XXX */
Packit Service 82fcde
#endif
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  request = __alloca (max_size);
Packit Service 82fcde
  reply = __alloca (max_size);
Packit Service 82fcde
Packit Service 82fcde
  while (1)
Packit Service 82fcde
    {
Packit Service 82fcde
    get_request:
Packit Service 82fcde
      mr = __mach_msg (&request->Head, MACH_RCV_MSG|option,
Packit Service 82fcde
		       0, max_size, rcv_name,
Packit Service 82fcde
		       timeout, MACH_PORT_NULL);
Packit Service 82fcde
      while (mr == MACH_MSG_SUCCESS)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* We have a request message.
Packit Service 82fcde
	     Pass it to DEMUX for processing.  */
Packit Service 82fcde
Packit Service 82fcde
	  (void) (*demux) (&request->Head, &reply->Head);
Packit Service 82fcde
	  assert (reply->Head.msgh_size <= max_size);
Packit Service 82fcde
Packit Service 82fcde
	  switch (reply->RetCode)
Packit Service 82fcde
	    {
Packit Service 82fcde
	    case KERN_SUCCESS:
Packit Service 82fcde
	      /* Hunky dory.  */
Packit Service 82fcde
	      break;
Packit Service 82fcde
Packit Service 82fcde
	    case MIG_NO_REPLY:
Packit Service 82fcde
	      /* The server function wanted no reply sent.
Packit Service 82fcde
		 Loop for another request.  */
Packit Service 82fcde
	      goto get_request;
Packit Service 82fcde
Packit Service 82fcde
	    default:
Packit Service 82fcde
	      /* Some error; destroy the request message to release any
Packit Service 82fcde
		 port rights or VM it holds.  Don't destroy the reply port
Packit Service 82fcde
		 right, so we can send an error message.  */
Packit Service 82fcde
	      request->Head.msgh_remote_port = MACH_PORT_NULL;
Packit Service 82fcde
	      __mach_msg_destroy (&request->Head);
Packit Service 82fcde
	      break;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  if (reply->Head.msgh_remote_port == MACH_PORT_NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* No reply port, so destroy the reply.  */
Packit Service 82fcde
	      if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
Packit Service 82fcde
		__mach_msg_destroy (&reply->Head);
Packit Service 82fcde
	      goto get_request;
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  /* Send the reply and the get next request.  */
Packit Service 82fcde
Packit Service 82fcde
	  {
Packit Service 82fcde
	    /* Swap the request and reply buffers.  mach_msg will read the
Packit Service 82fcde
	       reply message from the buffer we pass and write the new
Packit Service 82fcde
	       request message to the same buffer.  */
Packit Service 82fcde
	    void *tmp = request;
Packit Service 82fcde
	    request = reply;
Packit Service 82fcde
	    reply = tmp;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
	  mr = __mach_msg (&request->Head,
Packit Service 82fcde
			   MACH_SEND_MSG|MACH_RCV_MSG|option,
Packit Service 82fcde
			   request->Head.msgh_size, max_size, rcv_name,
Packit Service 82fcde
			   timeout, MACH_PORT_NULL);
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* A message error occurred.  */
Packit Service 82fcde
Packit Service 82fcde
      switch (mr)
Packit Service 82fcde
	{
Packit Service 82fcde
	case MACH_RCV_TOO_LARGE:
Packit Service 82fcde
#ifdef MACH_RCV_LARGE
Packit Service 82fcde
	  /* The request message is larger than MAX_SIZE, and has not
Packit Service 82fcde
	     been dequeued.  The message header has the actual size of
Packit Service 82fcde
	     the message.  We recurse here in hopes that the compiler
Packit Service 82fcde
	     will optimize the tail-call and allocate some more stack
Packit Service 82fcde
	     space instead of way too much.  */
Packit Service 82fcde
	  return __mach_msg_server_timeout (demux, request->Head.msgh_size,
Packit Service 82fcde
					    rcv_name, option, timeout);
Packit Service 82fcde
#else
Packit Service 82fcde
	  /* XXX the kernel has destroyed the msg */
Packit Service 82fcde
	  break;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
	case MACH_SEND_INVALID_DEST:
Packit Service 82fcde
	  /* The reply can't be delivered, so destroy it.  This error
Packit Service 82fcde
	     indicates only that the requester went away, so we
Packit Service 82fcde
	     continue and get the next request.  */
Packit Service 82fcde
	  __mach_msg_destroy (&request->Head);
Packit Service 82fcde
	  break;
Packit Service 82fcde
Packit Service 82fcde
	default:
Packit Service 82fcde
	  /* Some other form of lossage; return to caller.  */
Packit Service 82fcde
	  return mr;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
weak_alias (__mach_msg_server_timeout, mach_msg_server_timeout)
Packit Service 82fcde
Packit Service 82fcde
mach_msg_return_t
Packit Service 82fcde
__mach_msg_server (boolean_t (*demux) (mach_msg_header_t *in,
Packit Service 82fcde
				       mach_msg_header_t *out),
Packit Service 82fcde
		   mach_msg_size_t max_size,
Packit Service 82fcde
		   mach_port_t rcv_name)
Packit Service 82fcde
{
Packit Service 82fcde
  return __mach_msg_server_timeout (demux, max_size, rcv_name,
Packit Service 82fcde
				    MACH_MSG_OPTION_NONE,
Packit Service 82fcde
				    MACH_MSG_TIMEOUT_NONE);
Packit Service 82fcde
}
Packit Service 82fcde
weak_alias (__mach_msg_server, mach_msg_server)