Annotation of OSKit-Mach/ipc/ipc_marequest.c, revision 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.