Back to index

glibc  2.9
msgserver.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993,94,95,96,2001,02 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 /* Based on CMU's mach_msg_server.c revision 2.4 of 91/05/14, and thus
00020    under the following copyright.  Rewritten by Roland McGrath (FSF)
00021    93/12/06 to use stack space instead of malloc, and to handle
00022    large messages with MACH_RCV_LARGE.  */
00023 
00024 /*
00025  * Mach Operating System
00026  * Copyright (c) 1991,1990 Carnegie Mellon University
00027  * All Rights Reserved.
00028  *
00029  * Permission to use, copy, modify and distribute this software and its
00030  * documentation is hereby granted, provided that both the copyright
00031  * notice and this permission notice appear in all copies of the
00032  * software, derivative works or modified versions, and any portions
00033  * thereof, and that both notices appear in supporting documentation.
00034  *
00035  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
00036  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
00037  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00038  *
00039  * Carnegie Mellon requests users of this software to return to
00040  *
00041  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
00042  *  School of Computer Science
00043  *  Carnegie Mellon University
00044  *  Pittsburgh PA 15213-3890
00045  *
00046  * any improvements or extensions that they make and grant Carnegie Mellon
00047  * the rights to redistribute these changes.
00048  */
00049 /*
00050  * (pre-GNU) HISTORY
00051  *
00052  * Revision 2.4  91/05/14  17:53:22  mrt
00053  *     Correcting copyright
00054  *
00055  * Revision 2.3  91/02/14  14:17:47  mrt
00056  *     Added new Mach copyright
00057  *     [91/02/13  12:44:20  mrt]
00058  *
00059  * Revision 2.2  90/08/06  17:23:58  rpd
00060  *     Created.
00061  *
00062  */
00063 
00064 
00065 #include <mach.h>
00066 #include <mach/mig_errors.h>
00067 #include <stdlib.h>         /* For malloc and free.  */
00068 #include <assert.h>
00069 
00070 #ifdef NDR_CHAR_ASCII              /* OSF Mach flavors have different names.  */
00071 # define mig_reply_header_t mig_reply_error_t
00072 #endif
00073 
00074 mach_msg_return_t
00075 __mach_msg_server_timeout (boolean_t (*demux) (mach_msg_header_t *request,
00076                                           mach_msg_header_t *reply),
00077                         mach_msg_size_t max_size,
00078                         mach_port_t rcv_name,
00079                         mach_msg_option_t option,
00080                         mach_msg_timeout_t timeout)
00081 {
00082   register mig_reply_header_t *request, *reply;
00083   register mach_msg_return_t mr;
00084 
00085   if (max_size == 0)
00086     {
00087 #ifdef MACH_RCV_LARGE
00088       option |= MACH_RCV_LARGE;
00089       max_size = 2 * __vm_page_size; /* Generic.  Good? XXX */
00090 #else
00091       max_size = 4 * __vm_page_size; /* XXX */
00092 #endif
00093     }
00094 
00095   request = __alloca (max_size);
00096   reply = __alloca (max_size);
00097 
00098   while (1)
00099     {
00100     get_request:
00101       mr = __mach_msg (&request->Head, MACH_RCV_MSG|option,
00102                      0, max_size, rcv_name,
00103                      timeout, MACH_PORT_NULL);
00104       while (mr == MACH_MSG_SUCCESS)
00105        {
00106          /* We have a request message.
00107             Pass it to DEMUX for processing.  */
00108 
00109          (void) (*demux) (&request->Head, &reply->Head);
00110          assert (reply->Head.msgh_size <= max_size);
00111 
00112          switch (reply->RetCode)
00113            {
00114            case KERN_SUCCESS:
00115              /* Hunky dory.  */
00116              break;
00117 
00118            case MIG_NO_REPLY:
00119              /* The server function wanted no reply sent.
00120                Loop for another request.  */
00121              goto get_request;
00122 
00123            default:
00124              /* Some error; destroy the request message to release any
00125                port rights or VM it holds.  Don't destroy the reply port
00126                right, so we can send an error message.  */
00127              request->Head.msgh_remote_port = MACH_PORT_NULL;
00128              __mach_msg_destroy (&request->Head);
00129              break;
00130            }
00131 
00132          if (reply->Head.msgh_remote_port == MACH_PORT_NULL)
00133            {
00134              /* No reply port, so destroy the reply.  */
00135              if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
00136               __mach_msg_destroy (&reply->Head);
00137              goto get_request;
00138            }
00139 
00140          /* Send the reply and the get next request.  */
00141 
00142          {
00143            /* Swap the request and reply buffers.  mach_msg will read the
00144               reply message from the buffer we pass and write the new
00145               request message to the same buffer.  */
00146            void *tmp = request;
00147            request = reply;
00148            reply = tmp;
00149          }
00150 
00151          mr = __mach_msg (&request->Head,
00152                         MACH_SEND_MSG|MACH_RCV_MSG|option,
00153                         request->Head.msgh_size, max_size, rcv_name,
00154                         timeout, MACH_PORT_NULL);
00155        }
00156 
00157       /* A message error occurred.  */
00158 
00159       switch (mr)
00160        {
00161        case MACH_RCV_TOO_LARGE:
00162 #ifdef MACH_RCV_LARGE
00163          /* The request message is larger than MAX_SIZE, and has not
00164             been dequeued.  The message header has the actual size of
00165             the message.  We recurse here in hopes that the compiler
00166             will optimize the tail-call and allocate some more stack
00167             space instead of way too much.  */
00168          return __mach_msg_server_timeout (demux, request->Head.msgh_size,
00169                                        rcv_name, option, timeout);
00170 #else
00171          /* XXX the kernel has destroyed the msg */
00172          break;
00173 #endif
00174 
00175        case MACH_SEND_INVALID_DEST:
00176          /* The reply can't be delivered, so destroy it.  This error
00177             indicates only that the requester went away, so we
00178             continue and get the next request.  */
00179          __mach_msg_destroy (&request->Head);
00180          break;
00181 
00182        default:
00183          /* Some other form of lossage; return to caller.  */
00184          return mr;
00185        }
00186     }
00187 }
00188 weak_alias (__mach_msg_server_timeout, mach_msg_server_timeout)
00189 
00190 mach_msg_return_t
00191 __mach_msg_server (demux, max_size, rcv_name)
00192      boolean_t (*demux) (mach_msg_header_t *in, mach_msg_header_t *out);
00193      mach_msg_size_t max_size;
00194      mach_port_t rcv_name;
00195 {
00196   return __mach_msg_server_timeout (demux, max_size, rcv_name,
00197                                 MACH_MSG_OPTION_NONE,
00198                                 MACH_MSG_TIMEOUT_NONE);
00199 }
00200 weak_alias (__mach_msg_server, mach_msg_server)