Annotation of XNU/osfmk/ipc/ipc_space.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_space.c
                     54:  *     Author: Rich Draves
                     55:  *     Date:   1989
                     56:  *
                     57:  *     Functions to manipulate IPC capability spaces.
                     58:  */
                     59: 
                     60: #include <dipc.h>
                     61: #include <mach_kdb.h>
                     62: 
                     63: #include <mach/boolean.h>
                     64: #include <mach/kern_return.h>
                     65: #include <mach/port.h>
                     66: #include <kern/assert.h>
                     67: #include <kern/sched_prim.h>
                     68: #include <kern/zalloc.h>
                     69: #include <ipc/port.h>
                     70: #include <ipc/ipc_entry.h>
                     71: #include <ipc/ipc_splay.h>
                     72: #include <ipc/ipc_object.h>
                     73: #include <ipc/ipc_hash.h>
                     74: #include <ipc/ipc_table.h>
                     75: #include <ipc/ipc_port.h>
                     76: #include <ipc/ipc_space.h>
                     77: #include <ipc/ipc_right.h>
                     78: #include <string.h>
                     79: 
                     80: zone_t ipc_space_zone;
                     81: ipc_space_t ipc_space_kernel;
                     82: ipc_space_t ipc_space_reply;
                     83: #if    DIPC
                     84: ipc_space_t ipc_space_remote;
                     85: #endif /* DIPC */
                     86: #if    DIPC || MACH_KDB
                     87: ipc_space_t default_pager_space;
                     88: #endif /* DIPC || MACH_KDB */
                     89: 
                     90: /*
                     91:  *     Routine:        ipc_space_reference
                     92:  *     Routine:        ipc_space_release
                     93:  *     Purpose:
                     94:  *             Function versions of the IPC space macros.
                     95:  *             The "is_" cover macros can be defined to use the
                     96:  *             macros or the functions, as desired.
                     97:  */
                     98: 
                     99: void
                    100: ipc_space_reference(
                    101:        ipc_space_t     space)
                    102: {
                    103:        ipc_space_reference_macro(space);
                    104: }
                    105: 
                    106: void
                    107: ipc_space_release(
                    108:        ipc_space_t     space)
                    109: {
                    110:        ipc_space_release_macro(space);
                    111: }
                    112: 
                    113: /*
                    114:  *     Routine:        ipc_space_create
                    115:  *     Purpose:
                    116:  *             Creates a new IPC space.
                    117:  *
                    118:  *             The new space has two references, one for the caller
                    119:  *             and one because it is active.
                    120:  *     Conditions:
                    121:  *             Nothing locked.  Allocates memory.
                    122:  *     Returns:
                    123:  *             KERN_SUCCESS            Created a space.
                    124:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    125:  */
                    126: 
                    127: kern_return_t
                    128: ipc_space_create(
                    129:        ipc_table_size_t        initial,
                    130:        ipc_space_t             *spacep)
                    131: {
                    132:        ipc_space_t space;
                    133:        ipc_entry_t table;
                    134:        ipc_entry_num_t new_size;
                    135:        mach_port_index_t index;
                    136: 
                    137:        space = is_alloc();
                    138:        if (space == IS_NULL)
                    139:                return KERN_RESOURCE_SHORTAGE;
                    140: 
                    141:        table = it_entries_alloc(initial);
                    142:        if (table == IE_NULL) {
                    143:                is_free(space);
                    144:                return KERN_RESOURCE_SHORTAGE;
                    145:        }
                    146: 
                    147:        new_size = initial->its_size;
                    148:        memset((void *) table, 0, new_size * sizeof(struct ipc_entry));
                    149: 
                    150:        /*
                    151:         *      Initialize the free list in the table.
                    152:         *      Add the entries in reverse order, and
                    153:         *      set the generation number to -1, so that
                    154:         *      initial allocations produce "natural" names.
                    155:         */
                    156:        for (index = 0; index < new_size; index++) {
                    157:                ipc_entry_t entry = &table[index];
                    158: 
                    159:                entry->ie_bits = IE_BITS_GEN_MASK;
                    160:                entry->ie_next = index+1;
                    161:        }
                    162:        table[new_size-1].ie_next = 0;
                    163: 
                    164:        is_ref_lock_init(space);
                    165:        space->is_references = 2;
                    166: 
                    167:        is_lock_init(space);
                    168:        space->is_active = TRUE;
                    169:        space->is_growing = FALSE;
                    170:        space->is_table = table;
                    171:        space->is_table_size = new_size;
                    172:        space->is_table_next = initial+1;
                    173: 
                    174:        ipc_splay_tree_init(&space->is_tree);
                    175:        space->is_tree_total = 0;
                    176:        space->is_tree_small = 0;
                    177:        space->is_tree_hash = 0;
                    178: 
                    179:        *spacep = space;
                    180:        return KERN_SUCCESS;
                    181: }
                    182: 
                    183: /*
                    184:  *     Routine:        ipc_space_create_special
                    185:  *     Purpose:
                    186:  *             Create a special space.  A special space
                    187:  *             doesn't hold rights in the normal way.
                    188:  *             Instead it is place-holder for holding
                    189:  *             disembodied (naked) receive rights.
                    190:  *             See ipc_port_alloc_special/ipc_port_dealloc_special.
                    191:  *     Conditions:
                    192:  *             Nothing locked.
                    193:  *     Returns:
                    194:  *             KERN_SUCCESS            Created a space.
                    195:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
                    196:  */
                    197: 
                    198: kern_return_t
                    199: ipc_space_create_special(
                    200:        ipc_space_t     *spacep)
                    201: {
                    202:        ipc_space_t space;
                    203: 
                    204:        space = is_alloc();
                    205:        if (space == IS_NULL)
                    206:                return KERN_RESOURCE_SHORTAGE;
                    207: 
                    208:        is_ref_lock_init(space);
                    209:        space->is_references = 1;
                    210: 
                    211:        is_lock_init(space);
                    212:        space->is_active = FALSE;
                    213: 
                    214:        *spacep = space;
                    215:        return KERN_SUCCESS;
                    216: }
                    217: 
                    218: /*
                    219:  * ipc_space_clean - remove all port references from an ipc space.
                    220:  *
                    221:  * In order to follow the traditional semantic, ipc_space_destroy
                    222:  * will not destroy the entire port table of a shared space.  Instead
                    223:  * it will simply clear its own sub-space.
                    224:  */
                    225: void
                    226: ipc_space_clean(
                    227:        ipc_space_t space)
                    228: {
                    229:        ipc_tree_entry_t tentry;
                    230:        ipc_entry_t table;
                    231:        ipc_entry_num_t size;
                    232:        mach_port_index_t index;
                    233: 
                    234:        /*
                    235:         *      If somebody is trying to grow the table,
                    236:         *      we must wait until they finish and figure
                    237:         *      out the space died.
                    238:         */
                    239:        is_write_lock(space);
                    240:        while (space->is_growing) {
                    241:                assert_wait((event_t) space, THREAD_UNINT);
                    242:                is_write_unlock(space);
                    243:                thread_block((void (*)(void)) 0);
                    244:                is_write_lock(space);
                    245:        }
                    246: 
                    247:        /*
                    248:         *      Now we can futz with it since we have the write lock.
                    249:         */
                    250: #if    DIPC || MACH_KDB
                    251:        if (space == default_pager_space)
                    252:                default_pager_space = IS_NULL;
                    253: #endif /* DIPC || MACH_KDB */
                    254: 
                    255:        table = space->is_table;
                    256:        size = space->is_table_size;
                    257: 
                    258:        for (index = 0; index < size; index++) {
                    259:                ipc_entry_t entry = &table[index];
                    260:                mach_port_type_t type;
                    261: 
                    262:                type = IE_BITS_TYPE(entry->ie_bits);
                    263:                if (type != MACH_PORT_TYPE_NONE) {
                    264:                        mach_port_name_t name = MACH_PORT_MAKE(index,
                    265:                                                IE_BITS_GEN(entry->ie_bits));
                    266:                        ipc_right_destroy(space, name, entry);
                    267:                }
                    268:        }
                    269: 
                    270:        /*
                    271:         * JMM - Now the table is cleaned out.  We don't bother shrinking the
                    272:         * size of the table at this point, but we probably should if it is
                    273:         * really large.  Lets just clean up the splay tree.
                    274:         */
                    275:  start_splay:
                    276:        for (tentry = ipc_splay_traverse_start(&space->is_tree);
                    277:             tentry != ITE_NULL;
                    278:             tentry = ipc_splay_traverse_next(&space->is_tree, TRUE)) {
                    279:                int i;
                    280:                mach_port_type_t type;
                    281:                mach_port_name_t name = tentry->ite_name;
                    282: 
                    283:                type = IE_BITS_TYPE(tentry->ite_bits);
                    284:                /*
                    285:                 * If it is a real right, then destroy it.  This will have the
                    286:                 * side effect of removing it from the splay, so start over.
                    287:                 */
                    288:                if(type != MACH_PORT_TYPE_NONE) {
                    289:                        ipc_splay_traverse_finish(&space->is_tree);
                    290:                        ipc_right_destroy(space, name, &tentry->ite_entry);
                    291:                        goto start_splay;
                    292:                }
                    293:        }
                    294:        ipc_splay_traverse_finish(&space->is_tree);
                    295:        is_write_unlock(space);
                    296: }
                    297: 
                    298: 
                    299: /*
                    300:  *     Routine:        ipc_space_destroy
                    301:  *     Purpose:
                    302:  *             Marks the space as dead and cleans up the entries.
                    303:  *             Does nothing if the space is already dead.
                    304:  *     Conditions:
                    305:  *             Nothing locked.
                    306:  */
                    307: 
                    308: void
                    309: ipc_space_destroy(
                    310:        ipc_space_t     space)
                    311: {
                    312:        boolean_t active;
                    313:        ipc_tree_entry_t tentry;
                    314:        ipc_entry_t table;
                    315:        ipc_entry_num_t size;
                    316:        mach_port_index_t index;
                    317: 
                    318:        assert(space != IS_NULL);
                    319: 
                    320:        is_write_lock(space);
                    321:        active = space->is_active;
                    322:        space->is_active = FALSE;
                    323:        is_write_unlock(space);
                    324: 
                    325:        if (!active)
                    326:                return;
                    327: 
                    328: 
                    329:        /*
                    330:         *      If somebody is trying to grow the table,
                    331:         *      we must wait until they finish and figure
                    332:         *      out the space died.
                    333:         */
                    334:        is_read_lock(space);
                    335:        while (space->is_growing) {
                    336:                assert_wait((event_t) space, THREAD_UNINT);
                    337:                is_read_unlock(space);
                    338:                thread_block((void (*)(void)) 0);
                    339:                is_read_lock(space);
                    340:        }
                    341: 
                    342:        is_read_unlock(space);
                    343:        /*
                    344:         *      Now we can futz with it unlocked.
                    345:         */
                    346: #if    DIPC || MACH_KDB
                    347:        if (space == default_pager_space)
                    348:                default_pager_space = IS_NULL;
                    349: #endif /* DIPC || MACH_KDB */
                    350: 
                    351:        table = space->is_table;
                    352:        size = space->is_table_size;
                    353: 
                    354:        for (index = 0; index < size; index++) {
                    355:                ipc_entry_t entry = &table[index];
                    356:                mach_port_type_t type;
                    357: 
                    358:                type = IE_BITS_TYPE(entry->ie_bits);
                    359:                if (type != MACH_PORT_TYPE_NONE) {
                    360:                        mach_port_name_t name;
                    361: 
                    362:                        name = MACH_PORT_MAKE(index,
                    363:                                              IE_BITS_GEN(entry->ie_bits));
                    364:                        ipc_right_clean(space, name, entry);
                    365:                }
                    366:        }
                    367: 
                    368:        it_entries_free(space->is_table_next-1, table);
                    369:        space->is_table_size = 0;
                    370: 
                    371:        for (tentry = ipc_splay_traverse_start(&space->is_tree);
                    372:             tentry != ITE_NULL;
                    373:             tentry = ipc_splay_traverse_next(&space->is_tree, TRUE)) {
                    374:                mach_port_type_t type;
                    375:                mach_port_name_t name = tentry->ite_name;
                    376: 
                    377:                type = IE_BITS_TYPE(tentry->ite_bits);
                    378:                assert(type != MACH_PORT_TYPE_NONE);
                    379: 
                    380:                ipc_right_clean(space, name, &tentry->ite_entry);
                    381: 
                    382:                if(type == MACH_PORT_TYPE_SEND)
                    383:                        ipc_hash_global_delete(space, tentry->ite_object,
                    384:                                               name, tentry);
                    385:        }
                    386:        ipc_splay_traverse_finish(&space->is_tree);
                    387: 
                    388:        /*
                    389:         *      Because the space is now dead,
                    390:         *      we must release the "active" reference for it.
                    391:         *      Our caller still has his reference.
                    392:         */
                    393:        is_release(space);
                    394: }

unix.superglobalmegacorp.com

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