ipc_kobject.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989 Carnegie Mellon University
  4. * All Rights Reserved.
  5. *
  6. * Permission to use, copy, modify and distribute this software and its
  7. * documentation is hereby granted, provided that both the copyright
  8. * notice and this permission notice appear in all copies of the
  9. * software, derivative works or modified versions, and any portions
  10. * thereof, and that both notices appear in supporting documentation.
  11. *
  12. * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13. * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15. *
  16. * Carnegie Mellon requests users of this software to return to
  17. *
  18. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  19. * School of Computer Science
  20. * Carnegie Mellon University
  21. * Pittsburgh PA 15213-3890
  22. *
  23. * any improvements or extensions that they make and grant Carnegie Mellon
  24. * the rights to redistribute these changes.
  25. */
  26. /*
  27. */
  28. /*
  29. * File: kern/ipc_kobject.c
  30. * Author: Rich Draves
  31. * Date: 1989
  32. *
  33. * Functions for letting a port represent a kernel object.
  34. */
  35. #include <glue/gnulinux.h>
  36. #include <kern/debug.h>
  37. #include <kern/printf.h>
  38. #include <mach/port.h>
  39. #include <mach/kern_return.h>
  40. #include <mach/message.h>
  41. //#include <mach/mig_errors.h>
  42. #include <mach/notify.h>
  43. #include <kern/ipc_kobject.h>
  44. #include <ipc/ipc_object.h>
  45. #include <ipc/ipc_kmsg.h>
  46. #include <ipc/ipc_port.h>
  47. #include <ipc/ipc_thread.h>
  48. #include <vm/vm_object.h>
  49. #include <vm/memory_object_proxy.h>
  50. #if 0
  51. #include <device/ds_routines.h>
  52. #include <kern/mach.server.h>
  53. #include <ipc/mach_port.server.h>
  54. #include <kern/mach_host.server.h>
  55. #include <device/device.server.h>
  56. #include <device/device_pager.server.h>
  57. #include <kern/mach4.server.h>
  58. #include <kern/gnumach.server.h>
  59. #if MACH_DEBUG
  60. #include <kern/mach_debug.server.h>
  61. #endif
  62. #if MACH_MACHINE_ROUTINES
  63. #include <machine/machine_routines.h>
  64. #include MACHINE_SERVER_HEADER
  65. #endif
  66. /*
  67. * Routine: ipc_kobject_server
  68. * Purpose:
  69. * Handle a message sent to the kernel.
  70. * Generates a reply message.
  71. * Conditions:
  72. * Nothing locked.
  73. */
  74. ipc_kmsg_t
  75. ipc_kobject_server(request)
  76. ipc_kmsg_t request;
  77. {
  78. mach_msg_size_t reply_size = ikm_less_overhead(8192);
  79. ipc_kmsg_t reply;
  80. kern_return_t kr;
  81. mig_routine_t routine;
  82. ipc_port_t *destp;
  83. reply = ikm_alloc(reply_size);
  84. if (reply == IKM_NULL) {
  85. printf("ipc_kobject_server: dropping request\n");
  86. ipc_kmsg_destroy(request);
  87. return IKM_NULL;
  88. }
  89. ikm_init(reply, reply_size);
  90. /*
  91. * Initialize reply message.
  92. */
  93. {
  94. #define InP ((mach_msg_header_t *) &request->ikm_header)
  95. #define OutP ((mig_reply_header_t *) &reply->ikm_header)
  96. static mach_msg_type_t RetCodeType = {
  97. /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32,
  98. /* msgt_size = */ 32,
  99. /* msgt_number = */ 1,
  100. /* msgt_inline = */ TRUE,
  101. /* msgt_longform = */ FALSE,
  102. /* msgt_unused = */ 0
  103. };
  104. OutP->Head.msgh_bits =
  105. MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
  106. OutP->Head.msgh_size = sizeof(mig_reply_header_t);
  107. OutP->Head.msgh_remote_port = InP->msgh_local_port;
  108. OutP->Head.msgh_local_port = MACH_PORT_NULL;
  109. OutP->Head.msgh_seqno = 0;
  110. OutP->Head.msgh_id = InP->msgh_id + 100;
  111. #if 0
  112. if (InP->msgh_id) {
  113. static long _calls;
  114. static struct { long id, count; } _counts[512];
  115. int i, id;
  116. id = InP->msgh_id;
  117. for (i = 0; i < 511; i++) {
  118. if (_counts[i].id == 0) {
  119. _counts[i].id = id;
  120. _counts[i].count++;
  121. break;
  122. }
  123. if (_counts[i].id == id) {
  124. _counts[i].count++;
  125. break;
  126. }
  127. }
  128. if (i == 511) {
  129. _counts[i].id = id;
  130. _counts[i].count++;
  131. }
  132. if ((++_calls & 0x7fff) == 0)
  133. for (i = 0; i < 512; i++) {
  134. if (_counts[i].id == 0)
  135. break;
  136. printf("%d: %d\n",
  137. _counts[i].id, _counts[i].count);
  138. }
  139. }
  140. #endif
  141. OutP->RetCodeType = RetCodeType;
  142. #undef InP
  143. #undef OutP
  144. }
  145. /*
  146. * Find the server routine to call, and call it
  147. * to perform the kernel function
  148. */
  149. {
  150. check_simple_locks();
  151. if ((routine = mach_server_routine(&request->ikm_header)) != 0
  152. || (routine = mach_port_server_routine(&request->ikm_header)) != 0
  153. || (routine = mach_host_server_routine(&request->ikm_header)) != 0
  154. || (routine = device_server_routine(&request->ikm_header)) != 0
  155. || (routine = device_pager_server_routine(&request->ikm_header)) != 0
  156. #if MACH_DEBUG
  157. || (routine = mach_debug_server_routine(&request->ikm_header)) != 0
  158. #endif /* MACH_DEBUG */
  159. || (routine = mach4_server_routine(&request->ikm_header)) != 0
  160. || (routine = gnumach_server_routine(&request->ikm_header)) != 0
  161. #if MACH_MACHINE_ROUTINES
  162. || (routine = MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0
  163. #endif /* MACH_MACHINE_ROUTINES */
  164. ) {
  165. (*routine)(&request->ikm_header, &reply->ikm_header);
  166. kernel_task->messages_received++;
  167. } else {
  168. if (!ipc_kobject_notify(&request->ikm_header,
  169. &reply->ikm_header)) {
  170. ((mig_reply_header_t *) &reply->ikm_header)->RetCode
  171. = MIG_BAD_ID;
  172. #if MACH_IPC_TEST
  173. printf("ipc_kobject_server: bogus kernel message, id=%d\n",
  174. request->ikm_header.msgh_id);
  175. #endif /* MACH_IPC_TEST */
  176. } else {
  177. kernel_task->messages_received++;
  178. }
  179. }
  180. kernel_task->messages_sent++;
  181. }
  182. check_simple_locks();
  183. /*
  184. * Destroy destination. The following code differs from
  185. * ipc_object_destroy in that we release the send-once
  186. * right instead of generating a send-once notification
  187. * (which would bring us here again, creating a loop).
  188. * It also differs in that we only expect send or
  189. * send-once rights, never receive rights.
  190. *
  191. * We set msgh_remote_port to IP_NULL so that the kmsg
  192. * destroy routines don't try to destroy the port twice.
  193. */
  194. destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port;
  195. switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) {
  196. case MACH_MSG_TYPE_PORT_SEND:
  197. ipc_port_release_send(*destp);
  198. break;
  199. case MACH_MSG_TYPE_PORT_SEND_ONCE:
  200. ipc_port_release_sonce(*destp);
  201. break;
  202. default:
  203. #if MACH_ASSERT
  204. assert(!"ipc_object_destroy: strange destination rights");
  205. #else
  206. panic("ipc_object_destroy: strange destination rights");
  207. #endif
  208. }
  209. *destp = IP_NULL;
  210. kr = ((mig_reply_header_t *) &reply->ikm_header)->RetCode;
  211. if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
  212. /*
  213. * The server function is responsible for the contents
  214. * of the message. The reply port right is moved
  215. * to the reply message, and we have deallocated
  216. * the destination port right, so we just need
  217. * to free the kmsg.
  218. */
  219. /* like ipc_kmsg_put, but without the copyout */
  220. ikm_check_initialized(request, request->ikm_size);
  221. if ((request->ikm_size == IKM_SAVED_KMSG_SIZE) &&
  222. (ikm_cache() == IKM_NULL))
  223. ikm_cache() = request;
  224. else
  225. ikm_free(request);
  226. } else {
  227. /*
  228. * The message contents of the request are intact.
  229. * Destroy everything except the reply port right,
  230. * which is needed in the reply message.
  231. */
  232. request->ikm_header.msgh_local_port = MACH_PORT_NULL;
  233. ipc_kmsg_destroy(request);
  234. }
  235. if (kr == MIG_NO_REPLY) {
  236. /*
  237. * The server function will send a reply message
  238. * using the reply port right, which it has saved.
  239. */
  240. ikm_free(reply);
  241. return IKM_NULL;
  242. } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) {
  243. /*
  244. * Can't queue the reply message if the destination
  245. * (the reply port) isn't valid.
  246. */
  247. ipc_kmsg_destroy(reply);
  248. return IKM_NULL;
  249. }
  250. return reply;
  251. }
  252. #endif
  253. /*
  254. * Routine: ipc_kobject_set
  255. * Purpose:
  256. * Make a port represent a kernel object of the given type.
  257. * The caller is responsible for handling refs for the
  258. * kernel object, if necessary.
  259. * Conditions:
  260. * Nothing locked. The port must be active.
  261. */
  262. void
  263. ipc_kobject_set(port, kobject, type)
  264. ipc_port_t port;
  265. ipc_kobject_t kobject;
  266. ipc_kobject_type_t type;
  267. {
  268. ip_lock(port);
  269. assert(ip_active(port));
  270. port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type;
  271. port->ip_kobject = kobject;
  272. ip_unlock(port);
  273. }
  274. #if 0
  275. /*
  276. * Routine: ipc_kobject_destroy
  277. * Purpose:
  278. * Release any kernel object resources associated
  279. * with the port, which is being destroyed.
  280. *
  281. * This should only be needed when resources are
  282. * associated with a user's port. In the normal case,
  283. * when the kernel is the receiver, the code calling
  284. * ipc_port_dealloc_kernel should clean up the resources.
  285. * Conditions:
  286. * The port is not locked, but it is dead.
  287. */
  288. void
  289. ipc_kobject_destroy(
  290. ipc_port_t port)
  291. {
  292. switch (ip_kotype(port)) {
  293. case IKOT_PAGER:
  294. vm_object_destroy(port);
  295. break;
  296. case IKOT_PAGER_TERMINATING:
  297. vm_object_pager_wakeup(port);
  298. break;
  299. default:
  300. #if MACH_ASSERT
  301. printf("ipc_kobject_destroy: port 0x%p, kobj 0x%lx, type %d\n",
  302. port, port->ip_kobject, ip_kotype(port));
  303. #endif /* MACH_ASSERT */
  304. break;
  305. }
  306. }
  307. /*
  308. * Routine: ipc_kobject_notify
  309. * Purpose:
  310. * Deliver notifications to kobjects that care about them.
  311. */
  312. boolean_t
  313. ipc_kobject_notify(request_header, reply_header)
  314. mach_msg_header_t *request_header;
  315. mach_msg_header_t *reply_header;
  316. {
  317. ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port;
  318. ((mig_reply_header_t *) reply_header)->RetCode = MIG_NO_REPLY;
  319. switch (request_header->msgh_id) {
  320. case MACH_NOTIFY_PORT_DELETED:
  321. case MACH_NOTIFY_MSG_ACCEPTED:
  322. case MACH_NOTIFY_PORT_DESTROYED:
  323. case MACH_NOTIFY_NO_SENDERS:
  324. case MACH_NOTIFY_SEND_ONCE:
  325. case MACH_NOTIFY_DEAD_NAME:
  326. break;
  327. default:
  328. return FALSE;
  329. }
  330. switch (ip_kotype(port)) {
  331. case IKOT_DEVICE:
  332. return ds_notify(request_header);
  333. case IKOT_PAGER_PROXY:
  334. return memory_object_proxy_notify(request_header);
  335. default:
  336. return FALSE;
  337. }
  338. }
  339. #endif