|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: /* ! 53: * File: kern/ipc_kobject.c ! 54: * Author: Rich Draves ! 55: * Date: 1989 ! 56: * ! 57: * Functions for letting a port represent a kernel object. ! 58: */ ! 59: ! 60: #include <mach_debug.h> ! 61: #include <mach_ipc_test.h> ! 62: #include <mach_machine_routines.h> ! 63: #include <norma_task.h> ! 64: #include <dipc.h> ! 65: #include <mach_rt.h> ! 66: #include <platforms.h> ! 67: #include <xk_proxy.h> ! 68: ! 69: #include <kern/ast.h> ! 70: #include <mach/port.h> ! 71: #include <mach/kern_return.h> ! 72: #include <mach/message.h> ! 73: #include <mach/mig_errors.h> ! 74: #include <mach/notify.h> ! 75: #include <kern/etap_macros.h> ! 76: #include <kern/ipc_mig.h> ! 77: #include <kern/ipc_kobject.h> ! 78: #include <kern/misc_protos.h> ! 79: #include <ipc/ipc_object.h> ! 80: #include <ipc/ipc_kmsg.h> ! 81: #include <ipc/ipc_port.h> ! 82: #include <kern/counters.h> ! 83: ! 84: ! 85: void ! 86: def_pager_hash_insert( ! 87: ipc_port_t name_port); ! 88: void pager_mux_hash_insert( ! 89: ipc_port_t port, ! 90: rpc_subsystem_t rec); ! 91: void pager_mux_hash_delete( ! 92: ipc_port_t port); ! 93: rpc_subsystem_t pager_mux_hash_lookup( ! 94: ipc_port_t port); ! 95: ! 96: ! 97: /* ! 98: * Routine: ipc_kobject_notify ! 99: * Purpose: ! 100: * Deliver notifications to kobjects that care about them. ! 101: */ ! 102: boolean_t ! 103: ipc_kobject_notify( ! 104: mach_msg_header_t *request_header, ! 105: mach_msg_header_t *reply_header); ! 106: ! 107: #include <mach/ndr.h> ! 108: ! 109: typedef struct { ! 110: mach_msg_id_t num; ! 111: mig_routine_t routine; ! 112: int size; ! 113: #if MACH_COUNTERS ! 114: mach_counter_t callcount; ! 115: #endif ! 116: } mig_hash_t; ! 117: ! 118: #define MAX_MIG_ENTRIES 1024 ! 119: #define MIG_HASH(x) (x) ! 120: ! 121: #ifndef max ! 122: #define max(a,b) (((a) > (b)) ? (a) : (b)) ! 123: #endif /* max */ ! 124: ! 125: mig_hash_t mig_buckets[MAX_MIG_ENTRIES]; ! 126: int mig_table_max_displ; ! 127: mach_msg_size_t mig_reply_size; ! 128: ! 129: ! 130: #include <mach/mach_port_server.h> ! 131: #include <mach/mach_host_server.h> ! 132: #include <mach/host_priv_server.h> ! 133: #include <mach/host_security_server.h> ! 134: #include <mach/clock_server.h> ! 135: #include <mach/clock_priv_server.h> ! 136: #include <mach/bootstrap_server.h> ! 137: #include <mach/ledger_server.h> ! 138: #include <mach/lock_set_server.h> ! 139: #include <mach/semaphore_server.h> ! 140: #include <default_pager/default_pager_object_server.h> ! 141: #include <mach/memory_object_server.h> ! 142: #include <mach/memory_object_control_server.h> ! 143: #include <mach/memory_object_default_server.h> ! 144: #include <mach/memory_object_name_server.h> ! 145: #include <mach/processor_server.h> ! 146: #include <mach/processor_set_server.h> ! 147: #include <mach/task_server.h> ! 148: #include <mach/vm_task_server.h> ! 149: #include <mach/thread_act_server.h> ! 150: #include <device/device_server.h> ! 151: ! 152: #if MACH_MACHINE_ROUTINES ! 153: #include <machine/machine_routines.h> ! 154: #endif /* MACH_MACHINE_ROUTINES */ ! 155: #if XK_PROXY ! 156: #include <uk_xkern/xk_uproxy_server.h> ! 157: #endif /* XK_PROXY */ ! 158: ! 159: ! 160: rpc_subsystem_t mig_e[] = { ! 161: (rpc_subsystem_t)&mach_port_subsystem, ! 162: (rpc_subsystem_t)&mach_host_subsystem, ! 163: (rpc_subsystem_t)&host_priv_subsystem, ! 164: (rpc_subsystem_t)&host_security_subsystem, ! 165: (rpc_subsystem_t)&clock_subsystem, ! 166: (rpc_subsystem_t)&clock_priv_subsystem, ! 167: (rpc_subsystem_t)&processor_subsystem, ! 168: (rpc_subsystem_t)&processor_set_subsystem, ! 169: (rpc_subsystem_t)&do_bootstrap_subsystem, ! 170: (rpc_subsystem_t)&is_iokit_subsystem, ! 171: (rpc_subsystem_t)&dp_memory_object_subsystem, ! 172: (rpc_subsystem_t)&dp_memory_object_default_subsystem, ! 173: (rpc_subsystem_t)&memory_object_name_subsystem, ! 174: (rpc_subsystem_t)&default_pager_object_subsystem, ! 175: (rpc_subsystem_t)&semaphore_subsystem, ! 176: (rpc_subsystem_t)&lock_set_subsystem, ! 177: (rpc_subsystem_t)&ledger_subsystem, ! 178: (rpc_subsystem_t)&task_subsystem, ! 179: (rpc_subsystem_t)&thread_act_subsystem, ! 180: (rpc_subsystem_t)&vm_task_subsystem, ! 181: ! 182: #if XK_PROXY ! 183: (rpc_subsystem_t)&do_uproxy_xk_uproxy_subsystem, ! 184: #endif /* XK_PROXY */ ! 185: #if MACH_MACHINE_ROUTINES ! 186: (rpc_subsystem_t)&MACHINE_SUBSYSTEM, ! 187: #endif /* MACH_MACHINE_ROUTINES */ ! 188: #if MCMSG && iPSC860 ! 189: (rpc_subsystem_t)&mcmsg_info_subsystem, ! 190: #endif /* MCMSG && iPSC860 */ ! 191: }; ! 192: ! 193: void ! 194: mig_init(void) ! 195: { ! 196: register unsigned int i, n = sizeof(mig_e)/sizeof(rpc_subsystem_t); ! 197: register unsigned int howmany; ! 198: register mach_msg_id_t j, pos, nentry, range; ! 199: ! 200: for (i = 0; i < n; i++) { ! 201: range = mig_e[i]->end - mig_e[i]->start; ! 202: if (!mig_e[i]->start || range < 0) ! 203: panic("the msgh_ids in mig_e[] aren't valid!"); ! 204: mig_reply_size = max(mig_reply_size, mig_e[i]->maxsize); ! 205: ! 206: for (j = 0; j < range; j++) { ! 207: if (mig_e[i]->routine[j].stub_routine) { ! 208: /* Only put real entries in the table */ ! 209: nentry = j + mig_e[i]->start; ! 210: for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1; ! 211: mig_buckets[pos].num; ! 212: pos = ++pos % MAX_MIG_ENTRIES, howmany++) { ! 213: if (mig_buckets[pos].num == nentry) { ! 214: printf("message id = %d\n", nentry); ! 215: panic("multiple entries with the same msgh_id"); ! 216: } ! 217: if (howmany == MAX_MIG_ENTRIES) ! 218: panic("the mig dispatch table is too small"); ! 219: } ! 220: ! 221: mig_buckets[pos].num = nentry; ! 222: mig_buckets[pos].routine = mig_e[i]->routine[j].stub_routine; ! 223: if (mig_e[i]->routine[j].max_reply_msg) ! 224: mig_buckets[pos].size = mig_e[i]->routine[j].max_reply_msg; ! 225: else ! 226: mig_buckets[pos].size = mig_e[i]->maxsize; ! 227: ! 228: mig_table_max_displ = max(howmany, mig_table_max_displ); ! 229: } ! 230: } ! 231: } ! 232: } ! 233: ! 234: ! 235: #define PAGER_MUX_HASH_COUNT 127 ! 236: ! 237: ! 238: struct pager_mux_entry { ! 239: queue_chain_t links; ! 240: ipc_port_t name; ! 241: rpc_subsystem_t pager_object; ! 242: }; ! 243: typedef struct pager_mux_entry *pager_mux_entry_t; ! 244: ! 245: queue_head_t pager_mux_hashtable[PAGER_MUX_HASH_COUNT]; ! 246: zone_t pager_mux_hash_zone; ! 247: ! 248: decl_mutex_data(,pager_mux_hash_lock) ! 249: ! 250: #define pager_mux_hash(name_port) \ ! 251: (((natural_t)(name_port) & 0xffffff) % PAGER_MUX_HASH_COUNT) ! 252: ! 253: ! 254: rpc_subsystem_t ! 255: pager_mux_hash_lookup( ! 256: ipc_port_t name_port) ! 257: { ! 258: register queue_t bucket; ! 259: register pager_mux_entry_t entry; ! 260: register rpc_subsystem_t pager_object; ! 261: ! 262: bucket = &pager_mux_hashtable[pager_mux_hash(name_port)]; ! 263: ! 264: mutex_lock(&pager_mux_hash_lock); ! 265: for (entry = (pager_mux_entry_t)queue_first(bucket); ! 266: !queue_end(bucket, &entry->links); ! 267: entry = (pager_mux_entry_t)queue_next(&entry->links)) { ! 268: if (entry->name == name_port) { ! 269: pager_object = entry->pager_object; ! 270: /* don't need to reference the object, it can't disappear */ ! 271: /* pager_mux_reference(pager_object); */ ! 272: mutex_unlock(&pager_mux_hash_lock); ! 273: return (pager_object); ! 274: } ! 275: } ! 276: mutex_unlock(&pager_mux_hash_lock); ! 277: return (rpc_subsystem_t)0; ! 278: } ! 279: ! 280: ! 281: void ! 282: pager_mux_hash_init(void) ! 283: { ! 284: register int i; ! 285: register vm_size_t size; ! 286: ! 287: size = sizeof(struct pager_mux_entry); ! 288: pager_mux_hash_zone = zinit( ! 289: size, ! 290: size * 2000, ! 291: PAGE_SIZE, ! 292: "pager mux port hash"); ! 293: for (i = 0; i < PAGER_MUX_HASH_COUNT; i++) ! 294: queue_init(&pager_mux_hashtable[i]); ! 295: mutex_init(&pager_mux_hash_lock, ETAP_IO_DEV_PAGEH); ! 296: } ! 297: ! 298: ! 299: void ! 300: pager_mux_hash_insert( ! 301: ipc_port_t name_port, ! 302: rpc_subsystem_t pager_object) ! 303: { ! 304: register pager_mux_entry_t new_entry; ! 305: ! 306: new_entry = (pager_mux_entry_t) zalloc(pager_mux_hash_zone); ! 307: new_entry->links.prev = (queue_entry_t) 0; ! 308: new_entry->links.next = (queue_entry_t) 0; ! 309: new_entry->name = name_port; ! 310: new_entry->pager_object = pager_object; ! 311: ! 312: mutex_lock(&pager_mux_hash_lock); ! 313: queue_enter((&pager_mux_hashtable[pager_mux_hash(name_port)]), ! 314: new_entry, pager_mux_entry_t, links); ! 315: mutex_unlock(&pager_mux_hash_lock); ! 316: } ! 317: ! 318: void ! 319: pager_mux_hash_delete( ! 320: ipc_port_t name_port) ! 321: { ! 322: register queue_t bucket; ! 323: register pager_mux_entry_t entry; ! 324: ! 325: bucket = &pager_mux_hashtable[pager_mux_hash(name_port)]; ! 326: ! 327: mutex_lock(&pager_mux_hash_lock); ! 328: for (entry = (pager_mux_entry_t)queue_first(bucket); ! 329: !queue_end(bucket, &entry->links); ! 330: entry = (pager_mux_entry_t)queue_next(&entry->links)) { ! 331: if (entry->name == name_port) { ! 332: queue_remove(bucket, entry, pager_mux_entry_t, links); ! 333: zfree(pager_mux_hash_zone, (vm_offset_t)entry); ! 334: break; ! 335: } ! 336: } ! 337: mutex_unlock(&pager_mux_hash_lock); ! 338: } ! 339: ! 340: ! 341: /* ! 342: * Routine: ipc_kobject_server ! 343: * Purpose: ! 344: * Handle a message sent to the kernel. ! 345: * Generates a reply message. ! 346: * Version for Untyped IPC. ! 347: * Conditions: ! 348: * Nothing locked. ! 349: */ ! 350: ! 351: ipc_kmsg_t ! 352: ipc_kobject_server( ! 353: ipc_kmsg_t request) ! 354: { ! 355: mach_msg_size_t reply_size; ! 356: ipc_kmsg_t reply; ! 357: kern_return_t kr; ! 358: mig_routine_t routine; ! 359: ipc_port_t *destp; ! 360: mach_msg_format_0_trailer_t *trailer; ! 361: register mig_hash_t *ptr; ! 362: #if MACH_RT ! 363: boolean_t reply_rt; ! 364: #endif /* MACH_RT */ ! 365: unsigned int th; ! 366: ! 367: /* Only fetch current thread if ETAP is configured */ ! 368: ETAP_DATA_LOAD(th, current_thread()); ! 369: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH, ! 370: EVENT_BEGIN, ! 371: ((thread_t) th), ! 372: &request->ikm_header.msgh_id, ! 373: sizeof(int)); ! 374: /* ! 375: * Find out corresponding mig_hash entry if any ! 376: */ ! 377: { ! 378: register int key = request->ikm_header.msgh_id; ! 379: register int i = MIG_HASH(key); ! 380: register int max_iter = mig_table_max_displ; ! 381: ! 382: do ! 383: ptr = &mig_buckets[i++ % MAX_MIG_ENTRIES]; ! 384: while (key != ptr->num && ptr->num && --max_iter); ! 385: ! 386: if (!ptr->routine || key != ptr->num) { ! 387: ptr = (mig_hash_t *)0; ! 388: reply_size = mig_reply_size; ! 389: } else { ! 390: reply_size = ptr->size; ! 391: #if MACH_COUNTER ! 392: ptr->callcount++; ! 393: #endif ! 394: } ! 395: } ! 396: ! 397: /* round up for ikm_cache; overhead is added by ikm_alloc */ ! 398: if ((reply_size += MAX_TRAILER_SIZE) < IKM_SAVED_MSG_SIZE) ! 399: reply_size = IKM_SAVED_MSG_SIZE; ! 400: ! 401: #if MACH_RT ! 402: reply_rt = ! 403: IP_VALID((ipc_port_t)request->ikm_header.msgh_local_port) ? ! 404: IP_RT((ipc_port_t)request->ikm_header.msgh_local_port) : ! 405: FALSE; ! 406: ! 407: if (reply_rt) ! 408: reply = ikm_rtalloc(reply_size); ! 409: else ! 410: #endif /* MACH_RT */ ! 411: reply = ikm_alloc(reply_size); ! 412: ! 413: if (reply == IKM_NULL) { ! 414: printf("ipc_kobject_server: dropping request\n"); ! 415: ipc_kmsg_destroy(request); ! 416: return IKM_NULL; ! 417: } ! 418: ! 419: ikm_init(reply, reply_size); ! 420: #if DIPC ! 421: reply->ikm_handle = HANDLE_NULL; ! 422: #endif /* DIPC */ ! 423: ! 424: /* ! 425: * Initialize reply message. ! 426: */ ! 427: { ! 428: #define InP ((mach_msg_header_t *) &request->ikm_header) ! 429: #define OutP ((mig_reply_error_t *) &reply->ikm_header) ! 430: ! 431: OutP->NDR = NDR_record; ! 432: OutP->Head.msgh_size = sizeof(mig_reply_error_t); ! 433: ! 434: OutP->Head.msgh_bits = ! 435: MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0); ! 436: OutP->Head.msgh_remote_port = InP->msgh_local_port; ! 437: OutP->Head.msgh_local_port = MACH_PORT_NULL; ! 438: OutP->Head.msgh_id = InP->msgh_id + 100; ! 439: #if MACH_RT ! 440: if (reply_rt) ! 441: KMSG_MARK_RT(reply); ! 442: #endif /* MACH_RT */ ! 443: #undef InP ! 444: #undef OutP ! 445: } ! 446: ! 447: /* ! 448: * Find the routine to call, and call it ! 449: * to perform the kernel function ! 450: */ ! 451: { ! 452: if (ptr) { ! 453: (*ptr->routine)(&request->ikm_header, &reply->ikm_header); ! 454: kernel_task->messages_received++; ! 455: } ! 456: else { ! 457: if (!ipc_kobject_notify(&request->ikm_header, &reply->ikm_header)){ ! 458: #if MACH_IPC_TEST ! 459: printf("ipc_kobject_server: bogus kernel message, id=%d\n", ! 460: request->ikm_header.msgh_id); ! 461: #endif /* MACH_IPC_TEST */ ! 462: _MIG_MSGID_INVALID(request->ikm_header.msgh_id); ! 463: ! 464: ((mig_reply_error_t *) &reply->ikm_header)->RetCode ! 465: = MIG_BAD_ID; ! 466: } ! 467: else ! 468: kernel_task->messages_received++; ! 469: } ! 470: kernel_task->messages_sent++; ! 471: } ! 472: ! 473: /* ! 474: * Destroy destination. The following code differs from ! 475: * ipc_object_destroy in that we release the send-once ! 476: * right instead of generating a send-once notification ! 477: * (which would bring us here again, creating a loop). ! 478: * It also differs in that we only expect send or ! 479: * send-once rights, never receive rights. ! 480: * ! 481: * We set msgh_remote_port to IP_NULL so that the kmsg ! 482: * destroy routines don't try to destroy the port twice. ! 483: */ ! 484: destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port; ! 485: switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) { ! 486: case MACH_MSG_TYPE_PORT_SEND: ! 487: ipc_port_release_send(*destp); ! 488: break; ! 489: ! 490: case MACH_MSG_TYPE_PORT_SEND_ONCE: ! 491: ipc_port_release_sonce(*destp); ! 492: break; ! 493: ! 494: default: ! 495: panic("ipc_object_destroy: strange destination rights"); ! 496: } ! 497: *destp = IP_NULL; ! 498: ! 499: if (!(reply->ikm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) && ! 500: ((mig_reply_error_t *) &reply->ikm_header)->RetCode != KERN_SUCCESS) ! 501: kr = ((mig_reply_error_t *) &reply->ikm_header)->RetCode; ! 502: else ! 503: kr = KERN_SUCCESS; ! 504: ! 505: if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) { ! 506: /* ! 507: * The server function is responsible for the contents ! 508: * of the message. The reply port right is moved ! 509: * to the reply message, and we have deallocated ! 510: * the destination port right, so we just need ! 511: * to free the kmsg. ! 512: */ ! 513: ! 514: /* ! 515: * Like ipc_kmsg_put, but without the copyout. Also, ! 516: * messages to the kernel will never have been allocated ! 517: * from the rt_zone. ! 518: */ ! 519: ! 520: ikm_check_initialized(request, request->ikm_size); ! 521: if (request->ikm_size != IKM_SAVED_KMSG_SIZE || ! 522: !ikm_cache_put (request)) { ! 523: ikm_free(request); ! 524: } ! 525: } else { ! 526: /* ! 527: * The message contents of the request are intact. ! 528: * Destroy everthing except the reply port right, ! 529: * which is needed in the reply message. ! 530: */ ! 531: ! 532: request->ikm_header.msgh_local_port = MACH_PORT_NULL; ! 533: ipc_kmsg_destroy(request); ! 534: } ! 535: ! 536: if (kr == MIG_NO_REPLY) { ! 537: /* ! 538: * The server function will send a reply message ! 539: * using the reply port right, which it has saved. ! 540: */ ! 541: ! 542: ikm_free(reply); ! 543: ! 544: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH, ! 545: EVENT_END, ! 546: ((thread_t) th), ! 547: &request->ikm_header.msgh_id, ! 548: sizeof(int)); ! 549: ! 550: return IKM_NULL; ! 551: } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) { ! 552: /* ! 553: * Can't queue the reply message if the destination ! 554: * (the reply port) isn't valid. ! 555: */ ! 556: ! 557: ipc_kmsg_destroy(reply); ! 558: ! 559: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH, ! 560: EVENT_END, ! 561: ((thread_t) th), ! 562: &request->ikm_header.msgh_id, ! 563: sizeof(int)); ! 564: ! 565: return IKM_NULL; ! 566: } ! 567: ! 568: trailer = (mach_msg_format_0_trailer_t *) ! 569: ((vm_offset_t)&reply->ikm_header + (int)reply->ikm_header.msgh_size); ! 570: trailer->msgh_sender = KERNEL_SECURITY_TOKEN; ! 571: trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0; ! 572: trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE; ! 573: ! 574: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH, ! 575: EVENT_END, ! 576: ((thread_t) th), ! 577: &request->ikm_header.msgh_id, ! 578: sizeof(int)); ! 579: ! 580: return reply; ! 581: } ! 582: ! 583: /* ! 584: * Routine: ipc_kobject_set ! 585: * Purpose: ! 586: * Make a port represent a kernel object of the given type. ! 587: * The caller is responsible for handling refs for the ! 588: * kernel object, if necessary. ! 589: * Conditions: ! 590: * Nothing locked. The port must be active. ! 591: */ ! 592: ! 593: void ! 594: ipc_kobject_set( ! 595: ipc_port_t port, ! 596: ipc_kobject_t kobject, ! 597: ipc_kobject_type_t type) ! 598: { ! 599: ip_lock(port); ! 600: assert(ip_active(port)); ! 601: #if MACH_ASSERT ! 602: port->ip_spares[2] = (port->ip_bits & IO_BITS_KOTYPE); ! 603: #endif /* MACH_ASSERT */ ! 604: port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type; ! 605: port->ip_kobject = kobject; ! 606: ip_unlock(port); ! 607: } ! 608: ! 609: /* ! 610: * Routine: ipc_kobject_destroy ! 611: * Purpose: ! 612: * Release any kernel object resources associated ! 613: * with the port, which is being destroyed. ! 614: * ! 615: * This should only be needed when resources are ! 616: * associated with a user's port. In the normal case, ! 617: * when the kernel is the receiver, the code calling ! 618: * ipc_port_dealloc_kernel should clean up the resources. ! 619: * Conditions: ! 620: * The port is not locked, but it is dead. ! 621: */ ! 622: ! 623: void ! 624: ipc_kobject_destroy( ! 625: ipc_port_t port) ! 626: { ! 627: switch (ip_kotype(port)) { ! 628: case IKOT_NAMED_ENTRY: ! 629: mach_destroy_memory_entry(port); ! 630: return; ! 631: case IKOT_UPL: ! 632: mach_destroy_upl(port); ! 633: return; ! 634: default: ! 635: vm_object_destroy(port); ! 636: } ! 637: } ! 638: ! 639: ! 640: extern int vnode_pager_workaround; ! 641: ! 642: boolean_t ! 643: ipc_kobject_notify( ! 644: mach_msg_header_t *request_header, ! 645: mach_msg_header_t *reply_header) ! 646: { ! 647: ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port; ! 648: rpc_subsystem_t paging_subsystem_object; ! 649: mach_port_seqno_t seqno; ! 650: ! 651: ((mig_reply_error_t *) reply_header)->RetCode = MIG_NO_REPLY; ! 652: switch (request_header->msgh_id) { ! 653: case MACH_NOTIFY_NO_SENDERS: ! 654: if(ip_kotype(port) == IKOT_NAMED_ENTRY) { ! 655: ip_lock(port); ! 656: ! 657: /* ! 658: * Bring the sequence number and mscount in ! 659: * line with ipc_port_destroy assertion. ! 660: */ ! 661: port->ip_mscount = 0; ! 662: port->ip_messages.imq_seqno = 0; ! 663: ipc_port_destroy(port); /* releases lock */ ! 664: return TRUE; ! 665: } ! 666: paging_subsystem_object = pager_mux_hash_lookup( ! 667: (ipc_port_t)request_header->msgh_remote_port); ! 668: if(paging_subsystem_object == (rpc_subsystem_t) ! 669: &dp_memory_object_subsystem) { ! 670: default_pager_no_senders( ! 671: (ipc_port_t)request_header->msgh_remote_port, ! 672: seqno, ! 673: (mach_port_mscount_t) ! 674: ((mach_no_senders_notification_t *) ! 675: request_header)->not_count); ! 676: (ipc_port_t)reply_header->msgh_remote_port ! 677: = MACH_PORT_NULL; ! 678: return TRUE; ! 679: } ! 680: if(paging_subsystem_object == (rpc_subsystem_t) ! 681: &vnode_pager_workaround) { ! 682: vnode_pager_no_senders( ! 683: (ipc_port_t)request_header->msgh_remote_port, ! 684: (mach_port_mscount_t) ! 685: ((mach_no_senders_notification_t *) ! 686: request_header)->not_count); ! 687: (ipc_port_t)reply_header->msgh_remote_port ! 688: = MACH_PORT_NULL; ! 689: return TRUE; ! 690: } ! 691: break; ! 692: case MACH_NOTIFY_PORT_DELETED: ! 693: case MACH_NOTIFY_PORT_DESTROYED: ! 694: case MACH_NOTIFY_SEND_ONCE: ! 695: case MACH_NOTIFY_DEAD_NAME: ! 696: break; ! 697: ! 698: default: ! 699: return FALSE; ! 700: } ! 701: switch (ip_kotype(port)) { ! 702: ! 703: #ifdef IOKIT ! 704: case IKOT_IOKIT_OBJECT: ! 705: case IKOT_IOKIT_CONNECT: ! 706: case IKOT_IOKIT_SPARE: ! 707: { ! 708: extern boolean_t iokit_notify( mach_msg_header_t *msg); ! 709: ! 710: return iokit_notify(request_header); ! 711: } ! 712: #endif ! 713: default: ! 714: return FALSE; ! 715: } ! 716: } ! 717: ! 718: ! 719: ! 720: #include <mach_kdb.h> ! 721: #if MACH_COUNTERS && MACH_KDB ! 722: ! 723: #include <ddb/db_output.h> ! 724: #include <ddb/db_sym.h> ! 725: ! 726: #define printf kdbprintf ! 727: ! 728: extern void kobjserver_stats(void); ! 729: extern void bucket_stats_print(mig_hash_t *bucket); ! 730: ! 731: extern void kobjserver_stats_clear(void); ! 732: ! 733: ! 734: void ! 735: kobjserver_stats_clear(void) ! 736: { ! 737: int i; ! 738: for (i = 0; i < MAX_MIG_ENTRIES; i++) { ! 739: mig_buckets[i].callcount = 0; ! 740: } ! 741: } ! 742: ! 743: void ! 744: kobjserver_stats(void) ! 745: { ! 746: register unsigned int i, n = sizeof(mig_e)/sizeof(rpc_subsystem_t); ! 747: register unsigned int howmany; ! 748: register mach_msg_id_t j, pos, nentry, range; ! 749: ! 750: db_printf("Kobject server call counts:\n"); ! 751: for (i = 0; i < n; i++) { ! 752: db_printf(" "); ! 753: db_printsym((vm_offset_t)mig_e[i], DB_STGY_ANY); ! 754: db_printf(":\n"); ! 755: range = mig_e[i]->end - mig_e[i]->start; ! 756: if (!mig_e[i]->start || range < 0) continue; ! 757: ! 758: for (j = 0; j < range; j++) { ! 759: nentry = j + mig_e[i]->start; ! 760: for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1; ! 761: mig_buckets[pos].num; ! 762: pos = ++pos % MAX_MIG_ENTRIES, howmany++) { ! 763: if (mig_buckets[pos].num == nentry) ! 764: bucket_stats_print(&mig_buckets[pos]); ! 765: } ! 766: } ! 767: } ! 768: } ! 769: ! 770: void ! 771: bucket_stats_print(mig_hash_t *bucket) ! 772: { ! 773: if (bucket->callcount) { ! 774: db_printf(" "); ! 775: db_printsym((vm_offset_t)bucket->routine, DB_STGY_ANY); ! 776: db_printf(" (%d):\t%d\n", bucket->num, bucket->callcount); ! 777: } ! 778: } ! 779: ! 780: ! 781: #endif /* MACH_COUNTERS && MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.