Annotation of OSKit-Mach/ipc/ipc_pset.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989Carnegie 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/ipc_pset.c
                     33:  *     Author: Rich Draves
                     34:  *     Date:   1989
                     35:  *
                     36:  *     Functions to manipulate IPC port sets.
                     37:  */
                     38: 
                     39: #include <mach/port.h>
                     40: #include <mach/kern_return.h>
                     41: #include <mach/message.h>
                     42: #include <ipc/ipc_mqueue.h>
                     43: #include <ipc/ipc_object.h>
                     44: #include <ipc/ipc_pset.h>
                     45: #include <ipc/ipc_right.h>
                     46: #include <ipc/ipc_space.h>
                     47: 
                     48: 
                     49: /*
                     50:  *     Routine:        ipc_pset_alloc
                     51:  *     Purpose:
                     52:  *             Allocate a port set.
                     53:  *     Conditions:
                     54:  *             Nothing locked.  If successful, the port set is returned
                     55:  *             locked.  (The caller doesn't have a reference.)
                     56:  *     Returns:
                     57:  *             KERN_SUCCESS            The port set is allocated.
                     58:  *             KERN_INVALID_TASK       The space is dead.
                     59:  *             KERN_NO_SPACE           No room for an entry in the space.
                     60:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                     61:  */
                     62: 
                     63: kern_return_t
                     64: ipc_pset_alloc(
                     65:        ipc_space_t     space,
                     66:        mach_port_t     *namep,
                     67:        ipc_pset_t      *psetp)
                     68: {
                     69:        ipc_pset_t pset;
                     70:        mach_port_t name;
                     71:        kern_return_t kr;
                     72: 
                     73:        kr = ipc_object_alloc(space, IOT_PORT_SET,
                     74:                              MACH_PORT_TYPE_PORT_SET, 0,
                     75:                              &name, (ipc_object_t *) &pset);
                     76:        if (kr != KERN_SUCCESS)
                     77:                return kr;
                     78:        /* pset is locked */
                     79: 
                     80:        ipc_target_init(&pset->ips_target, name);
                     81: 
                     82:        *namep = name;
                     83:        *psetp = pset;
                     84:        return KERN_SUCCESS;
                     85: }
                     86: 
                     87: /*
                     88:  *     Routine:        ipc_pset_alloc_name
                     89:  *     Purpose:
                     90:  *             Allocate a port set, with a specific name.
                     91:  *     Conditions:
                     92:  *             Nothing locked.  If successful, the port set is returned
                     93:  *             locked.  (The caller doesn't have a reference.)
                     94:  *     Returns:
                     95:  *             KERN_SUCCESS            The port set is allocated.
                     96:  *             KERN_INVALID_TASK       The space is dead.
                     97:  *             KERN_NAME_EXISTS        The name already denotes a right.
                     98:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                     99:  */
                    100: 
                    101: kern_return_t
                    102: ipc_pset_alloc_name(
                    103:        ipc_space_t     space,
                    104:        mach_port_t     name,
                    105:        ipc_pset_t      *psetp)
                    106: {
                    107:        ipc_pset_t pset;
                    108:        kern_return_t kr;
                    109: 
                    110: 
                    111:        kr = ipc_object_alloc_name(space, IOT_PORT_SET,
                    112:                                   MACH_PORT_TYPE_PORT_SET, 0,
                    113:                                   name, (ipc_object_t *) &pset);
                    114:        if (kr != KERN_SUCCESS)
                    115:                return kr;
                    116:        /* pset is locked */
                    117: 
                    118:        ipc_target_init(&pset->ips_target, name);
                    119: 
                    120:        *psetp = pset;
                    121:        return KERN_SUCCESS;
                    122: }
                    123: 
                    124: /*
                    125:  *     Routine:        ipc_pset_add
                    126:  *     Purpose:
                    127:  *             Puts a port into a port set.
                    128:  *             The port set gains a reference.
                    129:  *     Conditions:
                    130:  *             Both port and port set are locked and active.
                    131:  *             The port isn't already in a set.
                    132:  *             The owner of the port set is also receiver for the port.
                    133:  */
                    134: 
                    135: void
                    136: ipc_pset_add(
                    137:        ipc_pset_t      pset,
                    138:        ipc_port_t      port)
                    139: {
                    140:        assert(ips_active(pset));
                    141:        assert(ip_active(port));
                    142:        assert(port->ip_pset == IPS_NULL);
                    143: 
                    144:        port->ip_pset = pset;
                    145:        port->ip_cur_target = &pset->ips_target;
                    146:        ips_reference(pset);
                    147: 
                    148:        imq_lock(&port->ip_messages);
                    149:        imq_lock(&pset->ips_messages);
                    150: 
                    151:        /* move messages from port's queue to the port set's queue */
                    152: 
                    153:        ipc_mqueue_move(&pset->ips_messages, &port->ip_messages, port);
                    154:        imq_unlock(&pset->ips_messages);
                    155:        assert(ipc_kmsg_queue_empty(&port->ip_messages.imq_messages));
                    156: 
                    157:        /* wake up threads waiting to receive from the port */
                    158: 
                    159:        ipc_mqueue_changed(&port->ip_messages, MACH_RCV_PORT_CHANGED);
                    160:        assert(ipc_thread_queue_empty(&port->ip_messages.imq_threads));
                    161:        imq_unlock(&port->ip_messages);
                    162: }
                    163: 
                    164: /*
                    165:  *     Routine:        ipc_pset_remove
                    166:  *     Purpose:
                    167:  *             Removes a port from a port set.
                    168:  *             The port set loses a reference.
                    169:  *     Conditions:
                    170:  *             Both port and port set are locked.
                    171:  *             The port must be active.
                    172:  */
                    173: 
                    174: void
                    175: ipc_pset_remove(
                    176:        ipc_pset_t      pset,
                    177:        ipc_port_t      port)
                    178: {
                    179:        assert(ip_active(port));
                    180:        assert(port->ip_pset == pset);
                    181: 
                    182:        port->ip_pset = IPS_NULL;
                    183:        port->ip_cur_target = &port->ip_target;
                    184:        ips_release(pset);
                    185: 
                    186:        imq_lock(&port->ip_messages);
                    187:        imq_lock(&pset->ips_messages);
                    188: 
                    189:        /* move messages from port set's queue to the port's queue */
                    190: 
                    191:        ipc_mqueue_move(&port->ip_messages, &pset->ips_messages, port);
                    192: 
                    193:        imq_unlock(&pset->ips_messages);
                    194:        imq_unlock(&port->ip_messages);
                    195: }
                    196: 
                    197: /*
                    198:  *     Routine:        ipc_pset_move
                    199:  *     Purpose:
                    200:  *             If nset is IPS_NULL, removes port
                    201:  *             from the port set it is in.  Otherwise, adds
                    202:  *             port to nset, removing it from any set
                    203:  *             it might already be in.
                    204:  *     Conditions:
                    205:  *             The space is read-locked.
                    206:  *     Returns:
                    207:  *             KERN_SUCCESS            Moved the port.
                    208:  *             KERN_NOT_IN_SET         nset is null and port isn't in a set.
                    209:  */
                    210: 
                    211: kern_return_t
                    212: ipc_pset_move(
                    213:        ipc_space_t     space,
                    214:        ipc_port_t      port,
                    215:        ipc_pset_t      nset)
                    216: {
                    217:        ipc_pset_t oset;
                    218: 
                    219:        /*
                    220:         *      While we've got the space locked, it holds refs for
                    221:         *      the port and nset (because of the entries).  Also,
                    222:         *      they must be alive.  While we've got port locked, it
                    223:         *      holds a ref for oset, which might not be alive.
                    224:         */
                    225: 
                    226:        ip_lock(port);
                    227:        assert(ip_active(port));
                    228: 
                    229:        oset = port->ip_pset;
                    230: 
                    231:        if (oset == nset) {
                    232:                /* the port is already in the new set:  a noop */
                    233: 
                    234:                is_read_unlock(space);
                    235:        } else if (oset == IPS_NULL) {
                    236:                /* just add port to the new set */
                    237: 
                    238:                ips_lock(nset);
                    239:                assert(ips_active(nset));
                    240:                is_read_unlock(space);
                    241: 
                    242:                ipc_pset_add(nset, port);
                    243: 
                    244:                ips_unlock(nset);
                    245:        } else if (nset == IPS_NULL) {
                    246:                /* just remove port from the old set */
                    247: 
                    248:                is_read_unlock(space);
                    249:                ips_lock(oset);
                    250: 
                    251:                ipc_pset_remove(oset, port);
                    252: 
                    253:                if (ips_active(oset))
                    254:                        ips_unlock(oset);
                    255:                else {
                    256:                        ips_check_unlock(oset);
                    257:                        oset = IPS_NULL; /* trigger KERN_NOT_IN_SET */
                    258:                }
                    259:        } else {
                    260:                /* atomically move port from oset to nset */
                    261: 
                    262:                if (oset < nset) {
                    263:                        ips_lock(oset);
                    264:                        ips_lock(nset);
                    265:                } else {
                    266:                        ips_lock(nset);
                    267:                        ips_lock(oset);
                    268:                }
                    269: 
                    270:                is_read_unlock(space);
                    271:                assert(ips_active(nset));
                    272: 
                    273:                ipc_pset_remove(oset, port);
                    274:                ipc_pset_add(nset, port);
                    275: 
                    276:                ips_unlock(nset);
                    277:                ips_check_unlock(oset); /* KERN_NOT_IN_SET not a possibility */
                    278:        }
                    279: 
                    280:        ip_unlock(port);
                    281: 
                    282:        return (((nset == IPS_NULL) && (oset == IPS_NULL)) ?
                    283:                KERN_NOT_IN_SET : KERN_SUCCESS);
                    284: }
                    285: 
                    286: /*
                    287:  *     Routine:        ipc_pset_destroy
                    288:  *     Purpose:
                    289:  *             Destroys a port_set.
                    290:  *
                    291:  *             Doesn't remove members from the port set;
                    292:  *             that happens lazily.  As members are removed,
                    293:  *             their messages are removed from the queue.
                    294:  *     Conditions:
                    295:  *             The port_set is locked and alive.
                    296:  *             The caller has a reference, which is consumed.
                    297:  *             Afterwards, the port_set is unlocked and dead.
                    298:  */
                    299: 
                    300: void
                    301: ipc_pset_destroy(
                    302:        ipc_pset_t      pset)
                    303: {
                    304:        assert(ips_active(pset));
                    305: 
                    306:        pset->ips_object.io_bits &= ~IO_BITS_ACTIVE;
                    307: 
                    308:        imq_lock(&pset->ips_messages);
                    309:        ipc_mqueue_changed(&pset->ips_messages, MACH_RCV_PORT_DIED);
                    310:        imq_unlock(&pset->ips_messages);
                    311: 
                    312:        /* Common destruction for the IPC target.  */
                    313:        ipc_target_terminate(&pset->ips_target);
                    314: 
                    315:        ips_release(pset);      /* consume the ref our caller gave us */
                    316:        ips_check_unlock(pset);
                    317: }
                    318: 
                    319: #include <mach_kdb.h>
                    320: 
                    321: 
                    322: #if    MACH_KDB
                    323: #define        printf  kdbprintf
                    324: 
                    325: /*
                    326:  *     Routine:        ipc_pset_print
                    327:  *     Purpose:
                    328:  *             Pretty-print a port set for kdb.
                    329:  */
                    330: 
                    331: void
                    332: ipc_pset_print(
                    333:        ipc_pset_t      pset)
                    334: {
                    335:        extern int indent;
                    336: 
                    337:        printf("pset 0x%x\n", pset);
                    338: 
                    339:        indent += 2;
                    340: 
                    341:        ipc_object_print(&pset->ips_object);
                    342:        iprintf("local_name = 0x%x\n", pset->ips_local_name);
                    343:        iprintf("kmsgs = 0x%x", pset->ips_messages.imq_messages.ikmq_base);
                    344:        printf(",rcvrs = 0x%x\n", pset->ips_messages.imq_threads.ithq_base);
                    345: 
                    346:        indent -=2;
                    347: }
                    348: 
                    349: #endif /* MACH_KDB */

unix.superglobalmegacorp.com

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