|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright (c) 1995, 1994, 1993, 1992, 1991, 1990 ! 27: * Open Software Foundation, Inc. ! 28: * ! 29: * Permission to use, copy, modify, and distribute this software and ! 30: * its documentation for any purpose and without fee is hereby granted, ! 31: * provided that the above copyright notice appears in all copies and ! 32: * that both the copyright notice and this permission notice appear in ! 33: * supporting documentation, and that the name of ("OSF") or Open Software ! 34: * Foundation not be used in advertising or publicity pertaining to ! 35: * distribution of the software without specific, written prior permission. ! 36: * ! 37: * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ! 38: * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ! 39: * FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL OSF BE LIABLE FOR ANY ! 40: * SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ! 41: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ! 42: * ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING ! 43: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE ! 44: */ ! 45: /* ! 46: * OSF Research Institute MK6.1 (unencumbered) 1/31/1995 ! 47: */ ! 48: /* ! 49: * Mach Operating System ! 50: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 51: * All Rights Reserved. ! 52: * ! 53: * Permission to use, copy, modify and distribute this software and its ! 54: * documentation is hereby granted, provided that both the copyright ! 55: * notice and this permission notice appear in all copies of the ! 56: * software, derivative works or modified versions, and any portions ! 57: * thereof, and that both notices appear in supporting documentation. ! 58: * ! 59: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 60: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 61: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 62: * ! 63: * Carnegie Mellon requests users of this software to return to ! 64: * ! 65: * Software Distribution Coordinator or [email protected] ! 66: * School of Computer Science ! 67: * Carnegie Mellon University ! 68: * Pittsburgh PA 15213-3890 ! 69: * ! 70: * any improvements or extensions that they make and grant Carnegie Mellon ! 71: * the rights to redistribute these changes. ! 72: */ ! 73: /* ! 74: * File: ipc/ipc_pset.c ! 75: * Author: Rich Draves ! 76: * Date: 1989 ! 77: * ! 78: * Functions to manipulate IPC port sets. ! 79: */ ! 80: ! 81: #include <mach/port.h> ! 82: #include <mach/kern_return.h> ! 83: #include <mach/message.h> ! 84: #include <ipc/ipc_mqueue.h> ! 85: #include <ipc/ipc_object.h> ! 86: #include <ipc/ipc_pset.h> ! 87: #include <ipc/ipc_right.h> ! 88: #include <ipc/ipc_space.h> ! 89: ! 90: /* ! 91: * Forward declarations ! 92: */ ! 93: void ipc_pset_add( ! 94: ipc_pset_t pset, ! 95: ipc_port_t port); ! 96: ! 97: /* ! 98: * Routine: ipc_pset_alloc ! 99: * Purpose: ! 100: * Allocate a port set. ! 101: * Conditions: ! 102: * Nothing locked. If successful, the port set is returned ! 103: * locked. (The caller doesn't have a reference.) ! 104: * Returns: ! 105: * KERN_SUCCESS The port set is allocated. ! 106: * KERN_INVALID_TASK The space is dead. ! 107: * KERN_NO_SPACE No room for an entry in the space. ! 108: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 109: */ ! 110: ! 111: kern_return_t ! 112: ipc_pset_alloc( ! 113: ipc_space_t space, ! 114: mach_port_t *namep, ! 115: ipc_pset_t *psetp) ! 116: { ! 117: ipc_pset_t pset; ! 118: mach_port_t name; ! 119: kern_return_t kr; ! 120: ! 121: kr = ipc_object_alloc(space, IOT_PORT_SET, ! 122: MACH_PORT_TYPE_PORT_SET, 0, ! 123: &name, (ipc_object_t *) &pset); ! 124: if (kr != KERN_SUCCESS) ! 125: return kr; ! 126: /* pset is locked */ ! 127: ! 128: pset->ips_local_name = name; ! 129: ipc_mqueue_init(&pset->ips_messages); ! 130: ! 131: *namep = name; ! 132: *psetp = pset; ! 133: return KERN_SUCCESS; ! 134: } ! 135: ! 136: /* ! 137: * Routine: ipc_pset_alloc_name ! 138: * Purpose: ! 139: * Allocate a port set, with a specific name. ! 140: * Conditions: ! 141: * Nothing locked. If successful, the port set is returned ! 142: * locked. (The caller doesn't have a reference.) ! 143: * Returns: ! 144: * KERN_SUCCESS The port set is allocated. ! 145: * KERN_INVALID_TASK The space is dead. ! 146: * KERN_NAME_EXISTS The name already denotes a right. ! 147: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 148: */ ! 149: ! 150: kern_return_t ! 151: ipc_pset_alloc_name( ! 152: ipc_space_t space, ! 153: mach_port_t name, ! 154: ipc_pset_t *psetp) ! 155: { ! 156: ipc_pset_t pset; ! 157: kern_return_t kr; ! 158: ! 159: kr = ipc_object_alloc_name(space, IOT_PORT_SET, ! 160: MACH_PORT_TYPE_PORT_SET, 0, ! 161: name, (ipc_object_t *) &pset); ! 162: if (kr != KERN_SUCCESS) ! 163: return kr; ! 164: /* pset is locked */ ! 165: ! 166: pset->ips_local_name = name; ! 167: ipc_mqueue_init(&pset->ips_messages); ! 168: ! 169: *psetp = pset; ! 170: return KERN_SUCCESS; ! 171: } ! 172: ! 173: /* ! 174: * Routine: ipc_pset_add ! 175: * Purpose: ! 176: * Puts a port into a port set. ! 177: * The port set gains a reference. ! 178: * Conditions: ! 179: * Both port and port set are locked and active. ! 180: * The port isn't already in a set. ! 181: * The owner of the port set is also receiver for the port. ! 182: */ ! 183: ! 184: void ! 185: ipc_pset_add( ! 186: ipc_pset_t pset, ! 187: ipc_port_t port) ! 188: { ! 189: assert(ips_active(pset)); ! 190: assert(ip_active(port)); ! 191: assert(port->ip_pset == IPS_NULL); ! 192: ! 193: port->ip_pset = pset; ! 194: ips_reference(pset); ! 195: ! 196: imq_lock(&port->ip_messages); ! 197: imq_lock(&pset->ips_messages); ! 198: ! 199: /* move messages from port's queue to the port set's queue */ ! 200: ! 201: ipc_mqueue_move(&pset->ips_messages, &port->ip_messages, port); ! 202: imq_unlock(&pset->ips_messages); ! 203: assert(ipc_kmsg_queue_empty(&port->ip_messages.imq_messages)); ! 204: ! 205: /* wake up threads waiting to receive from the port */ ! 206: ! 207: ipc_mqueue_changed(&port->ip_messages, MACH_RCV_PORT_CHANGED); ! 208: assert(ipc_thread_queue_empty(&port->ip_messages.imq_threads)); ! 209: imq_unlock(&port->ip_messages); ! 210: } ! 211: ! 212: /* ! 213: * Routine: ipc_pset_remove ! 214: * Purpose: ! 215: * Removes a port from a port set. ! 216: * The port set loses a reference. ! 217: * Conditions: ! 218: * Both port and port set are locked. ! 219: * The port must be active. ! 220: */ ! 221: ! 222: void ! 223: ipc_pset_remove( ! 224: ipc_pset_t pset, ! 225: ipc_port_t port) ! 226: { ! 227: assert(ip_active(port)); ! 228: assert(port->ip_pset == pset); ! 229: ! 230: port->ip_pset = IPS_NULL; ! 231: ips_release(pset); ! 232: ! 233: imq_lock(&port->ip_messages); ! 234: imq_lock(&pset->ips_messages); ! 235: ! 236: /* move messages from port set's queue to the port's queue */ ! 237: ! 238: ipc_mqueue_move(&port->ip_messages, &pset->ips_messages, port); ! 239: ! 240: imq_unlock(&pset->ips_messages); ! 241: imq_unlock(&port->ip_messages); ! 242: } ! 243: ! 244: /* ! 245: * Routine: ipc_pset_move ! 246: * Purpose: ! 247: * If nset is IPS_NULL, removes port ! 248: * from the port set it is in. Otherwise, adds ! 249: * port to nset, removing it from any set ! 250: * it might already be in. ! 251: * Conditions: ! 252: * The space is read-locked. ! 253: * Returns: ! 254: * KERN_SUCCESS Moved the port. ! 255: * KERN_NOT_IN_SET nset is null and port isn't in a set. ! 256: */ ! 257: ! 258: kern_return_t ! 259: ipc_pset_move( ! 260: ipc_space_t space, ! 261: ipc_port_t port, ! 262: ipc_pset_t nset) ! 263: { ! 264: ipc_pset_t oset; ! 265: ! 266: /* ! 267: * While we've got the space locked, it holds refs for ! 268: * the port and nset (because of the entries). Also, ! 269: * they must be alive. While we've got port locked, it ! 270: * holds a ref for oset, which might not be alive. ! 271: */ ! 272: ! 273: ip_lock(port); ! 274: assert(ip_active(port)); ! 275: ! 276: oset = port->ip_pset; ! 277: ! 278: if (oset == nset) { ! 279: /* the port is already in the new set: a noop */ ! 280: ! 281: is_read_unlock(space); ! 282: } else if (oset == IPS_NULL) { ! 283: /* just add port to the new set */ ! 284: ! 285: ips_lock(nset); ! 286: assert(ips_active(nset)); ! 287: is_read_unlock(space); ! 288: ! 289: ipc_pset_add(nset, port); ! 290: ! 291: ips_unlock(nset); ! 292: } else if (nset == IPS_NULL) { ! 293: /* just remove port from the old set */ ! 294: ! 295: is_read_unlock(space); ! 296: ips_lock(oset); ! 297: ! 298: ipc_pset_remove(oset, port); ! 299: ! 300: if (ips_active(oset)) ! 301: ips_unlock(oset); ! 302: else { ! 303: ips_check_unlock(oset); ! 304: oset = IPS_NULL; /* trigger KERN_NOT_IN_SET */ ! 305: } ! 306: } else { ! 307: /* atomically move port from oset to nset */ ! 308: ! 309: if (oset < nset) { ! 310: ips_lock(oset); ! 311: ips_lock(nset); ! 312: } else { ! 313: ips_lock(nset); ! 314: ips_lock(oset); ! 315: } ! 316: ! 317: is_read_unlock(space); ! 318: assert(ips_active(nset)); ! 319: ! 320: ipc_pset_remove(oset, port); ! 321: ipc_pset_add(nset, port); ! 322: ! 323: ips_unlock(nset); ! 324: ips_check_unlock(oset); /* KERN_NOT_IN_SET not a possibility */ ! 325: } ! 326: ! 327: ip_unlock(port); ! 328: ! 329: return (((nset == IPS_NULL) && (oset == IPS_NULL)) ? ! 330: KERN_NOT_IN_SET : KERN_SUCCESS); ! 331: } ! 332: ! 333: /* ! 334: * Routine: ipc_pset_destroy ! 335: * Purpose: ! 336: * Destroys a port_set. ! 337: * ! 338: * Doesn't remove members from the port set; ! 339: * that happens lazily. As members are removed, ! 340: * their messages are removed from the queue. ! 341: * Conditions: ! 342: * The port_set is locked and alive. ! 343: * The caller has a reference, which is consumed. ! 344: * Afterwards, the port_set is unlocked and dead. ! 345: */ ! 346: ! 347: void ! 348: ipc_pset_destroy( ! 349: ipc_pset_t pset) ! 350: { ! 351: assert(ips_active(pset)); ! 352: ! 353: pset->ips_object.io_bits &= ~IO_BITS_ACTIVE; ! 354: ! 355: imq_lock(&pset->ips_messages); ! 356: ipc_mqueue_changed(&pset->ips_messages, MACH_RCV_PORT_DIED); ! 357: imq_unlock(&pset->ips_messages); ! 358: ! 359: ips_release(pset); /* consume the ref our caller gave us */ ! 360: ips_check_unlock(pset); ! 361: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.