|
|
1.1 ! root 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 [email protected] ! 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: ! 36: #include <mach_debug.h> ! 37: #include <mach_ipc_test.h> ! 38: #include <mach_machine_routines.h> ! 39: #include <norma_task.h> ! 40: #include <norma_vm.h> ! 41: ! 42: #include <mach/port.h> ! 43: #include <mach/kern_return.h> ! 44: #include <mach/message.h> ! 45: #include <mach/mig_errors.h> ! 46: #include <mach/notify.h> ! 47: #include <kern/ipc_kobject.h> ! 48: #include <ipc/ipc_object.h> ! 49: #include <ipc/ipc_kmsg.h> ! 50: #include <ipc/ipc_port.h> ! 51: #include <ipc/ipc_thread.h> ! 52: ! 53: #if MACH_MACHINE_ROUTINES ! 54: #include <machine/machine_routines.h> ! 55: #endif ! 56: ! 57: ! 58: /* ! 59: * Routine: ipc_kobject_server ! 60: * Purpose: ! 61: * Handle a message sent to the kernel. ! 62: * Generates a reply message. ! 63: * Conditions: ! 64: * Nothing locked. ! 65: */ ! 66: ! 67: ipc_kmsg_t ! 68: ipc_kobject_server(request) ! 69: ipc_kmsg_t request; ! 70: { ! 71: mach_msg_size_t reply_size = ikm_less_overhead(8192); ! 72: ipc_kmsg_t reply; ! 73: kern_return_t kr; ! 74: mig_routine_t routine; ! 75: ipc_port_t *destp; ! 76: ! 77: reply = ikm_alloc(reply_size); ! 78: if (reply == IKM_NULL) { ! 79: printf("ipc_kobject_server: dropping request\n"); ! 80: ipc_kmsg_destroy(request); ! 81: return IKM_NULL; ! 82: } ! 83: ikm_init(reply, reply_size); ! 84: ! 85: /* ! 86: * Initialize reply message. ! 87: */ ! 88: { ! 89: #define InP ((mach_msg_header_t *) &request->ikm_header) ! 90: #define OutP ((mig_reply_header_t *) &reply->ikm_header) ! 91: ! 92: static mach_msg_type_t RetCodeType = { ! 93: /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32, ! 94: /* msgt_size = */ 32, ! 95: /* msgt_number = */ 1, ! 96: /* msgt_inline = */ TRUE, ! 97: /* msgt_longform = */ FALSE, ! 98: /* msgt_unused = */ 0 ! 99: }; ! 100: OutP->Head.msgh_bits = ! 101: MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0); ! 102: OutP->Head.msgh_size = sizeof(mig_reply_header_t); ! 103: OutP->Head.msgh_remote_port = InP->msgh_local_port; ! 104: OutP->Head.msgh_local_port = MACH_PORT_NULL; ! 105: OutP->Head.msgh_seqno = 0; ! 106: OutP->Head.msgh_id = InP->msgh_id + 100; ! 107: #if 0 ! 108: if (InP->msgh_id) { ! 109: static long _calls; ! 110: static struct { long id, count; } _counts[512]; ! 111: int i, id; ! 112: ! 113: id = InP->msgh_id; ! 114: for (i = 0; i < 511; i++) { ! 115: if (_counts[i].id == 0) { ! 116: _counts[i].id = id; ! 117: _counts[i].count++; ! 118: break; ! 119: } ! 120: if (_counts[i].id == id) { ! 121: _counts[i].count++; ! 122: break; ! 123: } ! 124: } ! 125: if (i == 511) { ! 126: _counts[i].id = id; ! 127: _counts[i].count++; ! 128: } ! 129: if ((++_calls & 0x7fff) == 0) ! 130: for (i = 0; i < 512; i++) { ! 131: if (_counts[i].id == 0) ! 132: break; ! 133: printf("%d: %d\n", ! 134: _counts[i].id, _counts[i].count); ! 135: } ! 136: } ! 137: #endif ! 138: ! 139: OutP->RetCodeType = RetCodeType; ! 140: ! 141: #undef InP ! 142: #undef OutP ! 143: } ! 144: ! 145: /* ! 146: * Find the server routine to call, and call it ! 147: * to perform the kernel function ! 148: */ ! 149: { ! 150: extern mig_routine_t mach_server_routine(), ! 151: mach_port_server_routine(), ! 152: mach_host_server_routine(), ! 153: device_server_routine(), ! 154: device_pager_server_routine(), ! 155: mach4_server_routine(); ! 156: #if MACH_DEBUG ! 157: extern mig_routine_t mach_debug_server_routine(); ! 158: #endif ! 159: #if NORMA_TASK ! 160: extern mig_routine_t mach_norma_server_routine(); ! 161: extern mig_routine_t norma_internal_server_routine(); ! 162: #endif ! 163: #if NORMA_VM ! 164: extern mig_routine_t proxy_server_routine(); ! 165: #endif ! 166: ! 167: #if MACH_MACHINE_ROUTINES ! 168: extern mig_routine_t MACHINE_SERVER_ROUTINE(); ! 169: #endif ! 170: ! 171: check_simple_locks(); ! 172: if ((routine = mach_server_routine(&request->ikm_header)) != 0 ! 173: || (routine = mach_port_server_routine(&request->ikm_header)) != 0 ! 174: || (routine = mach_host_server_routine(&request->ikm_header)) != 0 ! 175: || (routine = device_server_routine(&request->ikm_header)) != 0 ! 176: || (routine = device_pager_server_routine(&request->ikm_header)) != 0 ! 177: #if MACH_DEBUG ! 178: || (routine = mach_debug_server_routine(&request->ikm_header)) != 0 ! 179: #endif /* MACH_DEBUG */ ! 180: #if NORMA_TASK ! 181: || (routine = mach_norma_server_routine(&request->ikm_header)) != 0 ! 182: || (routine = norma_internal_server_routine(&request->ikm_header)) != 0 ! 183: #endif /* NORMA_TASK */ ! 184: #if NORMA_VM ! 185: || (routine = proxy_server_routine(&request->ikm_header)) != 0 ! 186: #endif /* NORMA_VM */ ! 187: || (routine = mach4_server_routine(&request->ikm_header)) != 0 ! 188: #if MACH_MACHINE_ROUTINES ! 189: || (routine = MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0 ! 190: #endif /* MACH_MACHINE_ROUTINES */ ! 191: ) { ! 192: (*routine)(&request->ikm_header, &reply->ikm_header); ! 193: } ! 194: else if (!ipc_kobject_notify(&request->ikm_header,&reply->ikm_header)){ ! 195: ((mig_reply_header_t *) &reply->ikm_header)->RetCode ! 196: = MIG_BAD_ID; ! 197: #if MACH_IPC_TEST ! 198: printf("ipc_kobject_server: bogus kernel message, id=%d\n", ! 199: request->ikm_header.msgh_id); ! 200: #endif /* MACH_IPC_TEST */ ! 201: } ! 202: } ! 203: check_simple_locks(); ! 204: ! 205: /* ! 206: * Destroy destination. The following code differs from ! 207: * ipc_object_destroy in that we release the send-once ! 208: * right instead of generating a send-once notification ! 209: * (which would bring us here again, creating a loop). ! 210: * It also differs in that we only expect send or ! 211: * send-once rights, never receive rights. ! 212: * ! 213: * We set msgh_remote_port to IP_NULL so that the kmsg ! 214: * destroy routines don't try to destroy the port twice. ! 215: */ ! 216: destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port; ! 217: switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) { ! 218: case MACH_MSG_TYPE_PORT_SEND: ! 219: ipc_port_release_send(*destp); ! 220: break; ! 221: ! 222: case MACH_MSG_TYPE_PORT_SEND_ONCE: ! 223: ipc_port_release_sonce(*destp); ! 224: break; ! 225: ! 226: default: ! 227: #if MACH_ASSERT ! 228: assert(!"ipc_object_destroy: strange destination rights"); ! 229: #else ! 230: panic("ipc_object_destroy: strange destination rights"); ! 231: #endif ! 232: } ! 233: *destp = IP_NULL; ! 234: ! 235: kr = ((mig_reply_header_t *) &reply->ikm_header)->RetCode; ! 236: if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) { ! 237: /* ! 238: * The server function is responsible for the contents ! 239: * of the message. The reply port right is moved ! 240: * to the reply message, and we have deallocated ! 241: * the destination port right, so we just need ! 242: * to free the kmsg. ! 243: */ ! 244: ! 245: /* like ipc_kmsg_put, but without the copyout */ ! 246: ! 247: ikm_check_initialized(request, request->ikm_size); ! 248: if ((request->ikm_size == IKM_SAVED_KMSG_SIZE) && ! 249: (ikm_cache() == IKM_NULL)) ! 250: ikm_cache() = request; ! 251: else ! 252: ikm_free(request); ! 253: } else { ! 254: /* ! 255: * The message contents of the request are intact. ! 256: * Destroy everthing except the reply port right, ! 257: * which is needed in the reply message. ! 258: */ ! 259: ! 260: request->ikm_header.msgh_local_port = MACH_PORT_NULL; ! 261: ipc_kmsg_destroy(request); ! 262: } ! 263: ! 264: if (kr == MIG_NO_REPLY) { ! 265: /* ! 266: * The server function will send a reply message ! 267: * using the reply port right, which it has saved. ! 268: */ ! 269: ! 270: ikm_free(reply); ! 271: return IKM_NULL; ! 272: } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) { ! 273: /* ! 274: * Can't queue the reply message if the destination ! 275: * (the reply port) isn't valid. ! 276: */ ! 277: ! 278: ipc_kmsg_destroy(reply); ! 279: return IKM_NULL; ! 280: } ! 281: ! 282: return reply; ! 283: } ! 284: ! 285: /* ! 286: * Routine: ipc_kobject_set ! 287: * Purpose: ! 288: * Make a port represent a kernel object of the given type. ! 289: * The caller is responsible for handling refs for the ! 290: * kernel object, if necessary. ! 291: * Conditions: ! 292: * Nothing locked. The port must be active. ! 293: */ ! 294: ! 295: void ! 296: ipc_kobject_set(port, kobject, type) ! 297: ipc_port_t port; ! 298: ipc_kobject_t kobject; ! 299: ipc_kobject_type_t type; ! 300: { ! 301: ip_lock(port); ! 302: assert(ip_active(port)); ! 303: port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type; ! 304: port->ip_kobject = kobject; ! 305: ip_unlock(port); ! 306: } ! 307: ! 308: /* ! 309: * Routine: ipc_kobject_destroy ! 310: * Purpose: ! 311: * Release any kernel object resources associated ! 312: * with the port, which is being destroyed. ! 313: * ! 314: * This should only be needed when resources are ! 315: * associated with a user's port. In the normal case, ! 316: * when the kernel is the receiver, the code calling ! 317: * ipc_port_dealloc_kernel should clean up the resources. ! 318: * Conditions: ! 319: * The port is not locked, but it is dead. ! 320: */ ! 321: ! 322: void ! 323: ipc_kobject_destroy( ! 324: ipc_port_t port) ! 325: { ! 326: switch (ip_kotype(port)) { ! 327: case IKOT_PAGER: ! 328: vm_object_destroy(port); ! 329: break; ! 330: ! 331: case IKOT_PAGER_TERMINATING: ! 332: vm_object_pager_wakeup(port); ! 333: break; ! 334: ! 335: default: ! 336: #if MACH_ASSERT ! 337: printf("ipc_kobject_destroy: port 0x%x, kobj 0x%x, type %d\n", ! 338: port, port->ip_kobject, ip_kotype(port)); ! 339: #endif /* MACH_ASSERT */ ! 340: break; ! 341: } ! 342: } ! 343: ! 344: /* ! 345: * Routine: ipc_kobject_notify ! 346: * Purpose: ! 347: * Deliver notifications to kobjects that care about them. ! 348: */ ! 349: ! 350: boolean_t ! 351: ipc_kobject_notify(request_header, reply_header) ! 352: mach_msg_header_t *request_header; ! 353: mach_msg_header_t *reply_header; ! 354: { ! 355: ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port; ! 356: ! 357: ((mig_reply_header_t *) reply_header)->RetCode = MIG_NO_REPLY; ! 358: switch (request_header->msgh_id) { ! 359: case MACH_NOTIFY_PORT_DELETED: ! 360: case MACH_NOTIFY_MSG_ACCEPTED: ! 361: case MACH_NOTIFY_PORT_DESTROYED: ! 362: case MACH_NOTIFY_NO_SENDERS: ! 363: case MACH_NOTIFY_SEND_ONCE: ! 364: case MACH_NOTIFY_DEAD_NAME: ! 365: break; ! 366: ! 367: default: ! 368: return FALSE; ! 369: } ! 370: switch (ip_kotype(port)) { ! 371: #if NORMA_VM ! 372: case IKOT_XMM_OBJECT: ! 373: return xmm_object_notify(request_header); ! 374: ! 375: case IKOT_XMM_PAGER: ! 376: return xmm_pager_notify(request_header); ! 377: ! 378: case IKOT_XMM_KERNEL: ! 379: return xmm_kernel_notify(request_header); ! 380: ! 381: case IKOT_XMM_REPLY: ! 382: return xmm_reply_notify(request_header); ! 383: #endif /* NORMA_VM */ ! 384: ! 385: case IKOT_DEVICE: ! 386: return ds_notify(request_header); ! 387: ! 388: default: ! 389: return FALSE; ! 390: } ! 391: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.