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

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