|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University. ! 4: * Copyright (c) 1993,1994 The University of Utah and ! 5: * the Computer Systems Laboratory (CSL). ! 6: * All rights reserved. ! 7: * ! 8: * Permission to use, copy, modify and distribute this software and its ! 9: * documentation is hereby granted, provided that both the copyright ! 10: * notice and this permission notice appear in all copies of the ! 11: * software, derivative works or modified versions, and any portions ! 12: * thereof, and that both notices appear in supporting documentation. ! 13: * ! 14: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF ! 15: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY ! 16: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF ! 17: * THIS SOFTWARE. ! 18: * ! 19: * Carnegie Mellon requests users of this software to return to ! 20: * ! 21: * Software Distribution Coordinator or [email protected] ! 22: * School of Computer Science ! 23: * Carnegie Mellon University ! 24: * Pittsburgh PA 15213-3890 ! 25: * ! 26: * any improvements or extensions that they make and grant Carnegie Mellon ! 27: * the rights to redistribute these changes. ! 28: */ ! 29: /* ! 30: */ ! 31: /* ! 32: * File: ipc/mach_port.c ! 33: * Author: Rich Draves ! 34: * Date: 1989 ! 35: * ! 36: * Exported kernel calls. See mach/mach_port.defs. ! 37: */ ! 38: ! 39: #include <mach_ipc_compat.h> ! 40: ! 41: #include <mach/port.h> ! 42: #include <mach/kern_return.h> ! 43: #include <mach/notify.h> ! 44: #include <mach/mach_param.h> ! 45: #include <mach/vm_param.h> ! 46: #include <mach/vm_prot.h> ! 47: #ifdef MIGRATING_THREADS ! 48: #include <mach/rpc.h> ! 49: #include <kern/task.h> ! 50: #include <kern/act.h> ! 51: #endif /* MIGRATING_THREADS */ ! 52: #include <vm/vm_map.h> ! 53: #include <vm/vm_kern.h> ! 54: #include <vm/vm_user.h> ! 55: #include <ipc/ipc_entry.h> ! 56: #include <ipc/ipc_space.h> ! 57: #include <ipc/ipc_object.h> ! 58: #include <ipc/ipc_notify.h> ! 59: #include <ipc/ipc_port.h> ! 60: #include <ipc/ipc_pset.h> ! 61: #include <ipc/ipc_right.h> ! 62: ! 63: ! 64: ! 65: /* ! 66: * Routine: mach_port_names_helper ! 67: * Purpose: ! 68: * A helper function for mach_port_names. ! 69: */ ! 70: ! 71: void ! 72: mach_port_names_helper( ! 73: ipc_port_timestamp_t timestamp, ! 74: ipc_entry_t entry, ! 75: mach_port_t name, ! 76: mach_port_t *names, ! 77: mach_port_type_t *types, ! 78: ipc_entry_num_t *actualp) ! 79: { ! 80: ipc_entry_bits_t bits = entry->ie_bits; ! 81: ipc_port_request_index_t request = entry->ie_request; ! 82: mach_port_type_t type; ! 83: ipc_entry_num_t actual; ! 84: ! 85: if (bits & MACH_PORT_TYPE_SEND_RIGHTS) { ! 86: ipc_port_t port; ! 87: boolean_t died; ! 88: ! 89: port = (ipc_port_t) entry->ie_object; ! 90: assert(port != IP_NULL); ! 91: ! 92: /* ! 93: * The timestamp serializes mach_port_names ! 94: * with ipc_port_destroy. If the port died, ! 95: * but after mach_port_names started, pretend ! 96: * that it isn't dead. ! 97: */ ! 98: ! 99: ip_lock(port); ! 100: died = (!ip_active(port) && ! 101: IP_TIMESTAMP_ORDER(port->ip_timestamp, timestamp)); ! 102: ip_unlock(port); ! 103: ! 104: if (died) { ! 105: #if MACH_IPC_COMPAT ! 106: if (bits & IE_BITS_COMPAT) ! 107: return; ! 108: #endif MACH_IPC_COMPAT ! 109: ! 110: /* pretend this is a dead-name entry */ ! 111: ! 112: bits &= ~(IE_BITS_TYPE_MASK|IE_BITS_MAREQUEST); ! 113: bits |= MACH_PORT_TYPE_DEAD_NAME; ! 114: if (request != 0) ! 115: bits++; ! 116: request = 0; ! 117: } ! 118: } ! 119: ! 120: type = IE_BITS_TYPE(bits); ! 121: #if MACH_IPC_COMPAT ! 122: if (bits & IE_BITS_COMPAT) ! 123: type |= MACH_PORT_TYPE_COMPAT; ! 124: else ! 125: #endif MACH_IPC_COMPAT ! 126: if (request != 0) ! 127: type |= MACH_PORT_TYPE_DNREQUEST; ! 128: if (bits & IE_BITS_MAREQUEST) ! 129: type |= MACH_PORT_TYPE_MAREQUEST; ! 130: ! 131: actual = *actualp; ! 132: names[actual] = name; ! 133: types[actual] = type; ! 134: *actualp = actual+1; ! 135: } ! 136: ! 137: /* ! 138: * Routine: mach_port_names [kernel call] ! 139: * Purpose: ! 140: * Retrieves a list of the rights present in the space, ! 141: * along with type information. (Same as returned ! 142: * by mach_port_type.) The names are returned in ! 143: * no particular order, but they (and the type info) ! 144: * are an accurate snapshot of the space. ! 145: * Conditions: ! 146: * Nothing locked. ! 147: * Returns: ! 148: * KERN_SUCCESS Arrays of names and types returned. ! 149: * KERN_INVALID_TASK The space is null. ! 150: * KERN_INVALID_TASK The space is dead. ! 151: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 152: */ ! 153: ! 154: kern_return_t ! 155: mach_port_names( ! 156: ipc_space_t space, ! 157: mach_port_t **namesp, ! 158: mach_msg_type_number_t *namesCnt, ! 159: mach_port_type_t **typesp, ! 160: mach_msg_type_number_t *typesCnt) ! 161: { ! 162: ipc_tree_entry_t tentry; ! 163: ipc_entry_t table; ! 164: ipc_entry_num_t tsize; ! 165: mach_port_index_t index; ! 166: ipc_entry_num_t actual; /* this many names */ ! 167: ipc_port_timestamp_t timestamp; /* logical time of this operation */ ! 168: mach_port_t *names; ! 169: mach_port_type_t *types; ! 170: kern_return_t kr; ! 171: ! 172: vm_size_t size; /* size of allocated memory */ ! 173: vm_offset_t addr1; /* allocated memory, for names */ ! 174: vm_offset_t addr2; /* allocated memory, for types */ ! 175: vm_map_copy_t memory1; /* copied-in memory, for names */ ! 176: vm_map_copy_t memory2; /* copied-in memory, for types */ ! 177: ! 178: /* safe simplifying assumption */ ! 179: assert_static(sizeof(mach_port_t) == sizeof(mach_port_type_t)); ! 180: ! 181: if (space == IS_NULL) ! 182: return KERN_INVALID_TASK; ! 183: ! 184: size = 0; ! 185: ! 186: for (;;) { ! 187: ipc_entry_num_t bound; ! 188: vm_size_t size_needed; ! 189: ! 190: is_read_lock(space); ! 191: if (!space->is_active) { ! 192: is_read_unlock(space); ! 193: if (size != 0) { ! 194: kmem_free(ipc_kernel_map, addr1, size); ! 195: kmem_free(ipc_kernel_map, addr2, size); ! 196: } ! 197: return KERN_INVALID_TASK; ! 198: } ! 199: ! 200: /* upper bound on number of names in the space */ ! 201: ! 202: bound = space->is_table_size + space->is_tree_total; ! 203: size_needed = round_page(bound * sizeof(mach_port_t)); ! 204: ! 205: if (size_needed <= size) ! 206: break; ! 207: ! 208: is_read_unlock(space); ! 209: ! 210: if (size != 0) { ! 211: kmem_free(ipc_kernel_map, addr1, size); ! 212: kmem_free(ipc_kernel_map, addr2, size); ! 213: } ! 214: size = size_needed; ! 215: ! 216: kr = vm_allocate(ipc_kernel_map, &addr1, size, TRUE); ! 217: if (kr != KERN_SUCCESS) ! 218: return KERN_RESOURCE_SHORTAGE; ! 219: ! 220: kr = vm_allocate(ipc_kernel_map, &addr2, size, TRUE); ! 221: if (kr != KERN_SUCCESS) { ! 222: kmem_free(ipc_kernel_map, addr1, size); ! 223: return KERN_RESOURCE_SHORTAGE; ! 224: } ! 225: ! 226: /* can't fault while we hold locks */ ! 227: ! 228: kr = vm_map_pageable(ipc_kernel_map, addr1, addr1 + size, ! 229: VM_PROT_READ|VM_PROT_WRITE); ! 230: assert(kr == KERN_SUCCESS); ! 231: ! 232: kr = vm_map_pageable(ipc_kernel_map, addr2, addr2 + size, ! 233: VM_PROT_READ|VM_PROT_WRITE); ! 234: assert(kr == KERN_SUCCESS); ! 235: } ! 236: /* space is read-locked and active */ ! 237: ! 238: names = (mach_port_t *) addr1; ! 239: types = (mach_port_type_t *) addr2; ! 240: actual = 0; ! 241: ! 242: timestamp = ipc_port_timestamp(); ! 243: ! 244: table = space->is_table; ! 245: tsize = space->is_table_size; ! 246: ! 247: for (index = 0; index < tsize; index++) { ! 248: ipc_entry_t entry = &table[index]; ! 249: ipc_entry_bits_t bits = entry->ie_bits; ! 250: ! 251: if (IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE) { ! 252: mach_port_t name = MACH_PORT_MAKEB(index, bits); ! 253: ! 254: mach_port_names_helper(timestamp, entry, name, ! 255: names, types, &actual); ! 256: } ! 257: } ! 258: ! 259: for (tentry = ipc_splay_traverse_start(&space->is_tree); ! 260: tentry != ITE_NULL; ! 261: tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) { ! 262: ipc_entry_t entry = &tentry->ite_entry; ! 263: mach_port_t name = tentry->ite_name; ! 264: ! 265: assert(IE_BITS_TYPE(tentry->ite_bits) != MACH_PORT_TYPE_NONE); ! 266: ! 267: mach_port_names_helper(timestamp, entry, name, ! 268: names, types, &actual); ! 269: } ! 270: ipc_splay_traverse_finish(&space->is_tree); ! 271: is_read_unlock(space); ! 272: ! 273: if (actual == 0) { ! 274: memory1 = VM_MAP_COPY_NULL; ! 275: memory2 = VM_MAP_COPY_NULL; ! 276: ! 277: if (size != 0) { ! 278: kmem_free(ipc_kernel_map, addr1, size); ! 279: kmem_free(ipc_kernel_map, addr2, size); ! 280: } ! 281: } else { ! 282: vm_size_t size_used; ! 283: ! 284: size_used = round_page(actual * sizeof(mach_port_t)); ! 285: ! 286: /* ! 287: * Make used memory pageable and get it into ! 288: * copied-in form. Free any unused memory. ! 289: */ ! 290: ! 291: kr = vm_map_pageable(ipc_kernel_map, ! 292: addr1, addr1 + size_used, ! 293: VM_PROT_NONE); ! 294: assert(kr == KERN_SUCCESS); ! 295: ! 296: kr = vm_map_pageable(ipc_kernel_map, ! 297: addr2, addr2 + size_used, ! 298: VM_PROT_NONE); ! 299: assert(kr == KERN_SUCCESS); ! 300: ! 301: kr = vm_map_copyin(ipc_kernel_map, addr1, size_used, ! 302: TRUE, &memory1); ! 303: assert(kr == KERN_SUCCESS); ! 304: ! 305: kr = vm_map_copyin(ipc_kernel_map, addr2, size_used, ! 306: TRUE, &memory2); ! 307: assert(kr == KERN_SUCCESS); ! 308: ! 309: if (size_used != size) { ! 310: kmem_free(ipc_kernel_map, ! 311: addr1 + size_used, size - size_used); ! 312: kmem_free(ipc_kernel_map, ! 313: addr2 + size_used, size - size_used); ! 314: } ! 315: } ! 316: ! 317: *namesp = (mach_port_t *) memory1; ! 318: *namesCnt = actual; ! 319: *typesp = (mach_port_type_t *) memory2; ! 320: *typesCnt = actual; ! 321: return KERN_SUCCESS; ! 322: } ! 323: ! 324: /* ! 325: * Routine: mach_port_type [kernel call] ! 326: * Purpose: ! 327: * Retrieves the type of a right in the space. ! 328: * The type is a bitwise combination of one or more ! 329: * of the following type bits: ! 330: * MACH_PORT_TYPE_SEND ! 331: * MACH_PORT_TYPE_RECEIVE ! 332: * MACH_PORT_TYPE_SEND_ONCE ! 333: * MACH_PORT_TYPE_PORT_SET ! 334: * MACH_PORT_TYPE_DEAD_NAME ! 335: * In addition, the following pseudo-type bits may be present: ! 336: * MACH_PORT_TYPE_DNREQUEST ! 337: * A dead-name notification is requested. ! 338: * MACH_PORT_TYPE_MAREQUEST ! 339: * The send/receive right is blocked; ! 340: * a msg-accepted notification is outstanding. ! 341: * MACH_PORT_TYPE_COMPAT ! 342: * This is a compatibility-mode right; ! 343: * when the port dies, it will disappear ! 344: * instead of turning into a dead-name. ! 345: * Conditions: ! 346: * Nothing locked. ! 347: * Returns: ! 348: * KERN_SUCCESS Type is returned. ! 349: * KERN_INVALID_TASK The space is null. ! 350: * KERN_INVALID_TASK The space is dead. ! 351: * KERN_INVALID_NAME The name doesn't denote a right. ! 352: */ ! 353: ! 354: kern_return_t ! 355: mach_port_type( ! 356: ipc_space_t space, ! 357: mach_port_t name, ! 358: mach_port_type_t *typep) ! 359: { ! 360: mach_port_urefs_t urefs; ! 361: ipc_entry_t entry; ! 362: kern_return_t kr; ! 363: ! 364: if (space == IS_NULL) ! 365: return KERN_INVALID_TASK; ! 366: ! 367: kr = ipc_right_lookup_write(space, name, &entry); ! 368: if (kr != KERN_SUCCESS) ! 369: return kr; ! 370: /* space is write-locked and active */ ! 371: ! 372: kr = ipc_right_info(space, name, entry, typep, &urefs); ! 373: if (kr == KERN_SUCCESS) ! 374: is_write_unlock(space); ! 375: /* space is unlocked */ ! 376: return kr; ! 377: } ! 378: ! 379: /* ! 380: * Routine: mach_port_rename [kernel call] ! 381: * Purpose: ! 382: * Changes the name denoting a right, ! 383: * from oname to nname. ! 384: * Conditions: ! 385: * Nothing locked. ! 386: * Returns: ! 387: * KERN_SUCCESS The right is renamed. ! 388: * KERN_INVALID_TASK The space is null. ! 389: * KERN_INVALID_TASK The space is dead. ! 390: * KERN_INVALID_NAME The oname doesn't denote a right. ! 391: * KERN_INVALID_VALUE The nname isn't a legal name. ! 392: * KERN_NAME_EXISTS The nname already denotes a right. ! 393: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 394: */ ! 395: ! 396: kern_return_t ! 397: mach_port_rename( ! 398: ipc_space_t space, ! 399: mach_port_t oname, ! 400: mach_port_t nname) ! 401: { ! 402: if (space == IS_NULL) ! 403: return KERN_INVALID_TASK; ! 404: ! 405: if (!MACH_PORT_VALID(nname)) ! 406: return KERN_INVALID_VALUE; ! 407: ! 408: return ipc_object_rename(space, oname, nname); ! 409: } ! 410: ! 411: /* ! 412: * Routine: mach_port_allocate_name [kernel call] ! 413: * Purpose: ! 414: * Allocates a right in a space, using a specific name ! 415: * for the new right. Possible rights: ! 416: * MACH_PORT_RIGHT_RECEIVE ! 417: * MACH_PORT_RIGHT_PORT_SET ! 418: * MACH_PORT_RIGHT_DEAD_NAME ! 419: * ! 420: * A new port (allocated with MACH_PORT_RIGHT_RECEIVE) ! 421: * has no extant send or send-once rights and no queued ! 422: * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT ! 423: * and its make-send count is 0. It is not a member of ! 424: * a port set. It has no registered no-senders or ! 425: * port-destroyed notification requests. ! 426: * ! 427: * A new port set has no members. ! 428: * ! 429: * A new dead name has one user reference. ! 430: * Conditions: ! 431: * Nothing locked. ! 432: * Returns: ! 433: * KERN_SUCCESS The right is allocated. ! 434: * KERN_INVALID_TASK The space is null. ! 435: * KERN_INVALID_TASK The space is dead. ! 436: * KERN_INVALID_VALUE The name isn't a legal name. ! 437: * KERN_INVALID_VALUE "right" isn't a legal kind of right. ! 438: * KERN_NAME_EXISTS The name already denotes a right. ! 439: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 440: */ ! 441: ! 442: kern_return_t ! 443: mach_port_allocate_name(space, right, name) ! 444: ipc_space_t space; ! 445: mach_port_right_t right; ! 446: mach_port_t name; ! 447: { ! 448: kern_return_t kr; ! 449: ! 450: if (space == IS_NULL) ! 451: return KERN_INVALID_TASK; ! 452: ! 453: if (!MACH_PORT_VALID(name)) ! 454: return KERN_INVALID_VALUE; ! 455: ! 456: switch (right) { ! 457: case MACH_PORT_RIGHT_RECEIVE: { ! 458: ipc_port_t port; ! 459: ! 460: kr = ipc_port_alloc_name(space, name, &port); ! 461: if (kr == KERN_SUCCESS) ! 462: ip_unlock(port); ! 463: break; ! 464: } ! 465: ! 466: case MACH_PORT_RIGHT_PORT_SET: { ! 467: ipc_pset_t pset; ! 468: ! 469: kr = ipc_pset_alloc_name(space, name, &pset); ! 470: if (kr == KERN_SUCCESS) ! 471: ips_unlock(pset); ! 472: break; ! 473: } ! 474: ! 475: case MACH_PORT_RIGHT_DEAD_NAME: ! 476: kr = ipc_object_alloc_dead_name(space, name); ! 477: break; ! 478: ! 479: default: ! 480: kr = KERN_INVALID_VALUE; ! 481: break; ! 482: } ! 483: ! 484: return kr; ! 485: } ! 486: ! 487: /* ! 488: * Routine: mach_port_allocate [kernel call] ! 489: * Purpose: ! 490: * Allocates a right in a space. Like mach_port_allocate_name, ! 491: * except that the implementation picks a name for the right. ! 492: * The name may be any legal name in the space that doesn't ! 493: * currently denote a right. ! 494: * Conditions: ! 495: * Nothing locked. ! 496: * Returns: ! 497: * KERN_SUCCESS The right is allocated. ! 498: * KERN_INVALID_TASK The space is null. ! 499: * KERN_INVALID_TASK The space is dead. ! 500: * KERN_INVALID_VALUE "right" isn't a legal kind of right. ! 501: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 502: * KERN_NO_SPACE No room in space for another right. ! 503: */ ! 504: ! 505: kern_return_t ! 506: mach_port_allocate(space, right, namep) ! 507: ipc_space_t space; ! 508: mach_port_right_t right; ! 509: mach_port_t *namep; ! 510: { ! 511: kern_return_t kr; ! 512: ! 513: if (space == IS_NULL) ! 514: return KERN_INVALID_TASK; ! 515: ! 516: switch (right) { ! 517: case MACH_PORT_RIGHT_RECEIVE: { ! 518: ipc_port_t port; ! 519: ! 520: kr = ipc_port_alloc(space, namep, &port); ! 521: if (kr == KERN_SUCCESS) ! 522: ip_unlock(port); ! 523: break; ! 524: } ! 525: ! 526: case MACH_PORT_RIGHT_PORT_SET: { ! 527: ipc_pset_t pset; ! 528: ! 529: kr = ipc_pset_alloc(space, namep, &pset); ! 530: if (kr == KERN_SUCCESS) ! 531: ips_unlock(pset); ! 532: break; ! 533: } ! 534: ! 535: case MACH_PORT_RIGHT_DEAD_NAME: ! 536: kr = ipc_object_alloc_dead(space, namep); ! 537: break; ! 538: ! 539: default: ! 540: kr = KERN_INVALID_VALUE; ! 541: break; ! 542: } ! 543: ! 544: return (kr); ! 545: } ! 546: ! 547: /* ! 548: * Routine: mach_port_destroy [kernel call] ! 549: * Purpose: ! 550: * Cleans up and destroys all rights denoted by a name ! 551: * in a space. The destruction of a receive right ! 552: * destroys the port, unless a port-destroyed request ! 553: * has been made for it; the destruction of a port-set right ! 554: * destroys the port set. ! 555: * Conditions: ! 556: * Nothing locked. ! 557: * Returns: ! 558: * KERN_SUCCESS The name is destroyed. ! 559: * KERN_INVALID_TASK The space is null. ! 560: * KERN_INVALID_TASK The space is dead. ! 561: * KERN_INVALID_NAME The name doesn't denote a right. ! 562: */ ! 563: ! 564: kern_return_t ! 565: mach_port_destroy( ! 566: ipc_space_t space, ! 567: mach_port_t name) ! 568: { ! 569: ipc_entry_t entry; ! 570: kern_return_t kr; ! 571: ! 572: if (space == IS_NULL) ! 573: return KERN_INVALID_TASK; ! 574: ! 575: kr = ipc_right_lookup_write(space, name, &entry); ! 576: if (kr != KERN_SUCCESS) ! 577: return kr; ! 578: /* space is write-locked and active */ ! 579: ! 580: kr = ipc_right_destroy(space, name, entry); /* unlocks space */ ! 581: return kr; ! 582: } ! 583: ! 584: /* ! 585: * Routine: mach_port_deallocate [kernel call] ! 586: * Purpose: ! 587: * Deallocates a user reference from a send right, ! 588: * send-once right, or a dead-name right. May ! 589: * deallocate the right, if this is the last uref, ! 590: * and destroy the name, if it doesn't denote ! 591: * other rights. ! 592: * Conditions: ! 593: * Nothing locked. ! 594: * Returns: ! 595: * KERN_SUCCESS The uref is deallocated. ! 596: * KERN_INVALID_TASK The space is null. ! 597: * KERN_INVALID_TASK The space is dead. ! 598: * KERN_INVALID_NAME The name doesn't denote a right. ! 599: * KERN_INVALID_RIGHT The right isn't correct. ! 600: */ ! 601: ! 602: kern_return_t ! 603: mach_port_deallocate( ! 604: ipc_space_t space, ! 605: mach_port_t name) ! 606: { ! 607: ipc_entry_t entry; ! 608: kern_return_t kr; ! 609: ! 610: if (space == IS_NULL) ! 611: return KERN_INVALID_TASK; ! 612: ! 613: kr = ipc_right_lookup_write(space, name, &entry); ! 614: if (kr != KERN_SUCCESS) ! 615: return kr; ! 616: /* space is write-locked */ ! 617: ! 618: kr = ipc_right_dealloc(space, name, entry); /* unlocks space */ ! 619: return kr; ! 620: } ! 621: ! 622: /* ! 623: * Routine: mach_port_get_refs [kernel call] ! 624: * Purpose: ! 625: * Retrieves the number of user references held by a right. ! 626: * Receive rights, port-set rights, and send-once rights ! 627: * always have one user reference. Returns zero if the ! 628: * name denotes a right, but not the queried right. ! 629: * Conditions: ! 630: * Nothing locked. ! 631: * Returns: ! 632: * KERN_SUCCESS Number of urefs returned. ! 633: * KERN_INVALID_TASK The space is null. ! 634: * KERN_INVALID_TASK The space is dead. ! 635: * KERN_INVALID_VALUE "right" isn't a legal value. ! 636: * KERN_INVALID_NAME The name doesn't denote a right. ! 637: */ ! 638: ! 639: kern_return_t ! 640: mach_port_get_refs( ! 641: ipc_space_t space, ! 642: mach_port_t name, ! 643: mach_port_right_t right, ! 644: mach_port_urefs_t *urefsp) ! 645: { ! 646: mach_port_type_t type; ! 647: mach_port_urefs_t urefs; ! 648: ipc_entry_t entry; ! 649: kern_return_t kr; ! 650: ! 651: if (space == IS_NULL) ! 652: return KERN_INVALID_TASK; ! 653: ! 654: if (right >= MACH_PORT_RIGHT_NUMBER) ! 655: return KERN_INVALID_VALUE; ! 656: ! 657: kr = ipc_right_lookup_write(space, name, &entry); ! 658: if (kr != KERN_SUCCESS) ! 659: return kr; ! 660: /* space is write-locked and active */ ! 661: ! 662: kr = ipc_right_info(space, name, entry, &type, &urefs); /* unlocks */ ! 663: if (kr != KERN_SUCCESS) ! 664: return kr; /* space is unlocked */ ! 665: is_write_unlock(space); ! 666: ! 667: if (type & MACH_PORT_TYPE(right)) ! 668: switch (right) { ! 669: case MACH_PORT_RIGHT_SEND_ONCE: ! 670: assert(urefs == 1); ! 671: /* fall-through */ ! 672: ! 673: case MACH_PORT_RIGHT_PORT_SET: ! 674: case MACH_PORT_RIGHT_RECEIVE: ! 675: *urefsp = 1; ! 676: break; ! 677: ! 678: case MACH_PORT_RIGHT_DEAD_NAME: ! 679: case MACH_PORT_RIGHT_SEND: ! 680: assert(urefs > 0); ! 681: *urefsp = urefs; ! 682: break; ! 683: ! 684: default: ! 685: panic("mach_port_get_refs: strange rights"); ! 686: } ! 687: else ! 688: *urefsp = 0; ! 689: ! 690: return kr; ! 691: } ! 692: ! 693: /* ! 694: * Routine: mach_port_mod_refs ! 695: * Purpose: ! 696: * Modifies the number of user references held by a right. ! 697: * The resulting number of user references must be non-negative. ! 698: * If it is zero, the right is deallocated. If the name ! 699: * doesn't denote other rights, it is destroyed. ! 700: * Conditions: ! 701: * Nothing locked. ! 702: * Returns: ! 703: * KERN_SUCCESS Modified number of urefs. ! 704: * KERN_INVALID_TASK The space is null. ! 705: * KERN_INVALID_TASK The space is dead. ! 706: * KERN_INVALID_VALUE "right" isn't a legal value. ! 707: * KERN_INVALID_NAME The name doesn't denote a right. ! 708: * KERN_INVALID_RIGHT Name doesn't denote specified right. ! 709: * KERN_INVALID_VALUE Impossible modification to urefs. ! 710: * KERN_UREFS_OVERFLOW Urefs would overflow. ! 711: */ ! 712: ! 713: kern_return_t ! 714: mach_port_mod_refs( ! 715: ipc_space_t space, ! 716: mach_port_t name, ! 717: mach_port_right_t right, ! 718: mach_port_delta_t delta) ! 719: { ! 720: ipc_entry_t entry; ! 721: kern_return_t kr; ! 722: ! 723: if (space == IS_NULL) ! 724: return KERN_INVALID_TASK; ! 725: ! 726: if (right >= MACH_PORT_RIGHT_NUMBER) ! 727: return KERN_INVALID_VALUE; ! 728: ! 729: kr = ipc_right_lookup_write(space, name, &entry); ! 730: if (kr != KERN_SUCCESS) ! 731: return kr; ! 732: /* space is write-locked and active */ ! 733: ! 734: kr = ipc_right_delta(space, name, entry, right, delta); /* unlocks */ ! 735: return kr; ! 736: } ! 737: ! 738: /* ! 739: * Routine: old_mach_port_get_receive_status [kernel call] ! 740: * Purpose: ! 741: * Compatibility for code written before sequence numbers. ! 742: * Retrieves mucho info about a receive right. ! 743: * Conditions: ! 744: * Nothing locked. ! 745: * Returns: ! 746: * KERN_SUCCESS Retrieved status. ! 747: * KERN_INVALID_TASK The space is null. ! 748: * KERN_INVALID_TASK The space is dead. ! 749: * KERN_INVALID_NAME The name doesn't denote a right. ! 750: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 751: */ ! 752: ! 753: kern_return_t ! 754: old_mach_port_get_receive_status(space, name, statusp) ! 755: ipc_space_t space; ! 756: mach_port_t name; ! 757: old_mach_port_status_t *statusp; ! 758: { ! 759: mach_port_status_t status; ! 760: kern_return_t kr; ! 761: ! 762: kr = mach_port_get_receive_status(space, name, &status); ! 763: if (kr != KERN_SUCCESS) ! 764: return kr; ! 765: ! 766: statusp->mps_pset = status.mps_pset; ! 767: statusp->mps_mscount = status.mps_mscount; ! 768: statusp->mps_qlimit = status.mps_qlimit; ! 769: statusp->mps_msgcount = status.mps_msgcount; ! 770: statusp->mps_sorights = status.mps_sorights; ! 771: statusp->mps_srights = status.mps_srights; ! 772: statusp->mps_pdrequest = status.mps_pdrequest; ! 773: statusp->mps_nsrequest = status.mps_nsrequest; ! 774: ! 775: return KERN_SUCCESS; ! 776: } ! 777: ! 778: /* ! 779: * Routine: mach_port_set_qlimit [kernel call] ! 780: * Purpose: ! 781: * Changes a receive right's queue limit. ! 782: * The new queue limit must be between 0 and ! 783: * MACH_PORT_QLIMIT_MAX, inclusive. ! 784: * Conditions: ! 785: * Nothing locked. ! 786: * Returns: ! 787: * KERN_SUCCESS Set queue limit. ! 788: * KERN_INVALID_TASK The space is null. ! 789: * KERN_INVALID_TASK The space is dead. ! 790: * KERN_INVALID_NAME The name doesn't denote a right. ! 791: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 792: * KERN_INVALID_VALUE Illegal queue limit. ! 793: */ ! 794: ! 795: kern_return_t ! 796: mach_port_set_qlimit(space, name, qlimit) ! 797: ipc_space_t space; ! 798: mach_port_t name; ! 799: mach_port_msgcount_t qlimit; ! 800: { ! 801: ipc_port_t port; ! 802: kern_return_t kr; ! 803: ! 804: if (space == IS_NULL) ! 805: return KERN_INVALID_TASK; ! 806: ! 807: if (qlimit > MACH_PORT_QLIMIT_MAX) ! 808: return KERN_INVALID_VALUE; ! 809: ! 810: kr = ipc_port_translate_receive(space, name, &port); ! 811: if (kr != KERN_SUCCESS) ! 812: return kr; ! 813: /* port is locked and active */ ! 814: ! 815: ipc_port_set_qlimit(port, qlimit); ! 816: ! 817: ip_unlock(port); ! 818: return KERN_SUCCESS; ! 819: } ! 820: ! 821: /* ! 822: * Routine: mach_port_set_mscount [kernel call] ! 823: * Purpose: ! 824: * Changes a receive right's make-send count. ! 825: * Conditions: ! 826: * Nothing locked. ! 827: * Returns: ! 828: * KERN_SUCCESS Set make-send count. ! 829: * KERN_INVALID_TASK The space is null. ! 830: * KERN_INVALID_TASK The space is dead. ! 831: * KERN_INVALID_NAME The name doesn't denote a right. ! 832: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 833: */ ! 834: ! 835: kern_return_t ! 836: mach_port_set_mscount( ! 837: ipc_space_t space, ! 838: mach_port_t name, ! 839: mach_port_mscount_t mscount) ! 840: { ! 841: ipc_port_t port; ! 842: kern_return_t kr; ! 843: ! 844: if (space == IS_NULL) ! 845: return KERN_INVALID_TASK; ! 846: ! 847: kr = ipc_port_translate_receive(space, name, &port); ! 848: if (kr != KERN_SUCCESS) ! 849: return kr; ! 850: /* port is locked and active */ ! 851: ! 852: ipc_port_set_mscount(port, mscount); ! 853: ! 854: ip_unlock(port); ! 855: return KERN_SUCCESS; ! 856: } ! 857: ! 858: /* ! 859: * Routine: mach_port_set_seqno [kernel call] ! 860: * Purpose: ! 861: * Changes a receive right's sequence number. ! 862: * Conditions: ! 863: * Nothing locked. ! 864: * Returns: ! 865: * KERN_SUCCESS Set sequence number. ! 866: * KERN_INVALID_TASK The space is null. ! 867: * KERN_INVALID_TASK The space is dead. ! 868: * KERN_INVALID_NAME The name doesn't denote a right. ! 869: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 870: */ ! 871: ! 872: kern_return_t ! 873: mach_port_set_seqno( ! 874: ipc_space_t space, ! 875: mach_port_t name, ! 876: mach_port_seqno_t seqno) ! 877: { ! 878: ipc_port_t port; ! 879: kern_return_t kr; ! 880: ! 881: if (space == IS_NULL) ! 882: return KERN_INVALID_TASK; ! 883: ! 884: kr = ipc_port_translate_receive(space, name, &port); ! 885: if (kr != KERN_SUCCESS) ! 886: return kr; ! 887: /* port is locked and active */ ! 888: ! 889: ipc_port_set_seqno(port, seqno); ! 890: ! 891: ip_unlock(port); ! 892: return KERN_SUCCESS; ! 893: } ! 894: ! 895: /* ! 896: * Routine: mach_port_gst_helper ! 897: * Purpose: ! 898: * A helper function for mach_port_get_set_status. ! 899: */ ! 900: ! 901: void ! 902: mach_port_gst_helper( ! 903: ipc_pset_t pset, ! 904: ipc_port_t port, ! 905: ipc_entry_num_t maxnames, ! 906: mach_port_t *names, ! 907: ipc_entry_num_t *actualp) ! 908: { ! 909: ipc_pset_t ip_pset; ! 910: mach_port_t name; ! 911: ! 912: assert(port != IP_NULL); ! 913: ! 914: ip_lock(port); ! 915: assert(ip_active(port)); ! 916: ! 917: name = port->ip_receiver_name; ! 918: assert(name != MACH_PORT_NULL); ! 919: ip_pset = port->ip_pset; ! 920: ! 921: ip_unlock(port); ! 922: ! 923: if (pset == ip_pset) { ! 924: ipc_entry_num_t actual = *actualp; ! 925: ! 926: if (actual < maxnames) ! 927: names[actual] = name; ! 928: ! 929: *actualp = actual+1; ! 930: } ! 931: } ! 932: ! 933: /* ! 934: * Routine: mach_port_get_set_status [kernel call] ! 935: * Purpose: ! 936: * Retrieves a list of members in a port set. ! 937: * Returns the space's name for each receive right member. ! 938: * Conditions: ! 939: * Nothing locked. ! 940: * Returns: ! 941: * KERN_SUCCESS Retrieved list of members. ! 942: * KERN_INVALID_TASK The space is null. ! 943: * KERN_INVALID_TASK The space is dead. ! 944: * KERN_INVALID_NAME The name doesn't denote a right. ! 945: * KERN_INVALID_RIGHT Name doesn't denote a port set. ! 946: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 947: */ ! 948: ! 949: kern_return_t ! 950: mach_port_get_set_status( ! 951: ipc_space_t space, ! 952: mach_port_t name, ! 953: mach_port_t **members, ! 954: mach_msg_type_number_t *membersCnt) ! 955: { ! 956: ipc_entry_num_t actual; /* this many members */ ! 957: ipc_entry_num_t maxnames; /* space for this many members */ ! 958: kern_return_t kr; ! 959: ! 960: vm_size_t size; /* size of allocated memory */ ! 961: vm_offset_t addr; /* allocated memory */ ! 962: vm_map_copy_t memory; /* copied-in memory */ ! 963: ! 964: if (space == IS_NULL) ! 965: return KERN_INVALID_TASK; ! 966: ! 967: size = PAGE_SIZE; /* initial guess */ ! 968: ! 969: for (;;) { ! 970: ipc_tree_entry_t tentry; ! 971: ipc_entry_t entry, table; ! 972: ipc_entry_num_t tsize; ! 973: mach_port_index_t index; ! 974: mach_port_t *names; ! 975: ipc_pset_t pset; ! 976: ! 977: kr = vm_allocate(ipc_kernel_map, &addr, size, TRUE); ! 978: if (kr != KERN_SUCCESS) ! 979: return KERN_RESOURCE_SHORTAGE; ! 980: ! 981: /* can't fault while we hold locks */ ! 982: ! 983: kr = vm_map_pageable(ipc_kernel_map, addr, addr + size, ! 984: VM_PROT_READ|VM_PROT_WRITE); ! 985: assert(kr == KERN_SUCCESS); ! 986: ! 987: kr = ipc_right_lookup_read(space, name, &entry); ! 988: if (kr != KERN_SUCCESS) { ! 989: kmem_free(ipc_kernel_map, addr, size); ! 990: return kr; ! 991: } ! 992: /* space is read-locked and active */ ! 993: ! 994: if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_PORT_SET) { ! 995: is_read_unlock(space); ! 996: kmem_free(ipc_kernel_map, addr, size); ! 997: return KERN_INVALID_RIGHT; ! 998: } ! 999: ! 1000: pset = (ipc_pset_t) entry->ie_object; ! 1001: assert(pset != IPS_NULL); ! 1002: /* the port set must be active */ ! 1003: ! 1004: names = (mach_port_t *) addr; ! 1005: maxnames = size / sizeof(mach_port_t); ! 1006: actual = 0; ! 1007: ! 1008: table = space->is_table; ! 1009: tsize = space->is_table_size; ! 1010: ! 1011: for (index = 0; index < tsize; index++) { ! 1012: ipc_entry_t ientry = &table[index]; ! 1013: ipc_entry_bits_t bits = ientry->ie_bits; ! 1014: ! 1015: if (bits & MACH_PORT_TYPE_RECEIVE) { ! 1016: ipc_port_t port = ! 1017: (ipc_port_t) ientry->ie_object; ! 1018: ! 1019: mach_port_gst_helper(pset, port, maxnames, ! 1020: names, &actual); ! 1021: } ! 1022: } ! 1023: ! 1024: for (tentry = ipc_splay_traverse_start(&space->is_tree); ! 1025: tentry != ITE_NULL; ! 1026: tentry = ipc_splay_traverse_next(&space->is_tree,FALSE)) { ! 1027: ipc_entry_bits_t bits = tentry->ite_bits; ! 1028: ! 1029: assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE); ! 1030: ! 1031: if (bits & MACH_PORT_TYPE_RECEIVE) { ! 1032: ipc_port_t port = ! 1033: (ipc_port_t) tentry->ite_object; ! 1034: ! 1035: mach_port_gst_helper(pset, port, maxnames, ! 1036: names, &actual); ! 1037: } ! 1038: } ! 1039: ipc_splay_traverse_finish(&space->is_tree); ! 1040: is_read_unlock(space); ! 1041: ! 1042: if (actual <= maxnames) ! 1043: break; ! 1044: ! 1045: /* didn't have enough memory; allocate more */ ! 1046: ! 1047: kmem_free(ipc_kernel_map, addr, size); ! 1048: size = round_page(actual * sizeof(mach_port_t)) + PAGE_SIZE; ! 1049: } ! 1050: ! 1051: if (actual == 0) { ! 1052: memory = VM_MAP_COPY_NULL; ! 1053: ! 1054: kmem_free(ipc_kernel_map, addr, size); ! 1055: } else { ! 1056: vm_size_t size_used; ! 1057: ! 1058: size_used = round_page(actual * sizeof(mach_port_t)); ! 1059: ! 1060: /* ! 1061: * Make used memory pageable and get it into ! 1062: * copied-in form. Free any unused memory. ! 1063: */ ! 1064: ! 1065: kr = vm_map_pageable(ipc_kernel_map, ! 1066: addr, addr + size_used, ! 1067: VM_PROT_NONE); ! 1068: assert(kr == KERN_SUCCESS); ! 1069: ! 1070: kr = vm_map_copyin(ipc_kernel_map, addr, size_used, ! 1071: TRUE, &memory); ! 1072: assert(kr == KERN_SUCCESS); ! 1073: ! 1074: if (size_used != size) ! 1075: kmem_free(ipc_kernel_map, ! 1076: addr + size_used, size - size_used); ! 1077: } ! 1078: ! 1079: *members = (mach_port_t *) memory; ! 1080: *membersCnt = actual; ! 1081: return KERN_SUCCESS; ! 1082: } ! 1083: ! 1084: /* ! 1085: * Routine: mach_port_move_member [kernel call] ! 1086: * Purpose: ! 1087: * If after is MACH_PORT_NULL, removes member ! 1088: * from the port set it is in. Otherwise, adds ! 1089: * member to after, removing it from any set ! 1090: * it might already be in. ! 1091: * Conditions: ! 1092: * Nothing locked. ! 1093: * Returns: ! 1094: * KERN_SUCCESS Moved the port. ! 1095: * KERN_INVALID_TASK The space is null. ! 1096: * KERN_INVALID_TASK The space is dead. ! 1097: * KERN_INVALID_NAME Member didn't denote a right. ! 1098: * KERN_INVALID_RIGHT Member didn't denote a receive right. ! 1099: * KERN_INVALID_NAME After didn't denote a right. ! 1100: * KERN_INVALID_RIGHT After didn't denote a port set right. ! 1101: * KERN_NOT_IN_SET ! 1102: * After is MACH_PORT_NULL and Member isn't in a port set. ! 1103: */ ! 1104: ! 1105: kern_return_t ! 1106: mach_port_move_member( ! 1107: ipc_space_t space, ! 1108: mach_port_t member, ! 1109: mach_port_t after) ! 1110: { ! 1111: ipc_entry_t entry; ! 1112: ipc_port_t port; ! 1113: ipc_pset_t nset; ! 1114: kern_return_t kr; ! 1115: ! 1116: if (space == IS_NULL) ! 1117: return KERN_INVALID_TASK; ! 1118: ! 1119: kr = ipc_right_lookup_read(space, member, &entry); ! 1120: if (kr != KERN_SUCCESS) ! 1121: return kr; ! 1122: /* space is read-locked and active */ ! 1123: ! 1124: if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) { ! 1125: is_read_unlock(space); ! 1126: return KERN_INVALID_RIGHT; ! 1127: } ! 1128: ! 1129: port = (ipc_port_t) entry->ie_object; ! 1130: assert(port != IP_NULL); ! 1131: ! 1132: if (after == MACH_PORT_NULL) ! 1133: nset = IPS_NULL; ! 1134: else { ! 1135: entry = ipc_entry_lookup(space, after); ! 1136: if (entry == IE_NULL) { ! 1137: is_read_unlock(space); ! 1138: return KERN_INVALID_NAME; ! 1139: } ! 1140: ! 1141: if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) { ! 1142: is_read_unlock(space); ! 1143: return KERN_INVALID_RIGHT; ! 1144: } ! 1145: ! 1146: nset = (ipc_pset_t) entry->ie_object; ! 1147: assert(nset != IPS_NULL); ! 1148: } ! 1149: ! 1150: kr = ipc_pset_move(space, port, nset); ! 1151: /* space is unlocked */ ! 1152: return kr; ! 1153: } ! 1154: ! 1155: /* ! 1156: * Routine: mach_port_request_notification [kernel call] ! 1157: * Purpose: ! 1158: * Requests a notification. The caller supplies ! 1159: * a send-once right for the notification to use, ! 1160: * and the call returns the previously registered ! 1161: * send-once right, if any. Possible types: ! 1162: * ! 1163: * MACH_NOTIFY_PORT_DESTROYED ! 1164: * Requests a port-destroyed notification ! 1165: * for a receive right. Sync should be zero. ! 1166: * MACH_NOTIFY_NO_SENDERS ! 1167: * Requests a no-senders notification for a ! 1168: * receive right. If there are currently no ! 1169: * senders, sync is less than or equal to the ! 1170: * current make-send count, and a send-once right ! 1171: * is supplied, then an immediate no-senders ! 1172: * notification is generated. ! 1173: * MACH_NOTIFY_DEAD_NAME ! 1174: * Requests a dead-name notification for a send ! 1175: * or receive right. If the name is already a ! 1176: * dead name, sync is non-zero, and a send-once ! 1177: * right is supplied, then an immediate dead-name ! 1178: * notification is generated. ! 1179: * Conditions: ! 1180: * Nothing locked. ! 1181: * Returns: ! 1182: * KERN_SUCCESS Requested a notification. ! 1183: * KERN_INVALID_TASK The space is null. ! 1184: * KERN_INVALID_TASK The space is dead. ! 1185: * KERN_INVALID_VALUE Bad id value. ! 1186: * KERN_INVALID_NAME Name doesn't denote a right. ! 1187: * KERN_INVALID_RIGHT Name doesn't denote appropriate right. ! 1188: * KERN_INVALID_CAPABILITY The notify port is dead. ! 1189: * MACH_NOTIFY_PORT_DESTROYED: ! 1190: * KERN_INVALID_VALUE Sync isn't zero. ! 1191: * MACH_NOTIFY_DEAD_NAME: ! 1192: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 1193: * KERN_INVALID_ARGUMENT Name denotes dead name, but ! 1194: * sync is zero or notify is IP_NULL. ! 1195: * KERN_UREFS_OVERFLOW Name denotes dead name, but ! 1196: * generating immediate notif. would overflow urefs. ! 1197: */ ! 1198: ! 1199: kern_return_t ! 1200: mach_port_request_notification( ! 1201: ipc_space_t space, ! 1202: mach_port_t name, ! 1203: mach_msg_id_t id, ! 1204: mach_port_mscount_t sync, ! 1205: ipc_port_t notify, ! 1206: ipc_port_t *previousp) ! 1207: { ! 1208: kern_return_t kr; ! 1209: ! 1210: if (space == IS_NULL) ! 1211: return KERN_INVALID_TASK; ! 1212: ! 1213: if (notify == IP_DEAD) ! 1214: return KERN_INVALID_CAPABILITY; ! 1215: ! 1216: switch (id) { ! 1217: case MACH_NOTIFY_PORT_DESTROYED: { ! 1218: ipc_port_t port, previous; ! 1219: ! 1220: if (sync != 0) ! 1221: return KERN_INVALID_VALUE; ! 1222: ! 1223: kr = ipc_port_translate_receive(space, name, &port); ! 1224: if (kr != KERN_SUCCESS) ! 1225: return kr; ! 1226: /* port is locked and active */ ! 1227: ! 1228: ipc_port_pdrequest(port, notify, &previous); ! 1229: /* port is unlocked */ ! 1230: ! 1231: #if MACH_IPC_COMPAT ! 1232: /* ! 1233: * If previous was a send right instead of a send-once ! 1234: * right, we can't return it in the reply message. ! 1235: * So destroy it instead. ! 1236: */ ! 1237: ! 1238: if ((previous != IP_NULL) && ip_pdsendp(previous)) { ! 1239: ipc_port_release_send(ip_pdsend(previous)); ! 1240: previous = IP_NULL; ! 1241: } ! 1242: #endif MACH_IPC_COMPAT ! 1243: ! 1244: *previousp = previous; ! 1245: break; ! 1246: } ! 1247: ! 1248: case MACH_NOTIFY_NO_SENDERS: { ! 1249: ipc_port_t port; ! 1250: ! 1251: kr = ipc_port_translate_receive(space, name, &port); ! 1252: if (kr != KERN_SUCCESS) ! 1253: return kr; ! 1254: /* port is locked and active */ ! 1255: ! 1256: ipc_port_nsrequest(port, sync, notify, previousp); ! 1257: /* port is unlocked */ ! 1258: break; ! 1259: } ! 1260: ! 1261: case MACH_NOTIFY_DEAD_NAME: ! 1262: kr = ipc_right_dnrequest(space, name, sync != 0, ! 1263: notify, previousp); ! 1264: if (kr != KERN_SUCCESS) ! 1265: return kr; ! 1266: break; ! 1267: ! 1268: default: ! 1269: return KERN_INVALID_VALUE; ! 1270: } ! 1271: ! 1272: return KERN_SUCCESS; ! 1273: } ! 1274: ! 1275: /* ! 1276: * Routine: mach_port_insert_right [kernel call] ! 1277: * Purpose: ! 1278: * Inserts a right into a space, as if the space ! 1279: * voluntarily received the right in a message, ! 1280: * except that the right gets the specified name. ! 1281: * Conditions: ! 1282: * Nothing locked. ! 1283: * Returns: ! 1284: * KERN_SUCCESS Inserted the right. ! 1285: * KERN_INVALID_TASK The space is null. ! 1286: * KERN_INVALID_TASK The space is dead. ! 1287: * KERN_INVALID_VALUE The name isn't a legal name. ! 1288: * KERN_NAME_EXISTS The name already denotes a right. ! 1289: * KERN_INVALID_VALUE Message doesn't carry a port right. ! 1290: * KERN_INVALID_CAPABILITY Port is null or dead. ! 1291: * KERN_UREFS_OVERFLOW Urefs limit would be exceeded. ! 1292: * KERN_RIGHT_EXISTS Space has rights under another name. ! 1293: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 1294: */ ! 1295: ! 1296: kern_return_t ! 1297: mach_port_insert_right( ! 1298: ipc_space_t space, ! 1299: mach_port_t name, ! 1300: ipc_port_t poly, ! 1301: mach_msg_type_name_t polyPoly) ! 1302: { ! 1303: if (space == IS_NULL) ! 1304: return KERN_INVALID_TASK; ! 1305: ! 1306: if (!MACH_PORT_VALID(name) || ! 1307: !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly)) ! 1308: return KERN_INVALID_VALUE; ! 1309: ! 1310: if (!IO_VALID(poly)) ! 1311: return KERN_INVALID_CAPABILITY; ! 1312: ! 1313: return ipc_object_copyout_name(space, poly, polyPoly, FALSE, name); ! 1314: } ! 1315: ! 1316: /* ! 1317: * Routine: mach_port_extract_right [kernel call] ! 1318: * Purpose: ! 1319: * Extracts a right from a space, as if the space ! 1320: * voluntarily sent the right to the caller. ! 1321: * Conditions: ! 1322: * Nothing locked. ! 1323: * Returns: ! 1324: * KERN_SUCCESS Extracted the right. ! 1325: * KERN_INVALID_TASK The space is null. ! 1326: * KERN_INVALID_TASK The space is dead. ! 1327: * KERN_INVALID_VALUE Requested type isn't a port right. ! 1328: * KERN_INVALID_NAME Name doesn't denote a right. ! 1329: * KERN_INVALID_RIGHT Name doesn't denote appropriate right. ! 1330: */ ! 1331: ! 1332: kern_return_t ! 1333: mach_port_extract_right( ! 1334: ipc_space_t space, ! 1335: mach_port_t name, ! 1336: mach_msg_type_name_t msgt_name, ! 1337: ipc_port_t *poly, ! 1338: mach_msg_type_name_t *polyPoly) ! 1339: { ! 1340: kern_return_t kr; ! 1341: ! 1342: if (space == IS_NULL) ! 1343: return KERN_INVALID_TASK; ! 1344: ! 1345: if (!MACH_MSG_TYPE_PORT_ANY(msgt_name)) ! 1346: return KERN_INVALID_VALUE; ! 1347: ! 1348: kr = ipc_object_copyin(space, name, msgt_name, (ipc_object_t *) poly); ! 1349: ! 1350: if (kr == KERN_SUCCESS) ! 1351: *polyPoly = ipc_object_copyin_type(msgt_name); ! 1352: return kr; ! 1353: } ! 1354: ! 1355: /* ! 1356: * Routine: mach_port_get_receive_status [kernel call] ! 1357: * Purpose: ! 1358: * Retrieves mucho info about a receive right. ! 1359: * Conditions: ! 1360: * Nothing locked. ! 1361: * Returns: ! 1362: * KERN_SUCCESS Retrieved status. ! 1363: * KERN_INVALID_TASK The space is null. ! 1364: * KERN_INVALID_TASK The space is dead. ! 1365: * KERN_INVALID_NAME The name doesn't denote a right. ! 1366: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 1367: */ ! 1368: ! 1369: kern_return_t ! 1370: mach_port_get_receive_status(space, name, statusp) ! 1371: ipc_space_t space; ! 1372: mach_port_t name; ! 1373: mach_port_status_t *statusp; ! 1374: { ! 1375: ipc_port_t port; ! 1376: kern_return_t kr; ! 1377: ! 1378: if (space == IS_NULL) ! 1379: return KERN_INVALID_TASK; ! 1380: ! 1381: kr = ipc_port_translate_receive(space, name, &port); ! 1382: if (kr != KERN_SUCCESS) ! 1383: return kr; ! 1384: /* port is locked and active */ ! 1385: ! 1386: if (port->ip_pset != IPS_NULL) { ! 1387: ipc_pset_t pset = port->ip_pset; ! 1388: ! 1389: ips_lock(pset); ! 1390: if (!ips_active(pset)) { ! 1391: ipc_pset_remove(pset, port); ! 1392: ips_check_unlock(pset); ! 1393: goto no_port_set; ! 1394: } else { ! 1395: statusp->mps_pset = pset->ips_local_name; ! 1396: imq_lock(&pset->ips_messages); ! 1397: statusp->mps_seqno = port->ip_seqno; ! 1398: imq_unlock(&pset->ips_messages); ! 1399: ips_unlock(pset); ! 1400: assert(MACH_PORT_VALID(statusp->mps_pset)); ! 1401: } ! 1402: } else { ! 1403: no_port_set: ! 1404: statusp->mps_pset = MACH_PORT_NULL; ! 1405: imq_lock(&port->ip_messages); ! 1406: statusp->mps_seqno = port->ip_seqno; ! 1407: imq_unlock(&port->ip_messages); ! 1408: } ! 1409: ! 1410: statusp->mps_mscount = port->ip_mscount; ! 1411: statusp->mps_qlimit = port->ip_qlimit; ! 1412: statusp->mps_msgcount = port->ip_msgcount; ! 1413: statusp->mps_sorights = port->ip_sorights; ! 1414: statusp->mps_srights = port->ip_srights > 0; ! 1415: statusp->mps_pdrequest = port->ip_pdrequest != IP_NULL; ! 1416: statusp->mps_nsrequest = port->ip_nsrequest != IP_NULL; ! 1417: ip_unlock(port); ! 1418: ! 1419: return KERN_SUCCESS; ! 1420: } ! 1421: ! 1422: #ifdef MIGRATING_THREADS ! 1423: kern_return_t ! 1424: mach_port_set_rpcinfo(space, name, rpc_info, rpc_info_count) ! 1425: ipc_space_t space; ! 1426: mach_port_t name; ! 1427: void *rpc_info; ! 1428: unsigned int rpc_info_count; ! 1429: { ! 1430: ipc_target_t target; ! 1431: ipc_object_t object; ! 1432: kern_return_t kr; ! 1433: ! 1434: if (space == IS_NULL) ! 1435: return KERN_INVALID_TASK; ! 1436: ! 1437: kr = ipc_object_translate(space, name, ! 1438: MACH_PORT_RIGHT_PORT_SET, &object); ! 1439: if (kr == KERN_SUCCESS) ! 1440: target = &((ipc_pset_t)object)->ips_target; ! 1441: else { ! 1442: kr = ipc_object_translate(space, name, ! 1443: MACH_PORT_RIGHT_RECEIVE, &object); ! 1444: if (kr != KERN_SUCCESS) ! 1445: return kr; ! 1446: target = &((ipc_port_t)object)->ip_target; ! 1447: } ! 1448: ! 1449: /* port/pset is locked and active */ ! 1450: ! 1451: kr = port_machine_set_rpcinfo(target, rpc_info, rpc_info_count); ! 1452: ! 1453: io_unlock(object); ! 1454: ! 1455: return kr; ! 1456: } ! 1457: ! 1458: #if 1 ! 1459: int sacts, maxsacts; ! 1460: #endif ! 1461: ! 1462: sact_count() ! 1463: { ! 1464: printf("%d server activations in use, %d max\n", sacts, maxsacts); ! 1465: } ! 1466: ! 1467: kern_return_t ! 1468: mach_port_create_act(task, name, user_stack, user_rbuf, user_rbuf_size, out_act) ! 1469: task_t task; ! 1470: mach_port_t name; ! 1471: vm_offset_t user_stack; ! 1472: vm_offset_t user_rbuf; ! 1473: vm_size_t user_rbuf_size; ! 1474: Act **out_act; ! 1475: { ! 1476: ipc_target_t target; ! 1477: ipc_space_t space; ! 1478: ipc_object_t object; ! 1479: kern_return_t kr; ! 1480: Act *act; ! 1481: ! 1482: if (task == 0) ! 1483: return KERN_INVALID_TASK; ! 1484: ! 1485: /* First create the new activation. */ ! 1486: kr = act_create(task, user_stack, user_rbuf, user_rbuf_size, &act); ! 1487: if (kr != KERN_SUCCESS) ! 1488: return kr; ! 1489: ! 1490: space = task->itk_space; ! 1491: ! 1492: kr = ipc_object_translate(space, name, ! 1493: MACH_PORT_RIGHT_PORT_SET, &object); ! 1494: if (kr == KERN_SUCCESS) ! 1495: target = &((ipc_pset_t)object)->ips_target; ! 1496: else { ! 1497: kr = ipc_object_translate(space, name, ! 1498: MACH_PORT_RIGHT_RECEIVE, &object); ! 1499: if (kr != KERN_SUCCESS) { ! 1500: act_terminate(act); ! 1501: act_deallocate(act); ! 1502: return kr; ! 1503: } ! 1504: target = &((ipc_port_t)object)->ip_target; ! 1505: } ! 1506: ! 1507: /* port/pset is locked and active */ ! 1508: #if 0 ! 1509: printf("act port/pset %08x ipc_target %08x stack %08x act %08x\n", ! 1510: object, target, user_stack, act); ! 1511: #endif ! 1512: ! 1513: /* Assign the activation to the port's actpool. */ ! 1514: kr = act_set_target(act, target); ! 1515: if (kr != KERN_SUCCESS) { ! 1516: io_unlock(object); ! 1517: act_terminate(act); ! 1518: act_deallocate(act); ! 1519: return kr; ! 1520: } ! 1521: #if 0 ! 1522: printf(" actpool %08x act %08x\n", target->ip_actpool, act); ! 1523: #endif ! 1524: ! 1525: io_unlock(object); ! 1526: ! 1527: /* Pass our reference to the activation back to the user. */ ! 1528: *out_act = act; ! 1529: ! 1530: #if 1 ! 1531: sacts++; ! 1532: if (sacts > maxsacts) ! 1533: maxsacts = sacts; ! 1534: act->mact.pcb->ss.mpsfu_high = 0x69; ! 1535: #endif ! 1536: return KERN_SUCCESS; ! 1537: } ! 1538: ! 1539: #ifdef RPCKERNELSIG ! 1540: kern_return_t ! 1541: mach_port_set_syscall_right(task, name) ! 1542: task_t task; ! 1543: mach_port_t name; ! 1544: { ! 1545: ipc_entry_t entry; ! 1546: ipc_port_t port; ! 1547: kern_return_t kr; ! 1548: ! 1549: if (task == IS_NULL) ! 1550: return KERN_INVALID_TASK; ! 1551: ! 1552: kr = ipc_right_lookup_write(task, name, &entry); ! 1553: if (kr != KERN_SUCCESS) { ! 1554: return kr; ! 1555: } ! 1556: ! 1557: if (!(entry->ie_bits & MACH_PORT_TYPE(MACH_PORT_RIGHT_SEND))) { ! 1558: is_write_unlock(space); ! 1559: return KERN_INVALID_RIGHT; ! 1560: } ! 1561: ! 1562: task->syscall_ipc_entry = *entry; ! 1563: ! 1564: is_write_unlock(space); ! 1565: ! 1566: return KERN_SUCCESS; ! 1567: } ! 1568: #endif ! 1569: #endif /* MIGRATING_THREADS */ ! 1570: ! 1571: #if MACH_IPC_COMPAT ! 1572: ! 1573: /* ! 1574: * Routine: port_translate_compat ! 1575: * Purpose: ! 1576: * Converts a name to a receive right. ! 1577: * Conditions: ! 1578: * Nothing locked. If successful, the port ! 1579: * is returned locked and active. ! 1580: * Returns: ! 1581: * KERN_SUCCESS Port is returned. ! 1582: * KERN_INVALID_ARGUMENT The space is dead. ! 1583: * KERN_INVALID_ARGUMENT Name doesn't denote port rights. ! 1584: * KERN_NOT_RECEIVER Name denotes send, not receive, rights. ! 1585: * KERN_NOT_RECEIVER Name denotes a send-once right. ! 1586: * KERN_NOT_RECEIVER Name denotes a dead name. ! 1587: */ ! 1588: ! 1589: kern_return_t ! 1590: port_translate_compat(space, name, portp) ! 1591: ipc_space_t space; ! 1592: mach_port_t name; ! 1593: ipc_port_t *portp; ! 1594: { ! 1595: ipc_entry_t entry; ! 1596: mach_port_type_t type; ! 1597: mach_port_urefs_t urefs; ! 1598: ipc_port_t port; ! 1599: kern_return_t kr; ! 1600: ! 1601: kr = ipc_right_lookup_write(space, name, &entry); ! 1602: if (kr != KERN_SUCCESS) ! 1603: return KERN_INVALID_ARGUMENT; ! 1604: /* space is write-locked and active */ ! 1605: ! 1606: kr = ipc_right_info(space, name, entry, &type, &urefs); ! 1607: if (kr != KERN_SUCCESS) ! 1608: return KERN_INVALID_ARGUMENT; /* space is unlocked */ ! 1609: ! 1610: if ((type & (MACH_PORT_TYPE_RECEIVE)) == 0) { ! 1611: is_write_unlock(space); ! 1612: if (type & MACH_PORT_TYPE_PORT_OR_DEAD) ! 1613: return KERN_NOT_RECEIVER; ! 1614: else ! 1615: return KERN_INVALID_ARGUMENT; ! 1616: } ! 1617: ! 1618: port = (ipc_port_t) entry->ie_object; ! 1619: assert(port != IP_NULL); ! 1620: ! 1621: ip_lock(port); ! 1622: is_write_unlock(space); ! 1623: assert(ip_active(port)); ! 1624: ! 1625: *portp = port; ! 1626: return KERN_SUCCESS; ! 1627: } ! 1628: ! 1629: /* ! 1630: * Routine: convert_port_type ! 1631: * Purpose: ! 1632: * Convert a new mach_port_type_t to an old value. ! 1633: * Note send-once rights and dead names get ! 1634: * represented as send rights. The extra info ! 1635: * bits get dropped. ! 1636: */ ! 1637: ! 1638: mach_port_type_t ! 1639: convert_port_type(type) ! 1640: mach_port_type_t type; ! 1641: { ! 1642: switch (type & MACH_PORT_TYPE_ALL_RIGHTS) { ! 1643: case MACH_PORT_TYPE_SEND: ! 1644: case MACH_PORT_TYPE_SEND_ONCE: ! 1645: case MACH_PORT_TYPE_DEAD_NAME: ! 1646: return PORT_TYPE_SEND; ! 1647: ! 1648: case MACH_PORT_TYPE_RECEIVE: ! 1649: case MACH_PORT_TYPE_SEND_RECEIVE: ! 1650: return PORT_TYPE_RECEIVE_OWN; ! 1651: ! 1652: case MACH_PORT_TYPE_PORT_SET: ! 1653: return PORT_TYPE_SET; ! 1654: ! 1655: default: ! 1656: #if MACH_ASSERT ! 1657: assert(!"convert_port_type: strange port type"); ! 1658: #else ! 1659: panic("convert_port_type: strange port type"); ! 1660: #endif ! 1661: } ! 1662: } ! 1663: ! 1664: /* ! 1665: * Routine: port_names [kernel call] ! 1666: * Purpose: ! 1667: * Retrieve all the names in the task's port name space. ! 1668: * As a (major) convenience, return port type information. ! 1669: * The port name space includes port sets. ! 1670: * Conditions: ! 1671: * Nothing locked. ! 1672: * Returns: ! 1673: * KERN_SUCCESS Retrieved names. ! 1674: * KERN_INVALID_ARGUMENT Task is null. ! 1675: * KERN_INVALID_ARGUMENT Task is not active. ! 1676: * Additions: ! 1677: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 1678: */ ! 1679: ! 1680: kern_return_t ! 1681: port_names(space, namesp, namesCnt, typesp, typesCnt) ! 1682: ipc_space_t space; ! 1683: mach_port_t **namesp; ! 1684: mach_msg_type_number_t *namesCnt; ! 1685: mach_port_type_t **typesp; ! 1686: mach_msg_type_number_t *typesCnt; ! 1687: { ! 1688: kern_return_t kr; ! 1689: ! 1690: kr = mach_port_names(space, namesp, namesCnt, typesp, typesCnt); ! 1691: if (kr == KERN_SUCCESS) { ! 1692: ipc_entry_num_t actual = (ipc_entry_num_t) *typesCnt; ! 1693: mach_port_type_t *types; ! 1694: ipc_entry_num_t i; ! 1695: ! 1696: vm_map_copy_t copy = (vm_map_copy_t) *typesp; ! 1697: vm_offset_t addr; ! 1698: vm_size_t size = round_page(actual * sizeof(mach_port_type_t)); ! 1699: ! 1700: /* convert copy object back to something we can use */ ! 1701: ! 1702: kr = vm_map_copyout(ipc_kernel_map, &addr, copy); ! 1703: if (kr != KERN_SUCCESS) { ! 1704: vm_map_copy_discard((vm_map_copy_t) *typesp); ! 1705: vm_map_copy_discard((vm_map_copy_t) *namesp); ! 1706: return KERN_RESOURCE_SHORTAGE; ! 1707: } ! 1708: ! 1709: types = (mach_port_type_t *) addr; ! 1710: ! 1711: for (i = 0; i < actual; i++) ! 1712: types[i] = convert_port_type(types[i]); ! 1713: ! 1714: /* convert memory back into a copy object */ ! 1715: ! 1716: kr = vm_map_copyin(ipc_kernel_map, addr, size, ! 1717: TRUE, ©); ! 1718: assert(kr == KERN_SUCCESS); ! 1719: ! 1720: *typesp = (mach_port_type_t *) copy; ! 1721: } else if (kr != KERN_RESOURCE_SHORTAGE) ! 1722: kr = KERN_INVALID_ARGUMENT; ! 1723: ! 1724: return kr; ! 1725: } ! 1726: ! 1727: /* ! 1728: * Routine: port_type [kernel call] ! 1729: * Purpose: ! 1730: * Return type of the capability named. ! 1731: * Conditions: ! 1732: * Nothing locked. ! 1733: * Returns: ! 1734: * KERN_SUCCESS Retrieved type. ! 1735: * KERN_INVALID_ARGUMENT Task is null. ! 1736: * KERN_INVALID_ARGUMENT Task is not active. ! 1737: * KERN_INVALID_ARGUMENT The name doesn't denote a right. ! 1738: */ ! 1739: ! 1740: kern_return_t ! 1741: port_type(space, name, typep) ! 1742: ipc_space_t space; ! 1743: mach_port_t name; ! 1744: mach_port_type_t *typep; ! 1745: { ! 1746: mach_port_type_t type; ! 1747: kern_return_t kr; ! 1748: ! 1749: kr = mach_port_type(space, name, &type); ! 1750: if (kr != KERN_SUCCESS) ! 1751: return KERN_INVALID_ARGUMENT; ! 1752: ! 1753: *typep = convert_port_type(type); ! 1754: return KERN_SUCCESS; ! 1755: } ! 1756: ! 1757: /* ! 1758: * Routine: port_rename [kernel call] ! 1759: * Purpose: ! 1760: * Change the name of a capability. ! 1761: * The new name can't be in use. ! 1762: * Conditions: ! 1763: * Nothing locked. ! 1764: * Returns: ! 1765: * KERN_SUCCESS Retrieved type. ! 1766: * KERN_INVALID_ARGUMENT Task is null. ! 1767: * KERN_INVALID_ARGUMENT Task is not active. ! 1768: * KERN_INVALID_ARGUMENT The new name is reserved. ! 1769: * KERN_NAME_EXISTS The new name already denotes a right. ! 1770: * KERN_INVALID_ARGUMENT The old name doesn't denote a right. ! 1771: */ ! 1772: ! 1773: kern_return_t ! 1774: port_rename(space, old_name, new_name) ! 1775: ipc_space_t space; ! 1776: mach_port_t old_name; ! 1777: mach_port_t new_name; ! 1778: { ! 1779: kern_return_t kr; ! 1780: ! 1781: kr = mach_port_rename(space, old_name, new_name); ! 1782: if ((kr != KERN_SUCCESS) && (kr != KERN_NAME_EXISTS)) ! 1783: kr = KERN_INVALID_ARGUMENT; ! 1784: ! 1785: return kr; ! 1786: } ! 1787: ! 1788: /* ! 1789: * Routine: port_allocate [kernel call] ! 1790: * Purpose: ! 1791: * Allocate a new port, giving all rights to "task". ! 1792: * ! 1793: * Returns in "port_name" the task's local name for the port. ! 1794: * Doesn't return a reference to the port. ! 1795: * Conditions: ! 1796: * Nothing locked. ! 1797: * Returns: ! 1798: * KERN_SUCCESS Allocated a port. ! 1799: * KERN_INVALID_ARGUMENT Task is null. ! 1800: * KERN_INVALID_ARGUMENT Task is not active. ! 1801: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 1802: */ ! 1803: ! 1804: kern_return_t ! 1805: port_allocate(space, namep) ! 1806: ipc_space_t space; ! 1807: mach_port_t *namep; ! 1808: { ! 1809: ipc_port_t port; ! 1810: kern_return_t kr; ! 1811: ! 1812: if (space == IS_NULL) ! 1813: return KERN_INVALID_ARGUMENT; ! 1814: ! 1815: kr = ipc_port_alloc_compat(space, namep, &port); ! 1816: if (kr == KERN_SUCCESS) ! 1817: ip_unlock(port); ! 1818: else if (kr != KERN_RESOURCE_SHORTAGE) ! 1819: kr = KERN_INVALID_ARGUMENT; ! 1820: ! 1821: return kr; ! 1822: } ! 1823: ! 1824: /* ! 1825: * Routine: port_deallocate [kernel call] ! 1826: * Purpose: ! 1827: * Delete port rights (send and receive) from a task. ! 1828: * Conditions: ! 1829: * Nothing locked. ! 1830: * Returns: ! 1831: * KERN_SUCCESS Deallocated the port right. ! 1832: * KERN_INVALID_ARGUMENT Task is null. ! 1833: * KERN_INVALID_ARGUMENT Task is not active. ! 1834: * KERN_INVALID_ARGUMENT Name doesn't denote a port right. ! 1835: * Additions: ! 1836: * KERN_SUCCESS Deallocated a send-once right. ! 1837: * KERN_SUCCESS Destroyed a dead name. ! 1838: */ ! 1839: ! 1840: kern_return_t ! 1841: port_deallocate(space, name) ! 1842: ipc_space_t space; ! 1843: mach_port_t name; ! 1844: { ! 1845: ipc_entry_t entry; ! 1846: mach_port_type_t type; ! 1847: mach_port_urefs_t urefs; ! 1848: kern_return_t kr; ! 1849: ! 1850: if (space == IS_NULL) ! 1851: return KERN_INVALID_ARGUMENT; ! 1852: ! 1853: kr = ipc_right_lookup_write(space, name, &entry); ! 1854: if (kr != KERN_SUCCESS) ! 1855: return KERN_INVALID_ARGUMENT; ! 1856: /* space is write-locked and active */ ! 1857: ! 1858: /* ! 1859: * We serialize with port destruction with the ! 1860: * ipc_right_info call, not ipc_right_destroy. ! 1861: * After ipc_right_info, we pretend that the ! 1862: * port doesn't get destroyed. ! 1863: */ ! 1864: ! 1865: kr = ipc_right_info(space, name, entry, &type, &urefs); ! 1866: if (kr != KERN_SUCCESS) ! 1867: return KERN_INVALID_ARGUMENT; /* space is unlocked */ ! 1868: ! 1869: if ((type & (MACH_PORT_TYPE_PORT_OR_DEAD)) == 0) { ! 1870: is_write_unlock(space); ! 1871: return KERN_INVALID_ARGUMENT; ! 1872: } ! 1873: ! 1874: (void) ipc_right_destroy(space, name, entry); ! 1875: /* space is unlocked */ ! 1876: ! 1877: return KERN_SUCCESS; ! 1878: } ! 1879: ! 1880: /* ! 1881: * Routine: port_set_backlog [kernel call] ! 1882: * Purpose: ! 1883: * Change the queueing backlog on "port_name" to "backlog"; ! 1884: * the specified "task" must be the current receiver. ! 1885: * ! 1886: * Valid backlog values are 0 < backlog <= PORT_BACKLOG_MAX. ! 1887: * Conditions: ! 1888: * Nothing locked. ! 1889: * Returns: ! 1890: * KERN_SUCCESS Set the backlog. ! 1891: * KERN_INVALID_ARGUMENT Task is null. ! 1892: * KERN_INVALID_ARGUMENT Task is not active. ! 1893: * KERN_INVALID_ARGUMENT Name doesn't denote a port right. ! 1894: * KERN_NOT_RECEIVER Name denotes send rights, not receive. ! 1895: * KERN_INVALID_ARGUMENT Backlog value is invalid. ! 1896: * Additions: ! 1897: * KERN_NOT_RECEIVER Name denotes a send-once right. ! 1898: * KERN_NOT_RECEIVER Name denotes a dead name. ! 1899: */ ! 1900: ! 1901: kern_return_t ! 1902: port_set_backlog(space, name, backlog) ! 1903: ipc_space_t space; ! 1904: mach_port_t name; ! 1905: int backlog; ! 1906: { ! 1907: ipc_port_t port; ! 1908: kern_return_t kr; ! 1909: ! 1910: if ((space == IS_NULL) || ! 1911: (backlog <= 0) || ! 1912: (backlog > PORT_BACKLOG_MAX)) ! 1913: return KERN_INVALID_ARGUMENT; ! 1914: ! 1915: kr = port_translate_compat(space, name, &port); ! 1916: if (kr != KERN_SUCCESS) ! 1917: return kr; ! 1918: /* port is locked and active */ ! 1919: ! 1920: ipc_port_set_qlimit(port, (mach_port_msgcount_t) backlog); ! 1921: ! 1922: ip_unlock(port); ! 1923: return KERN_SUCCESS; ! 1924: } ! 1925: ! 1926: /* ! 1927: * Routine: port_set_backup [kernel call] ! 1928: * Purpose: ! 1929: * Changes the backup port for the the named port. ! 1930: * The specified "task" must be the current receiver. ! 1931: * Returns the old backup port, if any. ! 1932: * Conditions: ! 1933: * Nothing locked. ! 1934: * Returns: ! 1935: * KERN_SUCCESS Set the backup. ! 1936: * KERN_INVALID_ARGUMENT Task is null. ! 1937: * KERN_INVALID_ARGUMENT Task is not active. ! 1938: * KERN_INVALID_ARGUMENT Name doesn't denote a port right. ! 1939: * KERN_NOT_RECEIVER Name denotes send rights, not receive. ! 1940: * Additions: ! 1941: * KERN_NOT_RECEIVER Name denotes a send-once right. ! 1942: * KERN_NOT_RECEIVER Name denotes a dead name. ! 1943: */ ! 1944: ! 1945: kern_return_t ! 1946: port_set_backup(space, name, backup, previousp) ! 1947: ipc_space_t space; ! 1948: mach_port_t name; ! 1949: ipc_port_t backup; ! 1950: ipc_port_t *previousp; ! 1951: { ! 1952: ipc_port_t port, previous; ! 1953: kern_return_t kr; ! 1954: ! 1955: if (space == IS_NULL) ! 1956: return KERN_INVALID_ARGUMENT; ! 1957: ! 1958: if (backup == IP_DEAD) ! 1959: backup = IP_NULL; ! 1960: else if (backup != IP_NULL) ! 1961: backup = ip_pdsendm(backup); ! 1962: ! 1963: kr = port_translate_compat(space, name, &port); ! 1964: if (kr != KERN_SUCCESS) ! 1965: return kr; ! 1966: /* port is locked and active */ ! 1967: ! 1968: ipc_port_pdrequest(port, backup, &previous); ! 1969: /* port is unlocked */ ! 1970: ! 1971: /* ! 1972: * If previous was a send-once right instead of a send ! 1973: * right, we can't return it in the reply message. ! 1974: * So get rid of it in a notification instead. ! 1975: */ ! 1976: ! 1977: if (previous != IP_NULL) { ! 1978: if (ip_pdsendp(previous)) ! 1979: previous = ip_pdsend(previous); ! 1980: else { ! 1981: ipc_notify_send_once(previous); ! 1982: previous = IP_NULL; ! 1983: } ! 1984: } ! 1985: ! 1986: *previousp = previous; ! 1987: return KERN_SUCCESS; ! 1988: } ! 1989: ! 1990: /* ! 1991: * Routine: port_status [kernel call] ! 1992: * Purpose: ! 1993: * Returns statistics related to "port_name", as seen by "task". ! 1994: * Only the receiver for a given port will see true message ! 1995: * counts. ! 1996: * Conditions: ! 1997: * Nothing locked. ! 1998: * Returns: ! 1999: * KERN_SUCCESS Retrieved status. ! 2000: * KERN_INVALID_ARGUMENT Task is null. ! 2001: * KERN_INVALID_ARGUMENT Task is not active. ! 2002: * KERN_INVALID_ARGUMENT Name doesn't denote a port right. ! 2003: * Additions: ! 2004: * KERN_SUCCESS Send-once right. ! 2005: * KERN_SUCCESS Dead name. ! 2006: */ ! 2007: ! 2008: kern_return_t ! 2009: port_status(space, name, enabledp, num_msgs, backlog, ! 2010: ownership, receive_rights) ! 2011: ipc_space_t space; ! 2012: mach_port_t name; ! 2013: mach_port_t *enabledp; ! 2014: int *num_msgs; ! 2015: int *backlog; ! 2016: boolean_t *ownership; ! 2017: boolean_t *receive_rights; ! 2018: { ! 2019: ipc_entry_t entry; ! 2020: mach_port_type_t type; ! 2021: mach_port_urefs_t urefs; ! 2022: kern_return_t kr; ! 2023: ! 2024: if (space == IS_NULL) ! 2025: return KERN_INVALID_ARGUMENT; ! 2026: ! 2027: kr = ipc_right_lookup_write(space, name, &entry); ! 2028: if (kr != KERN_SUCCESS) ! 2029: return KERN_INVALID_ARGUMENT; ! 2030: /* space is write-locked and active */ ! 2031: ! 2032: kr = ipc_right_info(space, name, entry, &type, &urefs); ! 2033: if (kr != KERN_SUCCESS) ! 2034: return KERN_INVALID_ARGUMENT; /* space is unlocked */ ! 2035: ! 2036: if ((type & MACH_PORT_TYPE_PORT_OR_DEAD) == 0) { ! 2037: is_write_unlock(space); ! 2038: return KERN_INVALID_ARGUMENT; ! 2039: } ! 2040: ! 2041: if (type & MACH_PORT_TYPE_RECEIVE) { ! 2042: mach_port_t enabled; ! 2043: mach_port_msgcount_t qlimit; ! 2044: mach_port_msgcount_t msgcount; ! 2045: ipc_port_t port; ! 2046: ! 2047: port = (ipc_port_t) entry->ie_object; ! 2048: assert(port != IP_NULL); ! 2049: ! 2050: ip_lock(port); ! 2051: is_write_unlock(space); ! 2052: assert(ip_active(port)); ! 2053: ! 2054: if (port->ip_pset != IPS_NULL) { ! 2055: ipc_pset_t pset = port->ip_pset; ! 2056: ! 2057: ips_lock(pset); ! 2058: if (!ips_active(pset)) { ! 2059: ipc_pset_remove(pset, port); ! 2060: ips_check_unlock(pset); ! 2061: enabled = MACH_PORT_NULL; ! 2062: } else { ! 2063: enabled = pset->ips_local_name; ! 2064: ips_unlock(pset); ! 2065: assert(MACH_PORT_VALID(enabled)); ! 2066: } ! 2067: } else ! 2068: enabled = MACH_PORT_NULL; ! 2069: ! 2070: qlimit = port->ip_qlimit; ! 2071: msgcount = port->ip_msgcount; ! 2072: ip_unlock(port); ! 2073: ! 2074: *ownership = TRUE; ! 2075: *receive_rights = TRUE; ! 2076: *enabledp = enabled; ! 2077: *num_msgs = (int) msgcount; ! 2078: *backlog = (int) qlimit; ! 2079: } else { ! 2080: is_write_unlock(space); ! 2081: ! 2082: *ownership = FALSE; ! 2083: *receive_rights = FALSE; ! 2084: *enabledp = MACH_PORT_NULL; ! 2085: *num_msgs = -1; ! 2086: *backlog = 0; ! 2087: } ! 2088: ! 2089: return KERN_SUCCESS; ! 2090: } ! 2091: ! 2092: /* ! 2093: * Routine: port_set_allocate [kernel call] ! 2094: * Purpose: ! 2095: * Create a new port set, give rights to task, and ! 2096: * return task's local name for the set. ! 2097: * Conditions: ! 2098: * Nothing locked. ! 2099: * Returns: ! 2100: * KERN_SUCCESS Allocated a port set. ! 2101: * KERN_INVALID_ARGUMENT Task is null. ! 2102: * KERN_INVALID_ARGUMENT Task is not active. ! 2103: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 2104: */ ! 2105: ! 2106: kern_return_t ! 2107: port_set_allocate(space, namep) ! 2108: ipc_space_t space; ! 2109: mach_port_t *namep; ! 2110: { ! 2111: ipc_pset_t pset; ! 2112: kern_return_t kr; ! 2113: ! 2114: if (space == IS_NULL) ! 2115: return KERN_INVALID_ARGUMENT; ! 2116: ! 2117: kr = ipc_pset_alloc(space, namep, &pset); ! 2118: if (kr == KERN_SUCCESS) ! 2119: ips_unlock(pset); ! 2120: else if (kr != KERN_RESOURCE_SHORTAGE) ! 2121: kr = KERN_INVALID_ARGUMENT; ! 2122: ! 2123: return kr; ! 2124: } ! 2125: ! 2126: /* ! 2127: * Routine: port_set_deallocate [kernel call] ! 2128: * Purpose: ! 2129: * Destroys the task's port set. If there are any ! 2130: * receive rights in the set, they are removed. ! 2131: * Conditions: ! 2132: * Nothing locked. ! 2133: * Returns: ! 2134: * KERN_SUCCESS Deallocated the port set. ! 2135: * KERN_INVALID_ARGUMENT Task is null. ! 2136: * KERN_INVALID_ARGUMENT Task is not active. ! 2137: * KERN_INVALID_ARGUMENT Name doesn't denote a port set. ! 2138: */ ! 2139: ! 2140: kern_return_t ! 2141: port_set_deallocate(space, name) ! 2142: ipc_space_t space; ! 2143: mach_port_t name; ! 2144: { ! 2145: ipc_entry_t entry; ! 2146: kern_return_t kr; ! 2147: ! 2148: if (space == IS_NULL) ! 2149: return KERN_INVALID_ARGUMENT; ! 2150: ! 2151: kr = ipc_right_lookup_write(space, name, &entry); ! 2152: if (kr != KERN_SUCCESS) ! 2153: return kr; ! 2154: /* space is write-locked and active */ ! 2155: ! 2156: if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) { ! 2157: is_write_unlock(space); ! 2158: return KERN_INVALID_ARGUMENT; ! 2159: } ! 2160: ! 2161: kr = ipc_right_destroy(space, name, entry); ! 2162: /* space is unlocked */ ! 2163: assert(kr == KERN_SUCCESS); ! 2164: return kr; ! 2165: } ! 2166: ! 2167: /* ! 2168: * Routine: port_set_add [kernel call] ! 2169: * Purpose: ! 2170: * Moves receive rights into the port set. ! 2171: * Conditions: ! 2172: * Nothing locked. ! 2173: * Returns: ! 2174: * KERN_SUCCESS Moved the receive right. ! 2175: * KERN_INVALID_ARGUMENT Task is null. ! 2176: * KERN_INVALID_ARGUMENT Task is not active. ! 2177: * KERN_INVALID_ARGUMENT port_name doesn't denote port rights. ! 2178: * KERN_NOT_RECEIVER port_name doesn't denote receive right. ! 2179: * KERN_INVALID_ARGUMENT set_name doesn't denote a port set. ! 2180: * Additions: ! 2181: * KERN_NOT_RECEIVER port_name denotes a send-once right. ! 2182: * KERN_NOT_RECEIVER port_name denotes a dead name. ! 2183: */ ! 2184: ! 2185: kern_return_t ! 2186: port_set_add(space, set_name, port_name) ! 2187: ipc_space_t space; ! 2188: mach_port_t set_name; ! 2189: mach_port_t port_name; ! 2190: { ! 2191: ipc_entry_t entry; ! 2192: mach_port_type_t type; ! 2193: mach_port_urefs_t urefs; ! 2194: ipc_port_t port; ! 2195: ipc_pset_t pset; ! 2196: kern_return_t kr; ! 2197: ! 2198: if (space == IS_NULL) ! 2199: return KERN_INVALID_ARGUMENT; ! 2200: ! 2201: kr = ipc_right_lookup_write(space, port_name, &entry); ! 2202: if (kr != KERN_SUCCESS) ! 2203: return KERN_INVALID_ARGUMENT; ! 2204: /* space is write-locked and active */ ! 2205: ! 2206: /* use ipc_right_info to check for dead compat entries */ ! 2207: ! 2208: kr = ipc_right_info(space, port_name, entry, &type, &urefs); ! 2209: if (kr != KERN_SUCCESS) ! 2210: return KERN_INVALID_ARGUMENT; /* space is unlocked */ ! 2211: ! 2212: if ((type & MACH_PORT_TYPE_RECEIVE) == 0) { ! 2213: is_write_unlock(space); ! 2214: if (type & MACH_PORT_TYPE_PORT_OR_DEAD) ! 2215: return KERN_NOT_RECEIVER; ! 2216: else ! 2217: return KERN_INVALID_ARGUMENT; ! 2218: } ! 2219: ! 2220: is_write_to_read_lock(space); ! 2221: port = (ipc_port_t) entry->ie_object; ! 2222: assert(port != IP_NULL); ! 2223: ! 2224: entry = ipc_entry_lookup(space, set_name); ! 2225: if ((entry == IE_NULL) || ! 2226: ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0)) { ! 2227: is_read_unlock(space); ! 2228: return KERN_INVALID_ARGUMENT; ! 2229: } ! 2230: ! 2231: pset = (ipc_pset_t) entry->ie_object; ! 2232: assert(pset != IPS_NULL); ! 2233: ! 2234: kr = ipc_pset_move(space, port, pset); ! 2235: /* space is unlocked */ ! 2236: assert(kr == KERN_SUCCESS); ! 2237: return kr; ! 2238: } ! 2239: ! 2240: /* ! 2241: * Routine: port_set_remove [kernel call] ! 2242: * Purpose: ! 2243: * Removes the receive rights from the set they are in. ! 2244: * Conditions: ! 2245: * Nothing locked. ! 2246: * Returns: ! 2247: * KERN_SUCCESS Removed the receive right. ! 2248: * KERN_INVALID_ARGUMENT Task is null. ! 2249: * KERN_INVALID_ARGUMENT Task is not active. ! 2250: * KERN_INVALID_ARGUMENT Name doesn't denote a port right. ! 2251: * KERN_NOT_RECEIVER Name denotes send rights, not receive. ! 2252: * KERN_NOT_IN_SET Port isn't in a port set. ! 2253: * Additions: ! 2254: * KERN_NOT_RECEIVER Name denotes a send-once right. ! 2255: * KERN_NOT_RECEIVER Name denotes a dead name. ! 2256: */ ! 2257: ! 2258: kern_return_t ! 2259: port_set_remove(space, name) ! 2260: ipc_space_t space; ! 2261: mach_port_t name; ! 2262: { ! 2263: ipc_entry_t entry; ! 2264: mach_port_type_t type; ! 2265: mach_port_urefs_t urefs; ! 2266: ipc_port_t port; ! 2267: kern_return_t kr; ! 2268: ! 2269: if (space == IS_NULL) ! 2270: return KERN_INVALID_ARGUMENT; ! 2271: ! 2272: kr = ipc_right_lookup_write(space, name, &entry); ! 2273: if (kr != KERN_SUCCESS) ! 2274: return KERN_INVALID_ARGUMENT; ! 2275: /* space is write-locked and active */ ! 2276: ! 2277: /* use ipc_right_info to check for dead compat entries */ ! 2278: ! 2279: kr = ipc_right_info(space, name, entry, &type, &urefs); ! 2280: if (kr != KERN_SUCCESS) ! 2281: return KERN_INVALID_ARGUMENT; /* space is unlocked */ ! 2282: ! 2283: if ((type & (MACH_PORT_TYPE_RECEIVE)) == 0) { ! 2284: is_write_unlock(space); ! 2285: if (type & MACH_PORT_TYPE_PORT_OR_DEAD) ! 2286: return KERN_NOT_RECEIVER; ! 2287: else ! 2288: return KERN_INVALID_ARGUMENT; ! 2289: } ! 2290: ! 2291: is_write_to_read_lock(space); ! 2292: port = (ipc_port_t) entry->ie_object; ! 2293: assert(port != IP_NULL); ! 2294: ! 2295: kr = ipc_pset_move(space, port, IPS_NULL); ! 2296: /* space is unlocked */ ! 2297: return kr; ! 2298: } ! 2299: ! 2300: /* ! 2301: * Routine: port_set_status [kernel call] ! 2302: * Purpose: ! 2303: * Retrieve list of members of a port set. ! 2304: * Conditions: ! 2305: * Nothing locked. ! 2306: * Returns: ! 2307: * KERN_SUCCESS Retrieved port set status. ! 2308: * KERN_INVALID_ARGUMENT Task is null. ! 2309: * KERN_INVALID_ARGUMENT Task is not active. ! 2310: * KERN_INVALID_ARGUMENT Name doesn't denote a port set. ! 2311: * Additions: ! 2312: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 2313: */ ! 2314: ! 2315: kern_return_t ! 2316: port_set_status(space, name, members, membersCnt) ! 2317: ipc_space_t space; ! 2318: mach_port_t name; ! 2319: mach_port_t **members; ! 2320: mach_msg_type_number_t *membersCnt; ! 2321: { ! 2322: kern_return_t kr; ! 2323: ! 2324: kr = mach_port_get_set_status(space, name, members, membersCnt); ! 2325: if ((kr != KERN_SUCCESS) && (kr != KERN_RESOURCE_SHORTAGE)) ! 2326: kr = KERN_INVALID_ARGUMENT; ! 2327: ! 2328: return kr; ! 2329: } ! 2330: ! 2331: /* ! 2332: * Routine: port_insert_send [kernel call] ! 2333: * Purpose: ! 2334: * Inserts send rights to a port into a task, ! 2335: * at a given name. The name must not be in use. ! 2336: * Conditions: ! 2337: * Nothing locked. ! 2338: * Returns: ! 2339: * KERN_SUCCESS Inserted send right. ! 2340: * KERN_INVALID_ARGUMENT Task is null. ! 2341: * KERN_INVALID_ARGUMENT Task is not active. ! 2342: * KERN_INVALID_ARGUMENT Port is null or dead. ! 2343: * KERN_INVALID_ARGUMENT Name is reserved. ! 2344: * KERN_NAME_EXISTS Name already denotes a right. ! 2345: * KERN_FAILURE Task already has rights for the port. ! 2346: * Additions: ! 2347: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 2348: */ ! 2349: ! 2350: kern_return_t ! 2351: port_insert_send(space, port, name) ! 2352: ipc_space_t space; ! 2353: ipc_port_t port; ! 2354: mach_port_t name; ! 2355: { ! 2356: kern_return_t kr; ! 2357: ! 2358: if ((space == IS_NULL) || ! 2359: !MACH_PORT_VALID(name) || ! 2360: !IP_VALID(port)) ! 2361: return KERN_INVALID_ARGUMENT; ! 2362: ! 2363: kr = ipc_object_copyout_name_compat(space, (ipc_object_t) port, ! 2364: MACH_MSG_TYPE_PORT_SEND, name); ! 2365: switch (kr) { ! 2366: case KERN_SUCCESS: ! 2367: case KERN_NAME_EXISTS: ! 2368: case KERN_RESOURCE_SHORTAGE: ! 2369: break; ! 2370: ! 2371: case KERN_RIGHT_EXISTS: ! 2372: kr = KERN_FAILURE; ! 2373: break; ! 2374: ! 2375: default: ! 2376: kr = KERN_INVALID_ARGUMENT; ! 2377: break; ! 2378: } ! 2379: ! 2380: return kr; ! 2381: } ! 2382: ! 2383: /* ! 2384: * Routine: port_extract_send [kernel call] ! 2385: * Purpose: ! 2386: * Extracts send rights from "task"'s "his_name" port. ! 2387: * The task is left with no rights for the port. ! 2388: * Conditions: ! 2389: * Nothing locked. ! 2390: * Returns: ! 2391: * KERN_SUCCESS Extracted send right. ! 2392: * KERN_INVALID_ARGUMENT Task is null. ! 2393: * KERN_INVALID_ARGUMENT Task is not active. ! 2394: * KERN_INVALID_ARGUMENT Name doesn't denote pure send rights. ! 2395: */ ! 2396: ! 2397: kern_return_t ! 2398: port_extract_send(space, name, portp) ! 2399: ipc_space_t space; ! 2400: mach_port_t name; ! 2401: ipc_port_t *portp; ! 2402: { ! 2403: kern_return_t kr; ! 2404: ! 2405: if (space == IS_NULL) ! 2406: return KERN_INVALID_ARGUMENT; ! 2407: ! 2408: kr = ipc_object_copyin_compat(space, name, ! 2409: MSG_TYPE_PORT, TRUE, ! 2410: (ipc_object_t *) portp); ! 2411: if (kr != KERN_SUCCESS) ! 2412: kr = KERN_INVALID_ARGUMENT; ! 2413: ! 2414: return kr; ! 2415: } ! 2416: ! 2417: /* ! 2418: * Routine: port_insert_receive [kernel call] ! 2419: * Purpose: ! 2420: * Inserts receive/ownership rights to a port into a task, ! 2421: * at a given name. ! 2422: * Conditions: ! 2423: * Nothing locked. ! 2424: * Returns: ! 2425: * KERN_SUCCESS Inserted receive right. ! 2426: * KERN_INVALID_ARGUMENT Task is null. ! 2427: * KERN_INVALID_ARGUMENT Task is not active. ! 2428: * KERN_INVALID_ARGUMENT Port is null. (Can't be dead.) ! 2429: * KERN_INVALID_ARGUMENT Name is reserved. ! 2430: * KERN_NAME_EXISTS Name already denotes a right. ! 2431: * KERN_FAILURE Task already has rights for the port. ! 2432: * Additions: ! 2433: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 2434: */ ! 2435: ! 2436: kern_return_t ! 2437: port_insert_receive(space, port, name) ! 2438: ipc_space_t space; ! 2439: ipc_port_t port; ! 2440: mach_port_t name; ! 2441: { ! 2442: kern_return_t kr; ! 2443: ! 2444: if ((space == IS_NULL) || ! 2445: !MACH_PORT_VALID(name) || ! 2446: !IP_VALID(port)) ! 2447: return KERN_INVALID_ARGUMENT; ! 2448: ! 2449: kr = ipc_object_copyout_name_compat(space, (ipc_object_t) port, ! 2450: MACH_MSG_TYPE_PORT_RECEIVE, name); ! 2451: switch (kr) { ! 2452: case KERN_SUCCESS: ! 2453: case KERN_NAME_EXISTS: ! 2454: case KERN_RESOURCE_SHORTAGE: ! 2455: break; ! 2456: ! 2457: case KERN_RIGHT_EXISTS: ! 2458: kr = KERN_FAILURE; ! 2459: break; ! 2460: ! 2461: default: ! 2462: kr = KERN_INVALID_ARGUMENT; ! 2463: break; ! 2464: } ! 2465: ! 2466: return kr; ! 2467: } ! 2468: ! 2469: /* ! 2470: * Routine: port_extract_receive [kernel call] ! 2471: * Purpose: ! 2472: * Extracts receive/ownership rights ! 2473: * from "task"'s "his_name" port. ! 2474: * ! 2475: * The task is left with no rights for the port. ! 2476: * Conditions: ! 2477: * Nothing locked. ! 2478: * Returns: ! 2479: * KERN_SUCCESS Extracted receive right. ! 2480: * KERN_INVALID_ARGUMENT Task is null. ! 2481: * KERN_INVALID_ARGUMENT Task is not active. ! 2482: * KERN_INVALID_ARGUMENT Name doesn't denote receive rights. ! 2483: */ ! 2484: ! 2485: kern_return_t ! 2486: port_extract_receive(space, name, portp) ! 2487: ipc_space_t space; ! 2488: mach_port_t name; ! 2489: ipc_port_t *portp; ! 2490: { ! 2491: kern_return_t kr; ! 2492: ! 2493: if (space == IS_NULL) ! 2494: return KERN_INVALID_ARGUMENT; ! 2495: ! 2496: kr = ipc_object_copyin_compat(space, name, ! 2497: MSG_TYPE_PORT_ALL, TRUE, ! 2498: (ipc_object_t *) portp); ! 2499: if (kr != KERN_SUCCESS) ! 2500: kr = KERN_INVALID_ARGUMENT; ! 2501: ! 2502: return kr; ! 2503: } ! 2504: ! 2505: #endif MACH_IPC_COMPAT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.