msgserver.c 5.9 KB

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