Annotation of kernel/ipc/ipc_marequest.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:  * 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:  *     File:   ipc/ipc_marequest.c
                     52:  *     Author: Rich Draves
                     53:  *     Date:   1989
                     54:  *
                     55:  *     Functions to handle msg-accepted requests.
                     56:  */
                     57: 
                     58: #import <mach/features.h>
                     59: 
                     60: #include <mach/message.h>
                     61: #include <mach/port.h>
                     62: #include <kern/lock.h>
                     63: #include <kern/mach_param.h>
                     64: #include <kern/kalloc.h>
                     65: #include <kern/zalloc.h>
                     66: #include <ipc/port.h>
                     67: #include <ipc/ipc_space.h>
                     68: #include <ipc/ipc_entry.h>
                     69: #include <ipc/ipc_port.h>
                     70: #include <ipc/ipc_right.h>
                     71: #include <ipc/ipc_marequest.h>
                     72: #include <ipc/ipc_notify.h>
                     73: 
                     74: #include <mach_ipc_debug.h>
                     75: #if    MACH_IPC_DEBUG
                     76: #include <mach/kern_return.h>
                     77: #include <mach_debug/hash_info.h>
                     78: #include <vm/vm_map.h>
                     79: #include <vm/vm_kern.h>
                     80: #include <vm/vm_user.h>
                     81: #endif
                     82: 
                     83: 
                     84: zone_t ipc_marequest_zone;
                     85: int ipc_marequest_max = IMAR_MAX;
                     86: 
                     87: #define        imar_alloc()            ((ipc_marequest_t) zalloc(ipc_marequest_zone))
                     88: #define        imar_free(imar)         zfree(ipc_marequest_zone, (vm_offset_t) (imar))
                     89: 
                     90: typedef unsigned int ipc_marequest_index_t;
                     91: 
                     92: ipc_marequest_index_t ipc_marequest_size;
                     93: ipc_marequest_index_t ipc_marequest_mask;
                     94: 
                     95: #define        IMAR_HASH(space, name)                                          \
                     96:                ((((ipc_marequest_index_t)((vm_offset_t)space) >> 4) +  \
                     97:                  MACH_PORT_INDEX(name) + MACH_PORT_NGEN(name)) &       \
                     98:                 ipc_marequest_mask)
                     99: 
                    100: typedef struct ipc_marequest_bucket {
                    101:        decl_simple_lock_data(, imarb_lock_data)
                    102:        ipc_marequest_t imarb_head;
                    103: } *ipc_marequest_bucket_t;
                    104: 
                    105: #define        IMARB_NULL      ((ipc_marequest_bucket_t) 0)
                    106: 
                    107: #define        imarb_lock_init(imarb)  simple_lock_init(&(imarb)->imarb_lock_data)
                    108: #define        imarb_lock(imarb)       simple_lock(&(imarb)->imarb_lock_data)
                    109: #define        imarb_unlock(imarb)     simple_unlock(&(imarb)->imarb_lock_data)
                    110: 
                    111: ipc_marequest_bucket_t ipc_marequest_table;
                    112: 
                    113: 
                    114: 
                    115: /*
                    116:  *     Routine:        ipc_marequest_init
                    117:  *     Purpose:
                    118:  *             Initialize the msg-accepted request module.
                    119:  */
                    120: 
                    121: void
                    122: ipc_marequest_init()
                    123: {
                    124:        ipc_marequest_index_t i;
                    125: 
                    126:        /* if not configured, initialize ipc_marequest_size */
                    127: 
                    128:        if (ipc_marequest_size == 0) {
                    129:                ipc_marequest_size = ipc_marequest_max >> 8;
                    130:                if (ipc_marequest_size < 16)
                    131:                        ipc_marequest_size = 16;
                    132:        }
                    133: 
                    134:        /* make sure it is a power of two */
                    135: 
                    136:        ipc_marequest_mask = ipc_marequest_size - 1;
                    137:        if ((ipc_marequest_size & ipc_marequest_mask) != 0) {
                    138:                unsigned int bit;
                    139: 
                    140:                /* round up to closest power of two */
                    141: 
                    142:                for (bit = 1;; bit <<= 1) {
                    143:                        ipc_marequest_mask |= bit;
                    144:                        ipc_marequest_size = ipc_marequest_mask + 1;
                    145: 
                    146:                        if ((ipc_marequest_size & ipc_marequest_mask) == 0)
                    147:                                break;
                    148:                }
                    149:        }
                    150: 
                    151:        /* allocate ipc_marequest_table */
                    152: 
                    153:        ipc_marequest_table = (ipc_marequest_bucket_t)
                    154:                kalloc((vm_size_t) (ipc_marequest_size *
                    155:                                    sizeof(struct ipc_marequest_bucket)));
                    156:        assert(ipc_marequest_table != IMARB_NULL);
                    157: 
                    158:        /* and initialize it */
                    159: 
                    160:        for (i = 0; i < ipc_marequest_size; i++) {
                    161:                ipc_marequest_bucket_t bucket;
                    162: 
                    163:                bucket = &ipc_marequest_table[i];
                    164:                imarb_lock_init(bucket);
                    165:                bucket->imarb_head = IMAR_NULL;
                    166:        }
                    167: 
                    168:        ipc_marequest_zone =
                    169:                zinit(sizeof(struct ipc_marequest),
                    170:                      ipc_marequest_max * sizeof(struct ipc_marequest),
                    171:                      sizeof(struct ipc_marequest),
                    172:                      FALSE, "ipc msg-accepted requests");
                    173:        /* make it exhaustible */
                    174:        zchange(ipc_marequest_zone, FALSE, FALSE, TRUE, FALSE);
                    175: }
                    176: 
                    177: /*
                    178:  *     Routine:        ipc_marequest_create
                    179:  *     Purpose:
                    180:  *             Create a msg-accepted request, because
                    181:  *             a sender is forcing a message with MACH_SEND_NOTIFY.
                    182:  *
                    183:  *             The "notify" argument should name a receive right
                    184:  *             that is used to create the send-once notify port.
                    185:  *
                    186:  *             [MACH_IPC_COMPAT] If "notify" is MACH_PORT_NULL,
                    187:  *             then an old-style msg-accepted request is created.
                    188:  *     Conditions:
                    189:  *             Nothing locked; refs held for space and port.
                    190:  *     Returns:
                    191:  *             MACH_MSG_SUCCESS        Msg-accepted request created.
                    192:  *             MACH_SEND_INVALID_NOTIFY        The space is dead.
                    193:  *             MACH_SEND_INVALID_NOTIFY        The notify port is bad.
                    194:  *             MACH_SEND_NOTIFY_IN_PROGRESS
                    195:  *                     This space has already forced a message to this port.
                    196:  *             MACH_SEND_NO_NOTIFY     Can't allocate a msg-accepted request.
                    197:  */
                    198: 
                    199: mach_msg_return_t
                    200: ipc_marequest_create(space, port, notify, marequestp)
                    201:        ipc_space_t space;
                    202:        ipc_port_t port;
                    203:        mach_port_t notify;
                    204:        ipc_marequest_t *marequestp;
                    205: {
                    206:        mach_port_t name;
                    207:        ipc_entry_t entry;
                    208:        ipc_port_t soright;
                    209:        ipc_marequest_t marequest;
                    210:        ipc_marequest_bucket_t bucket;
                    211: 
                    212: #if    !MACH_IPC_COMPAT
                    213:        assert(notify != MACH_PORT_NULL);
                    214: #endif !MACH_IPC_COMPAT
                    215: 
                    216:        marequest = imar_alloc();
                    217:        if (marequest == IMAR_NULL)
                    218:                return MACH_SEND_NO_NOTIFY;
                    219: 
                    220:        /*
                    221:         *      Delay creating the send-once right until
                    222:         *      we know there will be no errors.  Otherwise,
                    223:         *      we would have to worry about disposing of it
                    224:         *      when it turned out it wasn't needed.
                    225:         */
                    226: 
                    227:        is_write_lock(space);
                    228:        if (!space->is_active) {
                    229:                is_write_unlock(space);
                    230:                imar_free(marequest);
                    231:                return MACH_SEND_INVALID_NOTIFY;
                    232:        }
                    233: 
                    234:        if (ipc_right_reverse(space, (ipc_object_t) port, &name, &entry)) {
                    235:                ipc_entry_bits_t bits;
                    236: 
                    237:                /* port is locked and active */
                    238:                ip_unlock(port);
                    239:                bits = entry->ie_bits;
                    240: 
                    241:                assert(port == (ipc_port_t) entry->ie_object);
                    242:                assert(bits & MACH_PORT_TYPE_SEND_RECEIVE);
                    243: 
                    244:                if (bits & IE_BITS_MAREQUEST) {
                    245:                        is_write_unlock(space);
                    246:                        imar_free(marequest);
                    247:                        return MACH_SEND_NOTIFY_IN_PROGRESS;
                    248:                }
                    249: 
                    250: #if    MACH_IPC_COMPAT
                    251:                if (notify == MACH_PORT_NULL)
                    252:                        soright = IP_NULL;
                    253:                else
                    254: #endif MACH_IPC_COMPAT
                    255:                if ((soright = ipc_port_lookup_notify(space, notify))
                    256:                                                                == IP_NULL) {
                    257:                        is_write_unlock(space);
                    258:                        imar_free(marequest);
                    259:                        return MACH_SEND_INVALID_NOTIFY;
                    260:                }
                    261: 
                    262:                entry->ie_bits = bits | IE_BITS_MAREQUEST;
                    263: 
                    264:                is_reference(space);
                    265:                marequest->imar_space = space;
                    266:                marequest->imar_name = name;
                    267:                marequest->imar_soright = soright;
                    268: 
                    269:                bucket = &ipc_marequest_table[IMAR_HASH(space, name)];
                    270:                imarb_lock(bucket);
                    271: 
                    272:                marequest->imar_next = bucket->imarb_head;
                    273:                bucket->imarb_head = marequest;
                    274: 
                    275:                imarb_unlock(bucket);
                    276:        } else {
                    277: #if    MACH_IPC_COMPAT
                    278:                if (notify == MACH_PORT_NULL)
                    279:                        soright = IP_NULL;
                    280:                else
                    281: #endif MACH_IPC_COMPAT
                    282:                if ((soright = ipc_port_lookup_notify(space, notify))
                    283:                                                                == IP_NULL) {
                    284:                        is_write_unlock(space);
                    285:                        imar_free(marequest);
                    286:                        return MACH_SEND_INVALID_NOTIFY;
                    287:                }
                    288: 
                    289:                is_reference(space);
                    290:                marequest->imar_space = space;
                    291:                marequest->imar_name = MACH_PORT_NULL;
                    292:                marequest->imar_soright = soright;
                    293:        }
                    294: 
                    295:        is_write_unlock(space);
                    296:        *marequestp = marequest;
                    297:        return MACH_MSG_SUCCESS;
                    298: }
                    299: 
                    300: /*
                    301:  *     Routine:        ipc_marequest_cancel
                    302:  *     Purpose:
                    303:  *             Cancel a msg-accepted request, because
                    304:  *             the space's entry is being destroyed.
                    305:  *     Conditions:
                    306:  *             The space is write-locked and active.
                    307:  */
                    308: 
                    309: void
                    310: ipc_marequest_cancel(space, name)
                    311:        ipc_space_t space;
                    312:        mach_port_t name;
                    313: {
                    314:        ipc_marequest_bucket_t bucket;
                    315:        ipc_marequest_t marequest, *last;
                    316: 
                    317:        assert(space->is_active);
                    318: 
                    319:        bucket = &ipc_marequest_table[IMAR_HASH(space, name)];
                    320:        imarb_lock(bucket);
                    321: 
                    322:        for (last = &bucket->imarb_head;
                    323:             (marequest = *last) != IMAR_NULL;
                    324:             last = &marequest->imar_next)
                    325:                if ((marequest->imar_space == space) &&
                    326:                    (marequest->imar_name == name))
                    327:                        break;
                    328: 
                    329:        assert(marequest != IMAR_NULL);
                    330:        *last = marequest->imar_next;
                    331:        imarb_unlock(bucket);
                    332: 
                    333:        marequest->imar_name = MACH_PORT_NULL;
                    334: }
                    335: 
                    336: /*
                    337:  *     Routine:        ipc_marequest_rename
                    338:  *     Purpose:
                    339:  *             Rename a msg-accepted request, because the entry
                    340:  *             in the space is being renamed.
                    341:  *     Conditions:
                    342:  *             The space is write-locked and active.
                    343:  */
                    344: 
                    345: void
                    346: ipc_marequest_rename(space, old, new)
                    347:        ipc_space_t space;
                    348:        mach_port_t old, new;
                    349: {
                    350:        ipc_marequest_bucket_t bucket;
                    351:        ipc_marequest_t marequest, *last;
                    352: 
                    353:        assert(space->is_active);
                    354: 
                    355:        bucket = &ipc_marequest_table[IMAR_HASH(space, old)];
                    356:        imarb_lock(bucket);
                    357: 
                    358:        for (last = &bucket->imarb_head;
                    359:             (marequest = *last) != IMAR_NULL;
                    360:             last = &marequest->imar_next)
                    361:                if ((marequest->imar_space == space) &&
                    362:                    (marequest->imar_name == old))
                    363:                        break;
                    364: 
                    365:        assert(marequest != IMAR_NULL);
                    366:        *last = marequest->imar_next;
                    367:        imarb_unlock(bucket);
                    368: 
                    369:        marequest->imar_name = new;
                    370: 
                    371:        bucket = &ipc_marequest_table[IMAR_HASH(space, new)];
                    372:        imarb_lock(bucket);
                    373: 
                    374:        marequest->imar_next = bucket->imarb_head;
                    375:        bucket->imarb_head = marequest;
                    376: 
                    377:        imarb_unlock(bucket);
                    378: }
                    379: 
                    380: /*
                    381:  *     Routine:        ipc_marequest_destroy
                    382:  *     Purpose:
                    383:  *             Destroy a msg-accepted request, because
                    384:  *             the kernel message is being received/destroyed.
                    385:  *     Conditions:
                    386:  *             Nothing locked.
                    387:  */
                    388: 
                    389: void
                    390: ipc_marequest_destroy(marequest)
                    391:        ipc_marequest_t marequest;
                    392: {
                    393:        ipc_space_t space = marequest->imar_space;
                    394:        mach_port_t name;
                    395:        ipc_port_t soright;
                    396: #if    MACH_IPC_COMPAT
                    397:        ipc_port_t sright = IP_NULL;
                    398: #endif MACH_IPC_COMPAT
                    399: 
                    400:        is_write_lock(space);
                    401: 
                    402:        name = marequest->imar_name;
                    403:        soright = marequest->imar_soright;
                    404: 
                    405:        if (name != MACH_PORT_NULL) {
                    406:                ipc_marequest_bucket_t bucket;
                    407:                ipc_marequest_t this, *last;
                    408: 
                    409:                bucket = &ipc_marequest_table[IMAR_HASH(space, name)];
                    410:                imarb_lock(bucket);
                    411: 
                    412:                for (last = &bucket->imarb_head;
                    413:                     (this = *last) != IMAR_NULL;
                    414:                     last = &this->imar_next)
                    415:                        if ((this->imar_space == space) &&
                    416:                            (this->imar_name == name))
                    417:                                break;
                    418: 
                    419:                assert(this == marequest);
                    420:                *last = this->imar_next;
                    421:                imarb_unlock(bucket);
                    422: 
                    423:                if (space->is_active) {
                    424:                        ipc_entry_t entry;
                    425: 
                    426:                        entry = ipc_entry_lookup(space, name);
                    427:                        assert(entry != IE_NULL);
                    428:                        assert(entry->ie_bits & IE_BITS_MAREQUEST);
                    429:                        assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
                    430: 
                    431:                        entry->ie_bits &= ~IE_BITS_MAREQUEST;
                    432: 
                    433: #if    MACH_IPC_COMPAT
                    434:                        if (soright == IP_NULL)
                    435:                                sright = ipc_space_make_notify(space);
                    436: #endif MACH_IPC_COMPAT
                    437:                } else
                    438:                        name = MACH_PORT_NULL;
                    439:        }
                    440: 
                    441:        is_write_unlock(space);
                    442:        is_release(space);
                    443: 
                    444:        imar_free(marequest);
                    445: 
                    446: #if    MACH_IPC_COMPAT
                    447:        if (soright == IP_NULL) {
                    448:                if (IP_VALID(sright)) {
                    449:                        assert(name != MACH_PORT_NULL);
                    450:                        ipc_notify_msg_accepted_compat(sright, name);
                    451:                }
                    452: 
                    453:                return;
                    454:        }
                    455:        assert(sright == IP_NULL);
                    456: #endif MACH_IPC_COMPAT
                    457: 
                    458:        assert(soright != IP_NULL);
                    459:        panic("ipc_marequest_destroy");
                    460: }
                    461: 
                    462: #if    MACH_IPC_DEBUG
                    463: 
                    464: 
                    465: /*
                    466:  *     Routine:        ipc_marequest_info
                    467:  *     Purpose:
                    468:  *             Return information about the marequest hash table.
                    469:  *             Fills the buffer with as much information as possible
                    470:  *             and returns the desired size of the buffer.
                    471:  *     Conditions:
                    472:  *             Nothing locked.  The caller should provide
                    473:  *             possibly-pageable memory.
                    474:  */
                    475: 
                    476: unsigned int
                    477: ipc_marequest_info(maxp, info, count)
                    478:        unsigned int *maxp;
                    479:        hash_info_bucket_t *info;
                    480:        unsigned int count;
                    481: {
                    482:        ipc_marequest_index_t i;
                    483: 
                    484:        if (ipc_marequest_size < count)
                    485:                count = ipc_marequest_size;
                    486: 
                    487:        for (i = 0; i < count; i++) {
                    488:                ipc_marequest_bucket_t bucket = &ipc_marequest_table[i];
                    489:                unsigned int bucket_count = 0;
                    490:                ipc_marequest_t marequest;
                    491: 
                    492:                imarb_lock(bucket);
                    493:                for (marequest = bucket->imarb_head;
                    494:                     marequest != IMAR_NULL;
                    495:                     marequest = marequest->imar_next)
                    496:                        bucket_count++;
                    497:                imarb_unlock(bucket);
                    498: 
                    499:                /* don't touch pageable memory while holding locks */
                    500:                info[i].hib_count = bucket_count;
                    501:        }
                    502: 
                    503:        *maxp = ipc_marequest_max;
                    504:        return ipc_marequest_size;
                    505: }
                    506: 
                    507: #endif MACH_IPC_DEBUG

unix.superglobalmegacorp.com

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