|
|
1.1.1.2 ! root 1: /* 1.1 root 2: * Mach Operating System 3: * Copyright (c) 1991,1990 Carnegie Mellon University 4: * All Rights Reserved. 1.1.1.2 ! root 5: * 1.1 root 6: * Permission to use, copy, modify and distribute this software and its 7: * documentation is hereby granted, provided that both the copyright 8: * notice and this permission notice appear in all copies of the 9: * software, derivative works or modified versions, and any portions 10: * thereof, and that both notices appear in supporting documentation. 1.1.1.2 ! root 11: * 1.1 root 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 1.1.1.2 ! root 15: * 1.1 root 16: * Carnegie Mellon requests users of this software to return to 1.1.1.2 ! root 17: * 1.1 root 18: * Software Distribution Coordinator or [email protected] 19: * School of Computer Science 20: * Carnegie Mellon University 21: * Pittsburgh PA 15213-3890 1.1.1.2 ! root 22: * 1.1 root 23: * any improvements or extensions that they make and grant Carnegie Mellon 24: * the rights to redistribute these changes. 25: */ 26: /* 27: */ 28: /* 29: * File: ipc/mach_debug.c 30: * Author: Rich Draves 31: * Date: 1989 32: * 33: * Exported kernel calls. See mach_debug/mach_debug.defs. 34: */ 35: 36: #include <mach_ipc_compat.h> 37: 38: #include <mach/kern_return.h> 39: #include <mach/port.h> 40: #include <mach/machine/vm_types.h> 41: #include <mach/vm_param.h> 42: #include <mach_debug/ipc_info.h> 43: #include <mach_debug/hash_info.h> 44: #include <kern/host.h> 45: #include <vm/vm_map.h> 46: #include <vm/vm_kern.h> 47: #include <ipc/ipc_space.h> 48: #include <ipc/ipc_port.h> 49: #include <ipc/ipc_hash.h> 50: #include <ipc/ipc_marequest.h> 51: #include <ipc/ipc_table.h> 52: #include <ipc/ipc_right.h> 53: 54: 55: 56: /* 57: * Routine: mach_port_get_srights [kernel call] 58: * Purpose: 59: * Retrieve the number of extant send rights 60: * that a receive right has. 61: * Conditions: 62: * Nothing locked. 63: * Returns: 64: * KERN_SUCCESS Retrieved number of send rights. 65: * KERN_INVALID_TASK The space is null. 66: * KERN_INVALID_TASK The space is dead. 67: * KERN_INVALID_NAME The name doesn't denote a right. 68: * KERN_INVALID_RIGHT Name doesn't denote receive rights. 69: */ 70: 71: kern_return_t 72: mach_port_get_srights( 73: ipc_space_t space, 74: mach_port_t name, 75: mach_port_rights_t *srightsp) 76: { 77: ipc_port_t port; 78: kern_return_t kr; 79: mach_port_rights_t srights; 80: 81: if (space == IS_NULL) 82: return KERN_INVALID_TASK; 83: 84: kr = ipc_port_translate_receive(space, name, &port); 85: if (kr != KERN_SUCCESS) 86: return kr; 87: /* port is locked and active */ 88: 89: srights = port->ip_srights; 90: ip_unlock(port); 91: 92: *srightsp = srights; 93: return KERN_SUCCESS; 94: } 95: 96: /* 97: * Routine: host_ipc_hash_info 98: * Purpose: 99: * Return information about the global reverse hash table. 100: * Conditions: 101: * Nothing locked. Obeys CountInOut protocol. 102: * Returns: 103: * KERN_SUCCESS Returned information. 104: * KERN_INVALID_HOST The host is null. 105: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 106: */ 107: 108: kern_return_t 109: host_ipc_hash_info( 110: host_t host, 111: hash_info_bucket_array_t *infop, 112: mach_msg_type_number_t *countp) 113: { 114: vm_offset_t addr; 115: vm_size_t size; 116: hash_info_bucket_t *info; 117: unsigned int potential, actual; 118: kern_return_t kr; 119: 120: if (host == HOST_NULL) 121: return KERN_INVALID_HOST; 122: 123: /* start with in-line data */ 124: 125: info = *infop; 126: potential = *countp; 127: 128: for (;;) { 129: actual = ipc_hash_info(info, potential); 130: if (actual <= potential) 131: break; 132: 133: /* allocate more memory */ 134: 135: if (info != *infop) 136: kmem_free(ipc_kernel_map, addr, size); 137: 138: size = round_page(actual * sizeof *info); 139: kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size); 140: if (kr != KERN_SUCCESS) 141: return KERN_RESOURCE_SHORTAGE; 142: 143: info = (hash_info_bucket_t *) addr; 144: potential = size/sizeof *info; 145: } 146: 147: if (info == *infop) { 148: /* data fit in-line; nothing to deallocate */ 149: 150: *countp = actual; 151: } else if (actual == 0) { 152: kmem_free(ipc_kernel_map, addr, size); 153: 154: *countp = 0; 155: } else { 156: vm_map_copy_t copy; 157: vm_size_t used; 158: 159: used = round_page(actual * sizeof *info); 160: 161: if (used != size) 162: kmem_free(ipc_kernel_map, addr + used, size - used); 163: 164: kr = vm_map_copyin(ipc_kernel_map, addr, used, 165: TRUE, ©); 166: assert(kr == KERN_SUCCESS); 167: 168: *infop = (hash_info_bucket_t *) copy; 169: *countp = actual; 170: } 171: 172: return KERN_SUCCESS; 173: } 174: 175: /* 176: * Routine: host_ipc_marequest_info 177: * Purpose: 178: * Return information about the marequest hash table. 179: * Conditions: 180: * Nothing locked. Obeys CountInOut protocol. 181: * Returns: 182: * KERN_SUCCESS Returned information. 183: * KERN_INVALID_HOST The host is null. 184: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 185: */ 186: 187: kern_return_t 188: host_ipc_marequest_info(host, maxp, infop, countp) 189: host_t host; 190: unsigned int *maxp; 191: hash_info_bucket_array_t *infop; 192: unsigned int *countp; 193: { 194: vm_offset_t addr; 195: vm_size_t size = 0; /* '=0' to shut up lint */ 196: hash_info_bucket_t *info; 197: unsigned int potential, actual; 198: kern_return_t kr; 199: 200: if (host == HOST_NULL) 201: return KERN_INVALID_HOST; 202: 203: /* start with in-line data */ 204: 205: info = *infop; 206: potential = *countp; 207: 208: for (;;) { 209: actual = ipc_marequest_info(maxp, info, potential); 210: if (actual <= potential) 211: break; 212: 213: /* allocate more memory */ 214: 215: if (info != *infop) 216: kmem_free(ipc_kernel_map, addr, size); 217: 218: size = round_page(actual * sizeof *info); 219: kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size); 220: if (kr != KERN_SUCCESS) 221: return KERN_RESOURCE_SHORTAGE; 222: 223: info = (hash_info_bucket_t *) addr; 224: potential = size/sizeof *info; 225: } 226: 227: if (info == *infop) { 228: /* data fit in-line; nothing to deallocate */ 229: 230: *countp = actual; 231: } else if (actual == 0) { 232: kmem_free(ipc_kernel_map, addr, size); 233: 234: *countp = 0; 235: } else { 236: vm_map_copy_t copy; 237: vm_size_t used; 238: 239: used = round_page(actual * sizeof *info); 240: 241: if (used != size) 242: kmem_free(ipc_kernel_map, addr + used, size - used); 243: 244: kr = vm_map_copyin(ipc_kernel_map, addr, used, 245: TRUE, ©); 246: assert(kr == KERN_SUCCESS); 247: 248: *infop = (hash_info_bucket_t *) copy; 249: *countp = actual; 250: } 251: 252: return KERN_SUCCESS; 253: } 254: 255: /* 256: * Routine: mach_port_space_info 257: * Purpose: 258: * Returns information about an IPC space. 259: * Conditions: 260: * Nothing locked. Obeys CountInOut protocol. 261: * Returns: 262: * KERN_SUCCESS Returned information. 263: * KERN_INVALID_TASK The space is null. 264: * KERN_INVALID_TASK The space is dead. 265: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 266: */ 267: 268: kern_return_t 269: mach_port_space_info( 270: ipc_space_t space, 271: ipc_info_space_t *infop, 272: ipc_info_name_array_t *tablep, 273: mach_msg_type_number_t *tableCntp, 274: ipc_info_tree_name_array_t *treep, 275: mach_msg_type_number_t *treeCntp) 276: { 277: ipc_info_name_t *table_info; 278: unsigned int table_potential, table_actual; 279: vm_offset_t table_addr; 280: vm_size_t table_size; 281: ipc_info_tree_name_t *tree_info; 282: unsigned int tree_potential, tree_actual; 283: vm_offset_t tree_addr; 284: vm_size_t tree_size; 285: ipc_tree_entry_t tentry; 286: ipc_entry_t table; 287: ipc_entry_num_t tsize; 288: mach_port_index_t index; 289: kern_return_t kr; 290: 291: if (space == IS_NULL) 292: return KERN_INVALID_TASK; 293: 294: /* start with in-line memory */ 295: 296: table_info = *tablep; 297: table_potential = *tableCntp; 298: tree_info = *treep; 299: tree_potential = *treeCntp; 300: 301: for (;;) { 302: is_read_lock(space); 303: if (!space->is_active) { 304: is_read_unlock(space); 305: if (table_info != *tablep) 306: kmem_free(ipc_kernel_map, 307: table_addr, table_size); 308: if (tree_info != *treep) 309: kmem_free(ipc_kernel_map, 310: tree_addr, tree_size); 311: return KERN_INVALID_TASK; 312: } 313: 314: table_actual = space->is_table_size; 315: tree_actual = space->is_tree_total; 316: 317: if ((table_actual <= table_potential) && 318: (tree_actual <= tree_potential)) 319: break; 320: 321: is_read_unlock(space); 322: 323: if (table_actual > table_potential) { 324: if (table_info != *tablep) 325: kmem_free(ipc_kernel_map, 326: table_addr, table_size); 327: 328: table_size = round_page(table_actual * 329: sizeof *table_info); 330: kr = kmem_alloc(ipc_kernel_map, 331: &table_addr, table_size); 332: if (kr != KERN_SUCCESS) { 333: if (tree_info != *treep) 334: kmem_free(ipc_kernel_map, 335: tree_addr, tree_size); 336: 337: return KERN_RESOURCE_SHORTAGE; 338: } 339: 340: table_info = (ipc_info_name_t *) table_addr; 341: table_potential = table_size/sizeof *table_info; 342: } 343: 344: if (tree_actual > tree_potential) { 345: if (tree_info != *treep) 346: kmem_free(ipc_kernel_map, 347: tree_addr, tree_size); 348: 349: tree_size = round_page(tree_actual * 350: sizeof *tree_info); 351: kr = kmem_alloc(ipc_kernel_map, 352: &tree_addr, tree_size); 353: if (kr != KERN_SUCCESS) { 354: if (table_info != *tablep) 355: kmem_free(ipc_kernel_map, 356: table_addr, table_size); 357: 358: return KERN_RESOURCE_SHORTAGE; 359: } 360: 361: tree_info = (ipc_info_tree_name_t *) tree_addr; 362: tree_potential = tree_size/sizeof *tree_info; 363: } 364: } 365: /* space is read-locked and active; we have enough wired memory */ 366: 367: infop->iis_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD); 368: infop->iis_table_size = space->is_table_size; 369: infop->iis_table_next = space->is_table_next->its_size; 370: infop->iis_tree_size = space->is_tree_total; 371: infop->iis_tree_small = space->is_tree_small; 372: infop->iis_tree_hash = space->is_tree_hash; 373: 374: table = space->is_table; 375: tsize = space->is_table_size; 376: 377: for (index = 0; index < tsize; index++) { 378: ipc_info_name_t *iin = &table_info[index]; 379: ipc_entry_t entry = &table[index]; 380: ipc_entry_bits_t bits = entry->ie_bits; 381: 382: iin->iin_name = MACH_PORT_MAKEB(index, bits); 383: iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE; 384: #if MACH_IPC_COMPAT 385: iin->iin_compat = (bits & IE_BITS_COMPAT) ? TRUE : FALSE; 1.1.1.2 ! root 386: #else /* MACH_IPC_COMPAT */ 1.1 root 387: iin->iin_compat = FALSE; 1.1.1.2 ! root 388: #endif /* MACH_IPC_COMPAT */ 1.1 root 389: iin->iin_marequest = (bits & IE_BITS_MAREQUEST) ? TRUE : FALSE; 390: iin->iin_type = IE_BITS_TYPE(bits); 391: iin->iin_urefs = IE_BITS_UREFS(bits); 392: iin->iin_object = (vm_offset_t) entry->ie_object; 393: iin->iin_next = entry->ie_next; 394: iin->iin_hash = entry->ie_index; 395: } 396: 397: for (tentry = ipc_splay_traverse_start(&space->is_tree), index = 0; 398: tentry != ITE_NULL; 399: tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) { 400: ipc_info_tree_name_t *iitn = &tree_info[index++]; 401: ipc_info_name_t *iin = &iitn->iitn_name; 402: ipc_entry_t entry = &tentry->ite_entry; 403: ipc_entry_bits_t bits = entry->ie_bits; 404: 405: assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE); 406: 407: iin->iin_name = tentry->ite_name; 408: iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE; 409: #if MACH_IPC_COMPAT 410: iin->iin_compat = (bits & IE_BITS_COMPAT) ? TRUE : FALSE; 1.1.1.2 ! root 411: #else /* MACH_IPC_COMPAT */ 1.1 root 412: iin->iin_compat = FALSE; 1.1.1.2 ! root 413: #endif /* MACH_IPC_COMPAT */ 1.1 root 414: iin->iin_marequest = (bits & IE_BITS_MAREQUEST) ? TRUE : FALSE; 415: iin->iin_type = IE_BITS_TYPE(bits); 416: iin->iin_urefs = IE_BITS_UREFS(bits); 417: iin->iin_object = (vm_offset_t) entry->ie_object; 418: iin->iin_next = entry->ie_next; 419: iin->iin_hash = entry->ie_index; 420: 421: if (tentry->ite_lchild == ITE_NULL) 422: iitn->iitn_lchild = MACH_PORT_NULL; 423: else 424: iitn->iitn_lchild = tentry->ite_lchild->ite_name; 425: 426: if (tentry->ite_rchild == ITE_NULL) 427: iitn->iitn_rchild = MACH_PORT_NULL; 428: else 429: iitn->iitn_rchild = tentry->ite_rchild->ite_name; 430: 431: } 432: ipc_splay_traverse_finish(&space->is_tree); 433: is_read_unlock(space); 434: 435: if (table_info == *tablep) { 436: /* data fit in-line; nothing to deallocate */ 437: 438: *tableCntp = table_actual; 439: } else if (table_actual == 0) { 440: kmem_free(ipc_kernel_map, table_addr, table_size); 441: 442: *tableCntp = 0; 443: } else { 444: vm_size_t size_used, rsize_used; 445: vm_map_copy_t copy; 446: 447: /* kmem_alloc doesn't zero memory */ 448: 449: size_used = table_actual * sizeof *table_info; 450: rsize_used = round_page(size_used); 451: 452: if (rsize_used != table_size) 453: kmem_free(ipc_kernel_map, 454: table_addr + rsize_used, 455: table_size - rsize_used); 456: 457: if (size_used != rsize_used) 458: bzero((char *) (table_addr + size_used), 459: rsize_used - size_used); 460: 461: kr = vm_map_copyin(ipc_kernel_map, table_addr, rsize_used, 462: TRUE, ©); 463: 464: assert(kr == KERN_SUCCESS); 465: 466: *tablep = (ipc_info_name_t *) copy; 467: *tableCntp = table_actual; 468: } 469: 470: if (tree_info == *treep) { 471: /* data fit in-line; nothing to deallocate */ 472: 473: *treeCntp = tree_actual; 474: } else if (tree_actual == 0) { 475: kmem_free(ipc_kernel_map, tree_addr, tree_size); 476: 477: *treeCntp = 0; 478: } else { 479: vm_size_t size_used, rsize_used; 480: vm_map_copy_t copy; 481: 482: /* kmem_alloc doesn't zero memory */ 483: 484: size_used = tree_actual * sizeof *tree_info; 485: rsize_used = round_page(size_used); 486: 487: if (rsize_used != tree_size) 488: kmem_free(ipc_kernel_map, 489: tree_addr + rsize_used, 490: tree_size - rsize_used); 491: 492: if (size_used != rsize_used) 493: bzero((char *) (tree_addr + size_used), 494: rsize_used - size_used); 495: 496: kr = vm_map_copyin(ipc_kernel_map, tree_addr, rsize_used, 497: TRUE, ©); 498: 499: assert(kr == KERN_SUCCESS); 500: 501: *treep = (ipc_info_tree_name_t *) copy; 502: *treeCntp = tree_actual; 503: } 504: 505: return KERN_SUCCESS; 506: } 507: 508: /* 509: * Routine: mach_port_dnrequest_info 510: * Purpose: 511: * Returns information about the dead-name requests 512: * registered with the named receive right. 513: * Conditions: 514: * Nothing locked. 515: * Returns: 516: * KERN_SUCCESS Retrieved information. 517: * KERN_INVALID_TASK The space is null. 518: * KERN_INVALID_TASK The space is dead. 519: * KERN_INVALID_NAME The name doesn't denote a right. 520: * KERN_INVALID_RIGHT Name doesn't denote receive rights. 521: */ 522: 523: kern_return_t 524: mach_port_dnrequest_info( 525: ipc_space_t space, 526: mach_port_t name, 527: unsigned int *totalp, 528: unsigned int *usedp) 529: { 530: unsigned int total, used; 531: ipc_port_t port; 532: kern_return_t kr; 533: 534: if (space == IS_NULL) 535: return KERN_INVALID_TASK; 536: 537: kr = ipc_port_translate_receive(space, name, &port); 538: if (kr != KERN_SUCCESS) 539: return kr; 540: /* port is locked and active */ 541: 542: if (port->ip_dnrequests == IPR_NULL) { 543: total = 0; 544: used = 0; 545: } else { 546: ipc_port_request_t dnrequests = port->ip_dnrequests; 547: ipc_port_request_index_t index; 548: 549: total = dnrequests->ipr_size->its_size; 550: 551: for (index = 1, used = 0; 552: index < total; index++) { 553: ipc_port_request_t ipr = &dnrequests[index]; 554: 555: if (ipr->ipr_name != MACH_PORT_NULL) 556: used++; 557: } 558: } 559: ip_unlock(port); 560: 561: *totalp = total; 562: *usedp = used; 563: return KERN_SUCCESS; 564: } 565: 566: /* 567: * Routine: mach_port_kernel_object [kernel call] 568: * Purpose: 569: * Retrieve the type and address of the kernel object 570: * represented by a send or receive right. 571: * Conditions: 572: * Nothing locked. 573: * Returns: 574: * KERN_SUCCESS Retrieved kernel object info. 575: * KERN_INVALID_TASK The space is null. 576: * KERN_INVALID_TASK The space is dead. 577: * KERN_INVALID_NAME The name doesn't denote a right. 578: * KERN_INVALID_RIGHT Name doesn't denote 579: * send or receive rights. 580: */ 581: 582: kern_return_t 583: mach_port_kernel_object( 584: ipc_space_t space, 585: mach_port_t name, 586: unsigned int *typep, 587: vm_offset_t *addrp) 588: { 589: ipc_entry_t entry; 590: ipc_port_t port; 591: kern_return_t kr; 592: 593: kr = ipc_right_lookup_read(space, name, &entry); 594: if (kr != KERN_SUCCESS) 595: return kr; 596: /* space is read-locked and active */ 597: 598: if ((entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE) == 0) { 599: is_read_unlock(space); 600: return KERN_INVALID_RIGHT; 601: } 602: 603: port = (ipc_port_t) entry->ie_object; 604: assert(port != IP_NULL); 605: 606: ip_lock(port); 607: is_read_unlock(space); 608: 609: if (!ip_active(port)) { 610: ip_unlock(port); 611: return KERN_INVALID_RIGHT; 612: } 613: 614: *typep = (unsigned int) ip_kotype(port); 615: *addrp = (vm_offset_t) port->ip_kobject; 616: ip_unlock(port); 617: return KERN_SUCCESS; 618: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.