|
|
1.1.1.2 ! root 1: /* 1.1 root 2: * Mach Operating System 3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University 4: * All Rights Reserved. 1.1.1.2 ! root 5: * 1.1 root 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. 1.1.1.2 ! root 11: * 1.1 root 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. 1.1.1.2 ! root 15: * 1.1 root 16: * Carnegie Mellon requests users of this software to return to 1.1.1.2 ! root 17: * 1.1 root 18: * Software Distribution Coordinator or [email protected] 19: * School of Computer Science 20: * Carnegie Mellon University 21: * Pittsburgh PA 15213-3890 1.1.1.2 ! root 22: * 1.1 root 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 1.1.1.2 ! root 179: #endif /* MACH_DEBUG */ 1.1 root 180: #if NORMA_TASK 181: || (routine = mach_norma_server_routine(&request->ikm_header)) != 0 182: || (routine = norma_internal_server_routine(&request->ikm_header)) != 0 1.1.1.2 ! root 183: #endif /* NORMA_TASK */ 1.1 root 184: #if NORMA_VM 185: || (routine = proxy_server_routine(&request->ikm_header)) != 0 1.1.1.2 ! root 186: #endif /* NORMA_VM */ 1.1 root 187: || (routine = mach4_server_routine(&request->ikm_header)) != 0 188: #if MACH_MACHINE_ROUTINES 189: || (routine = MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0 1.1.1.2 ! root 190: #endif /* MACH_MACHINE_ROUTINES */ 1.1 root 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); 1.1.1.2 ! root 200: #endif /* MACH_IPC_TEST */ 1.1 root 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; 1.1.1.2 ! root 221: 1.1 root 222: case MACH_MSG_TYPE_PORT_SEND_ONCE: 223: ipc_port_release_sonce(*destp); 224: break; 1.1.1.2 ! root 225: 1.1 root 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)); 1.1.1.2 ! root 339: #endif /* MACH_ASSERT */ 1.1 root 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); 1.1.1.2 ! root 383: #endif /* NORMA_VM */ 1.1 root 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.