Annotation of XNU/osfmk/ipc/ipc_pset.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

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