|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 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: * File: ipc/ipc_marequest.c ! 52: * Author: Rich Draves ! 53: * Date: 1989 ! 54: * ! 55: * Functions to handle msg-accepted requests. ! 56: */ ! 57: ! 58: #import <mach/features.h> ! 59: ! 60: #include <mach/message.h> ! 61: #include <mach/port.h> ! 62: #include <kern/lock.h> ! 63: #include <kern/mach_param.h> ! 64: #include <kern/kalloc.h> ! 65: #include <kern/zalloc.h> ! 66: #include <ipc/port.h> ! 67: #include <ipc/ipc_space.h> ! 68: #include <ipc/ipc_entry.h> ! 69: #include <ipc/ipc_port.h> ! 70: #include <ipc/ipc_right.h> ! 71: #include <ipc/ipc_marequest.h> ! 72: #include <ipc/ipc_notify.h> ! 73: ! 74: #include <mach_ipc_debug.h> ! 75: #if MACH_IPC_DEBUG ! 76: #include <mach/kern_return.h> ! 77: #include <mach_debug/hash_info.h> ! 78: #include <vm/vm_map.h> ! 79: #include <vm/vm_kern.h> ! 80: #include <vm/vm_user.h> ! 81: #endif ! 82: ! 83: ! 84: zone_t ipc_marequest_zone; ! 85: int ipc_marequest_max = IMAR_MAX; ! 86: ! 87: #define imar_alloc() ((ipc_marequest_t) zalloc(ipc_marequest_zone)) ! 88: #define imar_free(imar) zfree(ipc_marequest_zone, (vm_offset_t) (imar)) ! 89: ! 90: typedef unsigned int ipc_marequest_index_t; ! 91: ! 92: ipc_marequest_index_t ipc_marequest_size; ! 93: ipc_marequest_index_t ipc_marequest_mask; ! 94: ! 95: #define IMAR_HASH(space, name) \ ! 96: ((((ipc_marequest_index_t)((vm_offset_t)space) >> 4) + \ ! 97: MACH_PORT_INDEX(name) + MACH_PORT_NGEN(name)) & \ ! 98: ipc_marequest_mask) ! 99: ! 100: typedef struct ipc_marequest_bucket { ! 101: decl_simple_lock_data(, imarb_lock_data) ! 102: ipc_marequest_t imarb_head; ! 103: } *ipc_marequest_bucket_t; ! 104: ! 105: #define IMARB_NULL ((ipc_marequest_bucket_t) 0) ! 106: ! 107: #define imarb_lock_init(imarb) simple_lock_init(&(imarb)->imarb_lock_data) ! 108: #define imarb_lock(imarb) simple_lock(&(imarb)->imarb_lock_data) ! 109: #define imarb_unlock(imarb) simple_unlock(&(imarb)->imarb_lock_data) ! 110: ! 111: ipc_marequest_bucket_t ipc_marequest_table; ! 112: ! 113: ! 114: ! 115: /* ! 116: * Routine: ipc_marequest_init ! 117: * Purpose: ! 118: * Initialize the msg-accepted request module. ! 119: */ ! 120: ! 121: void ! 122: ipc_marequest_init() ! 123: { ! 124: ipc_marequest_index_t i; ! 125: ! 126: /* if not configured, initialize ipc_marequest_size */ ! 127: ! 128: if (ipc_marequest_size == 0) { ! 129: ipc_marequest_size = ipc_marequest_max >> 8; ! 130: if (ipc_marequest_size < 16) ! 131: ipc_marequest_size = 16; ! 132: } ! 133: ! 134: /* make sure it is a power of two */ ! 135: ! 136: ipc_marequest_mask = ipc_marequest_size - 1; ! 137: if ((ipc_marequest_size & ipc_marequest_mask) != 0) { ! 138: unsigned int bit; ! 139: ! 140: /* round up to closest power of two */ ! 141: ! 142: for (bit = 1;; bit <<= 1) { ! 143: ipc_marequest_mask |= bit; ! 144: ipc_marequest_size = ipc_marequest_mask + 1; ! 145: ! 146: if ((ipc_marequest_size & ipc_marequest_mask) == 0) ! 147: break; ! 148: } ! 149: } ! 150: ! 151: /* allocate ipc_marequest_table */ ! 152: ! 153: ipc_marequest_table = (ipc_marequest_bucket_t) ! 154: kalloc((vm_size_t) (ipc_marequest_size * ! 155: sizeof(struct ipc_marequest_bucket))); ! 156: assert(ipc_marequest_table != IMARB_NULL); ! 157: ! 158: /* and initialize it */ ! 159: ! 160: for (i = 0; i < ipc_marequest_size; i++) { ! 161: ipc_marequest_bucket_t bucket; ! 162: ! 163: bucket = &ipc_marequest_table[i]; ! 164: imarb_lock_init(bucket); ! 165: bucket->imarb_head = IMAR_NULL; ! 166: } ! 167: ! 168: ipc_marequest_zone = ! 169: zinit(sizeof(struct ipc_marequest), ! 170: ipc_marequest_max * sizeof(struct ipc_marequest), ! 171: sizeof(struct ipc_marequest), ! 172: FALSE, "ipc msg-accepted requests"); ! 173: /* make it exhaustible */ ! 174: zchange(ipc_marequest_zone, FALSE, FALSE, TRUE, FALSE); ! 175: } ! 176: ! 177: /* ! 178: * Routine: ipc_marequest_create ! 179: * Purpose: ! 180: * Create a msg-accepted request, because ! 181: * a sender is forcing a message with MACH_SEND_NOTIFY. ! 182: * ! 183: * The "notify" argument should name a receive right ! 184: * that is used to create the send-once notify port. ! 185: * ! 186: * [MACH_IPC_COMPAT] If "notify" is MACH_PORT_NULL, ! 187: * then an old-style msg-accepted request is created. ! 188: * Conditions: ! 189: * Nothing locked; refs held for space and port. ! 190: * Returns: ! 191: * MACH_MSG_SUCCESS Msg-accepted request created. ! 192: * MACH_SEND_INVALID_NOTIFY The space is dead. ! 193: * MACH_SEND_INVALID_NOTIFY The notify port is bad. ! 194: * MACH_SEND_NOTIFY_IN_PROGRESS ! 195: * This space has already forced a message to this port. ! 196: * MACH_SEND_NO_NOTIFY Can't allocate a msg-accepted request. ! 197: */ ! 198: ! 199: mach_msg_return_t ! 200: ipc_marequest_create(space, port, notify, marequestp) ! 201: ipc_space_t space; ! 202: ipc_port_t port; ! 203: mach_port_t notify; ! 204: ipc_marequest_t *marequestp; ! 205: { ! 206: mach_port_t name; ! 207: ipc_entry_t entry; ! 208: ipc_port_t soright; ! 209: ipc_marequest_t marequest; ! 210: ipc_marequest_bucket_t bucket; ! 211: ! 212: #if !MACH_IPC_COMPAT ! 213: assert(notify != MACH_PORT_NULL); ! 214: #endif !MACH_IPC_COMPAT ! 215: ! 216: marequest = imar_alloc(); ! 217: if (marequest == IMAR_NULL) ! 218: return MACH_SEND_NO_NOTIFY; ! 219: ! 220: /* ! 221: * Delay creating the send-once right until ! 222: * we know there will be no errors. Otherwise, ! 223: * we would have to worry about disposing of it ! 224: * when it turned out it wasn't needed. ! 225: */ ! 226: ! 227: is_write_lock(space); ! 228: if (!space->is_active) { ! 229: is_write_unlock(space); ! 230: imar_free(marequest); ! 231: return MACH_SEND_INVALID_NOTIFY; ! 232: } ! 233: ! 234: if (ipc_right_reverse(space, (ipc_object_t) port, &name, &entry)) { ! 235: ipc_entry_bits_t bits; ! 236: ! 237: /* port is locked and active */ ! 238: ip_unlock(port); ! 239: bits = entry->ie_bits; ! 240: ! 241: assert(port == (ipc_port_t) entry->ie_object); ! 242: assert(bits & MACH_PORT_TYPE_SEND_RECEIVE); ! 243: ! 244: if (bits & IE_BITS_MAREQUEST) { ! 245: is_write_unlock(space); ! 246: imar_free(marequest); ! 247: return MACH_SEND_NOTIFY_IN_PROGRESS; ! 248: } ! 249: ! 250: #if MACH_IPC_COMPAT ! 251: if (notify == MACH_PORT_NULL) ! 252: soright = IP_NULL; ! 253: else ! 254: #endif MACH_IPC_COMPAT ! 255: if ((soright = ipc_port_lookup_notify(space, notify)) ! 256: == IP_NULL) { ! 257: is_write_unlock(space); ! 258: imar_free(marequest); ! 259: return MACH_SEND_INVALID_NOTIFY; ! 260: } ! 261: ! 262: entry->ie_bits = bits | IE_BITS_MAREQUEST; ! 263: ! 264: is_reference(space); ! 265: marequest->imar_space = space; ! 266: marequest->imar_name = name; ! 267: marequest->imar_soright = soright; ! 268: ! 269: bucket = &ipc_marequest_table[IMAR_HASH(space, name)]; ! 270: imarb_lock(bucket); ! 271: ! 272: marequest->imar_next = bucket->imarb_head; ! 273: bucket->imarb_head = marequest; ! 274: ! 275: imarb_unlock(bucket); ! 276: } else { ! 277: #if MACH_IPC_COMPAT ! 278: if (notify == MACH_PORT_NULL) ! 279: soright = IP_NULL; ! 280: else ! 281: #endif MACH_IPC_COMPAT ! 282: if ((soright = ipc_port_lookup_notify(space, notify)) ! 283: == IP_NULL) { ! 284: is_write_unlock(space); ! 285: imar_free(marequest); ! 286: return MACH_SEND_INVALID_NOTIFY; ! 287: } ! 288: ! 289: is_reference(space); ! 290: marequest->imar_space = space; ! 291: marequest->imar_name = MACH_PORT_NULL; ! 292: marequest->imar_soright = soright; ! 293: } ! 294: ! 295: is_write_unlock(space); ! 296: *marequestp = marequest; ! 297: return MACH_MSG_SUCCESS; ! 298: } ! 299: ! 300: /* ! 301: * Routine: ipc_marequest_cancel ! 302: * Purpose: ! 303: * Cancel a msg-accepted request, because ! 304: * the space's entry is being destroyed. ! 305: * Conditions: ! 306: * The space is write-locked and active. ! 307: */ ! 308: ! 309: void ! 310: ipc_marequest_cancel(space, name) ! 311: ipc_space_t space; ! 312: mach_port_t name; ! 313: { ! 314: ipc_marequest_bucket_t bucket; ! 315: ipc_marequest_t marequest, *last; ! 316: ! 317: assert(space->is_active); ! 318: ! 319: bucket = &ipc_marequest_table[IMAR_HASH(space, name)]; ! 320: imarb_lock(bucket); ! 321: ! 322: for (last = &bucket->imarb_head; ! 323: (marequest = *last) != IMAR_NULL; ! 324: last = &marequest->imar_next) ! 325: if ((marequest->imar_space == space) && ! 326: (marequest->imar_name == name)) ! 327: break; ! 328: ! 329: assert(marequest != IMAR_NULL); ! 330: *last = marequest->imar_next; ! 331: imarb_unlock(bucket); ! 332: ! 333: marequest->imar_name = MACH_PORT_NULL; ! 334: } ! 335: ! 336: /* ! 337: * Routine: ipc_marequest_rename ! 338: * Purpose: ! 339: * Rename a msg-accepted request, because the entry ! 340: * in the space is being renamed. ! 341: * Conditions: ! 342: * The space is write-locked and active. ! 343: */ ! 344: ! 345: void ! 346: ipc_marequest_rename(space, old, new) ! 347: ipc_space_t space; ! 348: mach_port_t old, new; ! 349: { ! 350: ipc_marequest_bucket_t bucket; ! 351: ipc_marequest_t marequest, *last; ! 352: ! 353: assert(space->is_active); ! 354: ! 355: bucket = &ipc_marequest_table[IMAR_HASH(space, old)]; ! 356: imarb_lock(bucket); ! 357: ! 358: for (last = &bucket->imarb_head; ! 359: (marequest = *last) != IMAR_NULL; ! 360: last = &marequest->imar_next) ! 361: if ((marequest->imar_space == space) && ! 362: (marequest->imar_name == old)) ! 363: break; ! 364: ! 365: assert(marequest != IMAR_NULL); ! 366: *last = marequest->imar_next; ! 367: imarb_unlock(bucket); ! 368: ! 369: marequest->imar_name = new; ! 370: ! 371: bucket = &ipc_marequest_table[IMAR_HASH(space, new)]; ! 372: imarb_lock(bucket); ! 373: ! 374: marequest->imar_next = bucket->imarb_head; ! 375: bucket->imarb_head = marequest; ! 376: ! 377: imarb_unlock(bucket); ! 378: } ! 379: ! 380: /* ! 381: * Routine: ipc_marequest_destroy ! 382: * Purpose: ! 383: * Destroy a msg-accepted request, because ! 384: * the kernel message is being received/destroyed. ! 385: * Conditions: ! 386: * Nothing locked. ! 387: */ ! 388: ! 389: void ! 390: ipc_marequest_destroy(marequest) ! 391: ipc_marequest_t marequest; ! 392: { ! 393: ipc_space_t space = marequest->imar_space; ! 394: mach_port_t name; ! 395: ipc_port_t soright; ! 396: #if MACH_IPC_COMPAT ! 397: ipc_port_t sright = IP_NULL; ! 398: #endif MACH_IPC_COMPAT ! 399: ! 400: is_write_lock(space); ! 401: ! 402: name = marequest->imar_name; ! 403: soright = marequest->imar_soright; ! 404: ! 405: if (name != MACH_PORT_NULL) { ! 406: ipc_marequest_bucket_t bucket; ! 407: ipc_marequest_t this, *last; ! 408: ! 409: bucket = &ipc_marequest_table[IMAR_HASH(space, name)]; ! 410: imarb_lock(bucket); ! 411: ! 412: for (last = &bucket->imarb_head; ! 413: (this = *last) != IMAR_NULL; ! 414: last = &this->imar_next) ! 415: if ((this->imar_space == space) && ! 416: (this->imar_name == name)) ! 417: break; ! 418: ! 419: assert(this == marequest); ! 420: *last = this->imar_next; ! 421: imarb_unlock(bucket); ! 422: ! 423: if (space->is_active) { ! 424: ipc_entry_t entry; ! 425: ! 426: entry = ipc_entry_lookup(space, name); ! 427: assert(entry != IE_NULL); ! 428: assert(entry->ie_bits & IE_BITS_MAREQUEST); ! 429: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE); ! 430: ! 431: entry->ie_bits &= ~IE_BITS_MAREQUEST; ! 432: ! 433: #if MACH_IPC_COMPAT ! 434: if (soright == IP_NULL) ! 435: sright = ipc_space_make_notify(space); ! 436: #endif MACH_IPC_COMPAT ! 437: } else ! 438: name = MACH_PORT_NULL; ! 439: } ! 440: ! 441: is_write_unlock(space); ! 442: is_release(space); ! 443: ! 444: imar_free(marequest); ! 445: ! 446: #if MACH_IPC_COMPAT ! 447: if (soright == IP_NULL) { ! 448: if (IP_VALID(sright)) { ! 449: assert(name != MACH_PORT_NULL); ! 450: ipc_notify_msg_accepted_compat(sright, name); ! 451: } ! 452: ! 453: return; ! 454: } ! 455: assert(sright == IP_NULL); ! 456: #endif MACH_IPC_COMPAT ! 457: ! 458: assert(soright != IP_NULL); ! 459: panic("ipc_marequest_destroy"); ! 460: } ! 461: ! 462: #if MACH_IPC_DEBUG ! 463: ! 464: ! 465: /* ! 466: * Routine: ipc_marequest_info ! 467: * Purpose: ! 468: * Return information about the marequest hash table. ! 469: * Fills the buffer with as much information as possible ! 470: * and returns the desired size of the buffer. ! 471: * Conditions: ! 472: * Nothing locked. The caller should provide ! 473: * possibly-pageable memory. ! 474: */ ! 475: ! 476: unsigned int ! 477: ipc_marequest_info(maxp, info, count) ! 478: unsigned int *maxp; ! 479: hash_info_bucket_t *info; ! 480: unsigned int count; ! 481: { ! 482: ipc_marequest_index_t i; ! 483: ! 484: if (ipc_marequest_size < count) ! 485: count = ipc_marequest_size; ! 486: ! 487: for (i = 0; i < count; i++) { ! 488: ipc_marequest_bucket_t bucket = &ipc_marequest_table[i]; ! 489: unsigned int bucket_count = 0; ! 490: ipc_marequest_t marequest; ! 491: ! 492: imarb_lock(bucket); ! 493: for (marequest = bucket->imarb_head; ! 494: marequest != IMAR_NULL; ! 495: marequest = marequest->imar_next) ! 496: bucket_count++; ! 497: imarb_unlock(bucket); ! 498: ! 499: /* don't touch pageable memory while holding locks */ ! 500: info[i].hib_count = bucket_count; ! 501: } ! 502: ! 503: *maxp = ipc_marequest_max; ! 504: return ipc_marequest_size; ! 505: } ! 506: ! 507: #endif MACH_IPC_DEBUG
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.