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