Annotation of Gnu-Mach/ipc/ipc_marequest.c, revision 1.1.1.4

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