Annotation of kernel/ipc/ipc_pset.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.