|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: /* ! 53: * File: ipc/ipc_pset.c ! 54: * Author: Rich Draves ! 55: * Date: 1989 ! 56: * ! 57: * Functions to manipulate IPC port sets. ! 58: */ ! 59: ! 60: #include <mach/port.h> ! 61: #include <mach/kern_return.h> ! 62: #include <mach/message.h> ! 63: #include <ipc/ipc_mqueue.h> ! 64: #include <ipc/ipc_object.h> ! 65: #include <ipc/ipc_pset.h> ! 66: #include <ipc/ipc_right.h> ! 67: #include <ipc/ipc_space.h> ! 68: #include <ipc/ipc_port.h> ! 69: #include <ipc/ipc_print.h> ! 70: #include <kern/thread_pool.h> ! 71: ! 72: /* ! 73: * Routine: ipc_pset_alloc ! 74: * Purpose: ! 75: * Allocate a port set. ! 76: * Conditions: ! 77: * Nothing locked. If successful, the port set is returned ! 78: * locked. (The caller doesn't have a reference.) ! 79: * Returns: ! 80: * KERN_SUCCESS The port set is allocated. ! 81: * KERN_INVALID_TASK The space is dead. ! 82: * KERN_NO_SPACE No room for an entry in the space. ! 83: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 84: */ ! 85: ! 86: kern_return_t ! 87: ipc_pset_alloc( ! 88: ipc_space_t space, ! 89: mach_port_name_t *namep, ! 90: ipc_pset_t *psetp) ! 91: { ! 92: ipc_pset_t pset; ! 93: mach_port_name_t name; ! 94: kern_return_t kr; ! 95: ! 96: kr = ipc_object_alloc(space, IOT_PORT_SET, ! 97: MACH_PORT_TYPE_PORT_SET, 0, ! 98: &name, (ipc_object_t *) &pset); ! 99: if (kr != KERN_SUCCESS) ! 100: return kr; ! 101: /* pset is locked */ ! 102: ! 103: pset->ips_local_name = name; ! 104: pset->ips_pset_self = pset; ! 105: ipc_mqueue_init(&pset->ips_messages, TRUE /* set */); ! 106: thread_pool_init(&pset->ips_thread_pool); ! 107: ! 108: *namep = name; ! 109: *psetp = pset; ! 110: return KERN_SUCCESS; ! 111: } ! 112: ! 113: /* ! 114: * Routine: ipc_pset_alloc_name ! 115: * Purpose: ! 116: * Allocate a port set, with a specific name. ! 117: * Conditions: ! 118: * Nothing locked. If successful, the port set is returned ! 119: * locked. (The caller doesn't have a reference.) ! 120: * Returns: ! 121: * KERN_SUCCESS The port set is allocated. ! 122: * KERN_INVALID_TASK The space is dead. ! 123: * KERN_NAME_EXISTS The name already denotes a right. ! 124: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 125: */ ! 126: ! 127: kern_return_t ! 128: ipc_pset_alloc_name( ! 129: ipc_space_t space, ! 130: mach_port_name_t name, ! 131: ipc_pset_t *psetp) ! 132: { ! 133: ipc_pset_t pset; ! 134: kern_return_t kr; ! 135: ! 136: ! 137: kr = ipc_object_alloc_name(space, IOT_PORT_SET, ! 138: MACH_PORT_TYPE_PORT_SET, 0, ! 139: name, (ipc_object_t *) &pset); ! 140: if (kr != KERN_SUCCESS) ! 141: return kr; ! 142: /* pset is locked */ ! 143: ! 144: pset->ips_local_name = name; ! 145: pset->ips_pset_self = pset; ! 146: ipc_mqueue_init(&pset->ips_messages, TRUE /* set */); ! 147: thread_pool_init(&pset->ips_thread_pool); ! 148: ! 149: *psetp = pset; ! 150: return KERN_SUCCESS; ! 151: } ! 152: ! 153: /* ! 154: * Routine: ipc_pset_member ! 155: * Purpose: ! 156: * Checks to see if a port is a member of a pset ! 157: * Conditions: ! 158: * Both port and port set are locked. ! 159: * The port must be active. ! 160: */ ! 161: boolean_t ! 162: ipc_pset_member( ! 163: ipc_pset_t pset, ! 164: ipc_port_t port) ! 165: { ! 166: assert(ip_active(port)); ! 167: ! 168: return (ipc_mqueue_member(&port->ip_messages, &pset->ips_messages)); ! 169: } ! 170: ! 171: ! 172: /* ! 173: * Routine: ipc_pset_add ! 174: * Purpose: ! 175: * Puts a port into a port set. ! 176: * The port set gains a reference. ! 177: * Conditions: ! 178: * Both port and port set are locked and active. ! 179: * The owner of the port set is also receiver for the port. ! 180: */ ! 181: ! 182: kern_return_t ! 183: ipc_pset_add( ! 184: ipc_pset_t pset, ! 185: ipc_port_t port) ! 186: { ! 187: assert(ips_active(pset)); ! 188: assert(ip_active(port)); ! 189: ! 190: if (ipc_pset_member(pset, port)) ! 191: return KERN_ALREADY_IN_SET; ! 192: ! 193: ips_reference(pset); ! 194: port->ip_pset_count++; ! 195: ! 196: ipc_mqueue_add(&port->ip_messages, &pset->ips_messages); ! 197: ! 198: return KERN_SUCCESS; ! 199: } ! 200: ! 201: ! 202: ! 203: /* ! 204: * Routine: ipc_pset_remove ! 205: * Purpose: ! 206: * Removes a port from a port set. ! 207: * The port set loses a reference. ! 208: * Conditions: ! 209: * Both port and port set are locked. ! 210: * The port must be active. ! 211: */ ! 212: ! 213: kern_return_t ! 214: ipc_pset_remove( ! 215: ipc_pset_t pset, ! 216: ipc_port_t port) ! 217: { ! 218: mach_msg_return_t mr; ! 219: ! 220: assert(ip_active(port)); ! 221: ! 222: if (port->ip_pset_count == 0) ! 223: return KERN_NOT_IN_SET; ! 224: ! 225: mr = ipc_mqueue_remove(&port->ip_messages, &pset->ips_messages); ! 226: ! 227: if (mr == MACH_MSG_SUCCESS) { ! 228: port->ip_pset_count--; ! 229: ips_release(pset); ! 230: } ! 231: return mr; ! 232: } ! 233: ! 234: /* ! 235: * Routine: ipc_pset_remove_all ! 236: * Purpose: ! 237: * Removes a port from all it's port sets. ! 238: * Each port set loses a reference. ! 239: * Conditions: ! 240: * port is locked and active. ! 241: */ ! 242: ! 243: kern_return_t ! 244: ipc_pset_remove_all( ! 245: ipc_port_t port) ! 246: { ! 247: ipc_pset_mqueue_t pset_mqueue; ! 248: ipc_pset_t pset; ! 249: ! 250: assert(ip_active(port)); ! 251: ! 252: if (port->ip_pset_count == 0) ! 253: return KERN_NOT_IN_SET; ! 254: ! 255: /* ! 256: * Remove each port set's mqueue from the port's (one at a time). ! 257: */ ! 258: for (;;) { ! 259: ipc_mqueue_remove_one(&port->ip_messages, ! 260: (ipc_mqueue_t)&pset_mqueue); ! 261: if (pset_mqueue == (ipc_pset_mqueue_t)0) ! 262: break; ! 263: ! 264: pset = pset_mqueue->ipsm_pset; ! 265: ips_release(pset); ! 266: ! 267: port->ip_pset_count--; ! 268: } ! 269: ! 270: assert(port->ip_pset_count == 0); ! 271: return KERN_SUCCESS; ! 272: } ! 273: ! 274: ! 275: /* ! 276: * Routine: ipc_pset_destroy ! 277: * Purpose: ! 278: * Destroys a port_set. ! 279: * ! 280: * Doesn't remove members from the port set; ! 281: * that happens lazily. ! 282: * Conditions: ! 283: * The port_set is locked and alive. ! 284: * The caller has a reference, which is consumed. ! 285: * Afterwards, the port_set is unlocked and dead. ! 286: */ ! 287: ! 288: void ! 289: ipc_pset_destroy( ! 290: ipc_pset_t pset) ! 291: { ! 292: assert(ips_active(pset)); ! 293: ! 294: pset->ips_object.io_bits &= ~IO_BITS_ACTIVE; ! 295: ! 296: imq_lock(&pset->ips_messages); ! 297: ipc_mqueue_changed(&pset->ips_messages); ! 298: imq_unlock(&pset->ips_messages); ! 299: ! 300: /* XXXX Perhaps ought to verify ips_thread_pool is empty */ ! 301: ! 302: ips_release(pset); /* consume the ref our caller gave us */ ! 303: ips_check_unlock(pset); ! 304: } ! 305: ! 306: #include <mach_kdb.h> ! 307: #if MACH_KDB ! 308: ! 309: #include <ddb/db_output.h> ! 310: ! 311: #define printf kdbprintf ! 312: ! 313: int ! 314: ipc_list_count( ! 315: struct ipc_kmsg *base) ! 316: { ! 317: register int count = 0; ! 318: ! 319: if (base) { ! 320: struct ipc_kmsg *kmsg = base; ! 321: ! 322: ++count; ! 323: while (kmsg && kmsg->ikm_next != base ! 324: && kmsg->ikm_next != IKM_BOGUS){ ! 325: kmsg = kmsg->ikm_next; ! 326: ++count; ! 327: } ! 328: } ! 329: return(count); ! 330: } ! 331: ! 332: /* ! 333: * Routine: ipc_pset_print ! 334: * Purpose: ! 335: * Pretty-print a port set for kdb. ! 336: */ ! 337: ! 338: void ! 339: ipc_pset_print( ! 340: ipc_pset_t pset) ! 341: { ! 342: extern int db_indent; ! 343: ! 344: printf("pset 0x%x\n", pset); ! 345: ! 346: db_indent += 2; ! 347: ! 348: ipc_object_print(&pset->ips_object); ! 349: iprintf("local_name = 0x%x\n", pset->ips_local_name); ! 350: iprintf("%d kmsgs => 0x%x", ! 351: ipc_list_count(pset->ips_messages.imq_messages.ikmq_base), ! 352: pset->ips_messages.imq_messages.ikmq_base); ! 353: printf(",rcvrs queue= 0x%x\n", &pset->ips_messages.imq_wait_queue); ! 354: ! 355: db_indent -=2; ! 356: } ! 357: ! 358: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.