
1: /* Copyright (C) 1993,94,95,96,2001,02 Free Software Foundation, Inc. 2: This file is part of the GNU C Library. 3: 4: The GNU C Library is free software; you can redistribute it and/or 5: modify it under the terms of the GNU Lesser General Public 6: License as published by the Free Software Foundation; either 7: version 2.1 of the License, or (at your option) any later version. 8: 9: The GNU C Library is distributed in the hope that it will be useful, 10: but WITHOUT ANY WARRANTY; without even the implied warranty of 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12: Lesser General Public License for more details. 13: 14: You should have received a copy of the GNU Lesser General Public 15: License along with the GNU C Library; if not, write to the Free 16: Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 17: 02111-1307 USA. */ 18: 19: /* Based on CMU's mach_msg_server.c revision 2.4 of 91/05/14, and thus 20: under the following copyright. Rewritten by Roland McGrath (FSF) 21: 93/12/06 to use stack space instead of malloc, and to handle 22: large messages with MACH_RCV_LARGE. */ 23: 24: /* 25: * Mach Operating System 26: * Copyright (c) 1991,1990 Carnegie Mellon University 27: * All Rights Reserved. 28: * 29: * Permission to use, copy, modify and distribute this software and its 30: * documentation is hereby granted, provided that both the copyright 31: * notice and this permission notice appear in all copies of the 32: * software, derivative works or modified versions, and any portions 33: * thereof, and that both notices appear in supporting documentation. 34: * 35: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 36: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 37: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 38: * 39: * Carnegie Mellon requests users of this software to return to 40: * 41: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 42: * School of Computer Science 43: * Carnegie Mellon University 44: * Pittsburgh PA 15213-3890 45: * 46: * any improvements or extensions that they make and grant Carnegie Mellon 47: * the rights to redistribute these changes. 48: */ 49: /* 50: * (pre-GNU) HISTORY 51: * 52: * Revision 2.4 91/05/14 17:53:22 mrt 53: * Correcting copyright 54: * 55: * Revision 2.3 91/02/14 14:17:47 mrt 56: * Added new Mach copyright 57: * [91/02/13 12:44:20 mrt] 58: * 59: * Revision 2.2 90/08/06 17:23:58 rpd 60: * Created. 61: * 62: */ 63: 64: 65: #include <mach.h> 66: #include <mach/mig_errors.h> 67: #include <stdlib.h> /* For malloc and free. */ 68: #include <assert.h> 69: 70: #ifdef NDR_CHAR_ASCII /* OSF Mach flavors have different names. */ 71: # define mig_reply_header_t mig_reply_error_t 72: #endif 73: 74: mach_msg_return_t 75: __mach_msg_server_timeout (boolean_t (*demux) (mach_msg_header_t *request, 76: mach_msg_header_t *reply), 77: mach_msg_size_t max_size, 78: mach_port_t rcv_name, 79: mach_msg_option_t option, 80: mach_msg_timeout_t timeout) 81: { 82: register mig_reply_header_t *request, *reply; 83: register mach_msg_return_t mr; 84: 85: if (max_size == 0) 86: { 87: #ifdef MACH_RCV_LARGE 88: option |= MACH_RCV_LARGE; 89: max_size = 2 * __vm_page_size; /* Generic. Good? XXX */ 90: #else 91: max_size = 4 * __vm_page_size; /* XXX */ 92: #endif 93: } 94: 95: request = __alloca (max_size); 96: reply = __alloca (max_size); 97: 98: while (1) 99: { 100: get_request: 101: mr = __mach_msg (&request->Head, MACH_RCV_MSG|option, 102: 0, max_size, rcv_name, 103: timeout, MACH_PORT_NULL); 104: while (mr == MACH_MSG_SUCCESS) 105: { 106: /* We have a request message. 107: Pass it to DEMUX for processing. */ 108: 109: (void) (*demux) (&request->Head, &reply->Head); 110: assert (reply->Head.msgh_size <= max_size); 111: 112: switch (reply->RetCode) 113: { 114: case KERN_SUCCESS: 115: /* Hunky dory. */ 116: break; 117: 118: case MIG_NO_REPLY: 119: /* The server function wanted no reply sent. 120: Loop for another request. */ 121: goto get_request; 122: 123: default: 124: /* Some error; destroy the request message to release any 125: port rights or VM it holds. Don't destroy the reply port 126: right, so we can send an error message. */ 127: request->Head.msgh_remote_port = MACH_PORT_NULL; 128: __mach_msg_destroy (&request->Head); 129: break; 130: } 131: 132: if (reply->Head.msgh_remote_port == MACH_PORT_NULL) 133: { 134: /* No reply port, so destroy the reply. */ 135: if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) 136: __mach_msg_destroy (&reply->Head); 137: goto get_request; 138: } 139: 140: /* Send the reply and the get next request. */ 141: 142: { 143: /* Swap the request and reply buffers. mach_msg will read the 144: reply message from the buffer we pass and write the new 145: request message to the same buffer. */ 146: void *tmp = request; 147: request = reply; 148: reply = tmp; 149: } 150: 151: mr = __mach_msg (&request->Head, 152: MACH_SEND_MSG|MACH_RCV_MSG|option, 153: request->Head.msgh_size, max_size, rcv_name, 154: timeout, MACH_PORT_NULL); 155: } 156: 157: /* A message error occurred. */ 158: 159: switch (mr) 160: { 161: case MACH_RCV_TOO_LARGE: 162: #ifdef MACH_RCV_LARGE 163: /* The request message is larger than MAX_SIZE, and has not 164: been dequeued. The message header has the actual size of 165: the message. We recurse here in hopes that the compiler 166: will optimize the tail-call and allocate some more stack 167: space instead of way too much. */ 168: return __mach_msg_server_timeout (demux, request->Head.msgh_size, 169: rcv_name, option, timeout); 170: #else 171: /* XXX the kernel has destroyed the msg */ 172: break; 173: #endif 174: 175: case MACH_SEND_INVALID_DEST: 176: /* The reply can't be delivered, so destroy it. This error 177: indicates only that the requester went away, so we 178: continue and get the next request. */ 179: __mach_msg_destroy (&request->Head); 180: break; 181: 182: default: 183: /* Some other form of lossage; return to caller. */ 184: return mr; 185: } 186: } 187: } 188: weak_alias (__mach_msg_server_timeout, mach_msg_server_timeout) 189: 190: mach_msg_return_t 191: __mach_msg_server (demux, max_size, rcv_name) 192: boolean_t (*demux) (mach_msg_header_t *in, mach_msg_header_t *out); 193: mach_msg_size_t max_size; 194: mach_port_t rcv_name; 195: { 196: return __mach_msg_server_timeout (demux, max_size, rcv_name, 197: MACH_MSG_OPTION_NONE, 198: MACH_MSG_TIMEOUT_NONE); 199: } 200: weak_alias (__mach_msg_server, mach_msg_server)