Annotation of XNU/osfmk/kern/ipc_kobject.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * @OSF_COPYRIGHT@
        !            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:  */
        !            52: /*
        !            53:  *     File:   kern/ipc_kobject.c
        !            54:  *     Author: Rich Draves
        !            55:  *     Date:   1989
        !            56:  *
        !            57:  *     Functions for letting a port represent a kernel object.
        !            58:  */
        !            59: 
        !            60: #include <mach_debug.h>
        !            61: #include <mach_ipc_test.h>
        !            62: #include <mach_machine_routines.h>
        !            63: #include <norma_task.h>
        !            64: #include <dipc.h>
        !            65: #include <mach_rt.h>
        !            66: #include <platforms.h>
        !            67: #include <xk_proxy.h>
        !            68: 
        !            69: #include <kern/ast.h>
        !            70: #include <mach/port.h>
        !            71: #include <mach/kern_return.h>
        !            72: #include <mach/message.h>
        !            73: #include <mach/mig_errors.h>
        !            74: #include <mach/notify.h>
        !            75: #include <kern/etap_macros.h>
        !            76: #include <kern/ipc_mig.h>
        !            77: #include <kern/ipc_kobject.h>
        !            78: #include <kern/misc_protos.h>
        !            79: #include <ipc/ipc_object.h>
        !            80: #include <ipc/ipc_kmsg.h>
        !            81: #include <ipc/ipc_port.h>
        !            82: #include <kern/counters.h>
        !            83: 
        !            84: 
        !            85: void
        !            86:                 def_pager_hash_insert(
        !            87:                                ipc_port_t name_port);
        !            88: void             pager_mux_hash_insert(
        !            89:                                 ipc_port_t              port,
        !            90:                                 rpc_subsystem_t         rec);
        !            91: void             pager_mux_hash_delete(
        !            92:                                 ipc_port_t              port);
        !            93: rpc_subsystem_t  pager_mux_hash_lookup(
        !            94:                                 ipc_port_t              port);
        !            95: 
        !            96: 
        !            97: /*
        !            98:  *     Routine:        ipc_kobject_notify
        !            99:  *     Purpose:
        !           100:  *             Deliver notifications to kobjects that care about them.
        !           101:  */
        !           102: boolean_t
        !           103: ipc_kobject_notify(
        !           104:         mach_msg_header_t *request_header,
        !           105:         mach_msg_header_t *reply_header);
        !           106: 
        !           107: #include <mach/ndr.h>
        !           108: 
        !           109: typedef struct {
        !           110:         mach_msg_id_t num;
        !           111:         mig_routine_t routine;
        !           112:        int size;
        !           113: #if    MACH_COUNTERS
        !           114:        mach_counter_t callcount;
        !           115: #endif
        !           116: } mig_hash_t;
        !           117: 
        !           118: #define MAX_MIG_ENTRIES 1024
        !           119: #define MIG_HASH(x) (x)
        !           120: 
        !           121: #ifndef max
        !           122: #define max(a,b)        (((a) > (b)) ? (a) : (b))
        !           123: #endif /* max */
        !           124: 
        !           125: mig_hash_t mig_buckets[MAX_MIG_ENTRIES];
        !           126: int mig_table_max_displ;
        !           127: mach_msg_size_t mig_reply_size;
        !           128: 
        !           129: 
        !           130: #include <mach/mach_port_server.h>
        !           131: #include <mach/mach_host_server.h>
        !           132: #include <mach/host_priv_server.h>
        !           133: #include <mach/host_security_server.h>
        !           134: #include <mach/clock_server.h>
        !           135: #include <mach/clock_priv_server.h>
        !           136: #include <mach/bootstrap_server.h>
        !           137: #include <mach/ledger_server.h>
        !           138: #include <mach/lock_set_server.h>
        !           139: #include <mach/semaphore_server.h>
        !           140: #include <default_pager/default_pager_object_server.h>
        !           141: #include <mach/memory_object_server.h>
        !           142: #include <mach/memory_object_control_server.h>
        !           143: #include <mach/memory_object_default_server.h>
        !           144: #include <mach/memory_object_name_server.h>
        !           145: #include <mach/processor_server.h>
        !           146: #include <mach/processor_set_server.h>
        !           147: #include <mach/task_server.h>
        !           148: #include <mach/vm_task_server.h>
        !           149: #include <mach/thread_act_server.h>
        !           150: #include <device/device_server.h>
        !           151: 
        !           152: #if     MACH_MACHINE_ROUTINES
        !           153: #include <machine/machine_routines.h>
        !           154: #endif /* MACH_MACHINE_ROUTINES */
        !           155: #if    XK_PROXY
        !           156: #include <uk_xkern/xk_uproxy_server.h>
        !           157: #endif /* XK_PROXY */
        !           158: 
        !           159: 
        !           160: rpc_subsystem_t mig_e[] = {
        !           161:         (rpc_subsystem_t)&mach_port_subsystem,
        !           162:         (rpc_subsystem_t)&mach_host_subsystem,
        !           163:         (rpc_subsystem_t)&host_priv_subsystem,
        !           164:         (rpc_subsystem_t)&host_security_subsystem,
        !           165:         (rpc_subsystem_t)&clock_subsystem,
        !           166:         (rpc_subsystem_t)&clock_priv_subsystem,
        !           167:         (rpc_subsystem_t)&processor_subsystem,
        !           168:         (rpc_subsystem_t)&processor_set_subsystem,
        !           169:         (rpc_subsystem_t)&do_bootstrap_subsystem,
        !           170:         (rpc_subsystem_t)&is_iokit_subsystem,
        !           171:         (rpc_subsystem_t)&dp_memory_object_subsystem,
        !           172:         (rpc_subsystem_t)&dp_memory_object_default_subsystem,
        !           173:         (rpc_subsystem_t)&memory_object_name_subsystem,
        !           174:        (rpc_subsystem_t)&default_pager_object_subsystem,
        !           175:        (rpc_subsystem_t)&semaphore_subsystem,
        !           176:        (rpc_subsystem_t)&lock_set_subsystem,
        !           177:        (rpc_subsystem_t)&ledger_subsystem,
        !           178:        (rpc_subsystem_t)&task_subsystem,
        !           179:        (rpc_subsystem_t)&thread_act_subsystem,
        !           180:        (rpc_subsystem_t)&vm_task_subsystem,
        !           181:        
        !           182: #if     XK_PROXY
        !           183:         (rpc_subsystem_t)&do_uproxy_xk_uproxy_subsystem,
        !           184: #endif /* XK_PROXY */
        !           185: #if     MACH_MACHINE_ROUTINES
        !           186:         (rpc_subsystem_t)&MACHINE_SUBSYSTEM,
        !           187: #endif  /* MACH_MACHINE_ROUTINES */
        !           188: #if     MCMSG && iPSC860
        !           189:        (rpc_subsystem_t)&mcmsg_info_subsystem,
        !           190: #endif  /* MCMSG && iPSC860 */
        !           191: };
        !           192: 
        !           193: void
        !           194: mig_init(void)
        !           195: {
        !           196:     register unsigned int i, n = sizeof(mig_e)/sizeof(rpc_subsystem_t);
        !           197:     register unsigned int howmany;
        !           198:     register mach_msg_id_t j, pos, nentry, range;
        !           199:        
        !           200:     for (i = 0; i < n; i++) {
        !           201:        range = mig_e[i]->end - mig_e[i]->start;
        !           202:        if (!mig_e[i]->start || range < 0)
        !           203:            panic("the msgh_ids in mig_e[] aren't valid!");
        !           204:        mig_reply_size = max(mig_reply_size, mig_e[i]->maxsize);
        !           205: 
        !           206:        for  (j = 0; j < range; j++) {
        !           207:          if (mig_e[i]->routine[j].stub_routine) { 
        !           208:            /* Only put real entries in the table */
        !           209:            nentry = j + mig_e[i]->start;       
        !           210:            for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1;
        !           211:                 mig_buckets[pos].num;
        !           212:                 pos = ++pos % MAX_MIG_ENTRIES, howmany++) {
        !           213:                 if (mig_buckets[pos].num == nentry) {
        !           214:                        printf("message id = %d\n", nentry);
        !           215:                        panic("multiple entries with the same msgh_id");
        !           216:                 }
        !           217:                 if (howmany == MAX_MIG_ENTRIES)
        !           218:                       panic("the mig dispatch table is too small");
        !           219:            }
        !           220:                
        !           221:            mig_buckets[pos].num = nentry;
        !           222:            mig_buckets[pos].routine = mig_e[i]->routine[j].stub_routine;
        !           223:            if (mig_e[i]->routine[j].max_reply_msg)
        !           224:                    mig_buckets[pos].size = mig_e[i]->routine[j].max_reply_msg;
        !           225:            else
        !           226:                    mig_buckets[pos].size = mig_e[i]->maxsize;
        !           227: 
        !           228:            mig_table_max_displ = max(howmany, mig_table_max_displ);
        !           229:          }
        !           230:        }
        !           231:     }
        !           232: }
        !           233: 
        !           234: 
        !           235: #define PAGER_MUX_HASH_COUNT 127
        !           236: 
        !           237: 
        !           238: struct pager_mux_entry {
        !           239:        queue_chain_t   links;
        !           240:        ipc_port_t      name;
        !           241:        rpc_subsystem_t pager_object;
        !           242: };
        !           243: typedef struct pager_mux_entry *pager_mux_entry_t;
        !           244: 
        !           245: queue_head_t   pager_mux_hashtable[PAGER_MUX_HASH_COUNT];
        !           246: zone_t         pager_mux_hash_zone;
        !           247: 
        !           248: decl_mutex_data(,pager_mux_hash_lock)
        !           249: 
        !           250: #define        pager_mux_hash(name_port) \
        !           251:                (((natural_t)(name_port) & 0xffffff) % PAGER_MUX_HASH_COUNT)
        !           252: 
        !           253: 
        !           254: rpc_subsystem_t
        !           255: pager_mux_hash_lookup(
        !           256:        ipc_port_t      name_port)
        !           257: {
        !           258:        register queue_t        bucket;
        !           259:        register pager_mux_entry_t      entry;
        !           260:        register rpc_subsystem_t        pager_object;
        !           261: 
        !           262:        bucket = &pager_mux_hashtable[pager_mux_hash(name_port)];
        !           263: 
        !           264:        mutex_lock(&pager_mux_hash_lock);
        !           265:        for (entry = (pager_mux_entry_t)queue_first(bucket);
        !           266:             !queue_end(bucket, &entry->links);
        !           267:             entry = (pager_mux_entry_t)queue_next(&entry->links)) {
        !           268:            if (entry->name == name_port) {
        !           269:                pager_object = entry->pager_object;
        !           270:                /* don't need to reference the object, it can't disappear */
        !           271:                /* pager_mux_reference(pager_object); */
        !           272:                mutex_unlock(&pager_mux_hash_lock);
        !           273:                return (pager_object);
        !           274:            }
        !           275:        }
        !           276:        mutex_unlock(&pager_mux_hash_lock);
        !           277:        return (rpc_subsystem_t)0;
        !           278: }
        !           279: 
        !           280: 
        !           281: void
        !           282: pager_mux_hash_init(void)
        !           283: {
        !           284:        register int    i;
        !           285:        register vm_size_t      size;
        !           286: 
        !           287:        size = sizeof(struct pager_mux_entry);
        !           288:        pager_mux_hash_zone = zinit(
        !           289:                                size,
        !           290:                                size * 2000,
        !           291:                                PAGE_SIZE,
        !           292:                                "pager mux port hash");
        !           293:        for (i = 0; i < PAGER_MUX_HASH_COUNT; i++)
        !           294:            queue_init(&pager_mux_hashtable[i]);
        !           295:        mutex_init(&pager_mux_hash_lock, ETAP_IO_DEV_PAGEH);
        !           296: }
        !           297: 
        !           298: 
        !           299: void
        !           300: pager_mux_hash_insert(
        !           301:        ipc_port_t      name_port,
        !           302:        rpc_subsystem_t pager_object)
        !           303: {
        !           304:        register pager_mux_entry_t new_entry;
        !           305: 
        !           306:        new_entry = (pager_mux_entry_t) zalloc(pager_mux_hash_zone);
        !           307:        new_entry->links.prev = (queue_entry_t) 0;
        !           308:        new_entry->links.next = (queue_entry_t) 0;
        !           309:        new_entry->name = name_port;
        !           310:        new_entry->pager_object = pager_object;
        !           311: 
        !           312:        mutex_lock(&pager_mux_hash_lock);
        !           313:        queue_enter((&pager_mux_hashtable[pager_mux_hash(name_port)]),
        !           314:                        new_entry, pager_mux_entry_t, links);
        !           315:        mutex_unlock(&pager_mux_hash_lock);
        !           316: }
        !           317: 
        !           318: void
        !           319: pager_mux_hash_delete(
        !           320:        ipc_port_t      name_port)
        !           321: {
        !           322:        register queue_t        bucket;
        !           323:        register pager_mux_entry_t      entry;
        !           324: 
        !           325:        bucket = &pager_mux_hashtable[pager_mux_hash(name_port)];
        !           326: 
        !           327:        mutex_lock(&pager_mux_hash_lock);
        !           328:        for (entry = (pager_mux_entry_t)queue_first(bucket);
        !           329:             !queue_end(bucket, &entry->links);
        !           330:             entry = (pager_mux_entry_t)queue_next(&entry->links)) {
        !           331:            if (entry->name == name_port) {
        !           332:                queue_remove(bucket, entry, pager_mux_entry_t, links);
        !           333:                zfree(pager_mux_hash_zone, (vm_offset_t)entry);
        !           334:                break;
        !           335:            }
        !           336:        }
        !           337:        mutex_unlock(&pager_mux_hash_lock);
        !           338: }
        !           339: 
        !           340: 
        !           341: /*
        !           342:  *     Routine:        ipc_kobject_server
        !           343:  *     Purpose:
        !           344:  *             Handle a message sent to the kernel.
        !           345:  *             Generates a reply message.
        !           346:  *             Version for Untyped IPC.
        !           347:  *     Conditions:
        !           348:  *             Nothing locked.
        !           349:  */
        !           350: 
        !           351: ipc_kmsg_t
        !           352: ipc_kobject_server(
        !           353:        ipc_kmsg_t      request)
        !           354: {
        !           355:        mach_msg_size_t reply_size;
        !           356:        ipc_kmsg_t reply;
        !           357:        kern_return_t kr;
        !           358:        mig_routine_t routine;
        !           359:        ipc_port_t *destp;
        !           360:        mach_msg_format_0_trailer_t *trailer;
        !           361:        register mig_hash_t *ptr;
        !           362: #if    MACH_RT
        !           363:        boolean_t reply_rt;
        !           364: #endif /* MACH_RT */
        !           365:        unsigned int th;
        !           366: 
        !           367:        /* Only fetch current thread if ETAP is configured */
        !           368:        ETAP_DATA_LOAD(th, current_thread());
        !           369:         ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH,
        !           370:                         EVENT_BEGIN,
        !           371:                        ((thread_t) th),
        !           372:                         &request->ikm_header.msgh_id,
        !           373:                         sizeof(int));
        !           374:        /*
        !           375:          * Find out corresponding mig_hash entry if any
        !           376:          */
        !           377:        {
        !           378:            register int key = request->ikm_header.msgh_id;
        !           379:            register int i = MIG_HASH(key);
        !           380:            register int max_iter = mig_table_max_displ;
        !           381:        
        !           382:            do
        !           383:                ptr = &mig_buckets[i++ % MAX_MIG_ENTRIES];
        !           384:            while (key != ptr->num && ptr->num && --max_iter);
        !           385: 
        !           386:            if (!ptr->routine || key != ptr->num) {
        !           387:                ptr = (mig_hash_t *)0;
        !           388:                reply_size = mig_reply_size;
        !           389:            } else {
        !           390:                reply_size = ptr->size;
        !           391: #if    MACH_COUNTER
        !           392:                ptr->callcount++;
        !           393: #endif
        !           394:            }
        !           395:        }
        !           396: 
        !           397:        /* round up for ikm_cache; overhead is added by ikm_alloc */
        !           398:         if ((reply_size += MAX_TRAILER_SIZE) < IKM_SAVED_MSG_SIZE)
        !           399:                reply_size = IKM_SAVED_MSG_SIZE;
        !           400: 
        !           401: #if    MACH_RT
        !           402:        reply_rt =
        !           403:          IP_VALID((ipc_port_t)request->ikm_header.msgh_local_port) ?
        !           404:            IP_RT((ipc_port_t)request->ikm_header.msgh_local_port) :
        !           405:            FALSE;
        !           406:            
        !           407:        if (reply_rt)
        !           408:              reply = ikm_rtalloc(reply_size);
        !           409:        else
        !           410: #endif /* MACH_RT */
        !           411:              reply = ikm_alloc(reply_size);
        !           412: 
        !           413:        if (reply == IKM_NULL) {
        !           414:                printf("ipc_kobject_server: dropping request\n");
        !           415:                ipc_kmsg_destroy(request);
        !           416:                return IKM_NULL;
        !           417:        }
        !           418: 
        !           419:        ikm_init(reply, reply_size);
        !           420: #if    DIPC
        !           421:        reply->ikm_handle = HANDLE_NULL;
        !           422: #endif /* DIPC */
        !           423: 
        !           424:        /*
        !           425:         * Initialize reply message.
        !           426:         */
        !           427:        {
        !           428: #define        InP     ((mach_msg_header_t *) &request->ikm_header)
        !           429: #define        OutP    ((mig_reply_error_t *) &reply->ikm_header)
        !           430: 
        !           431:            OutP->NDR = NDR_record;
        !           432:            OutP->Head.msgh_size = sizeof(mig_reply_error_t);
        !           433: 
        !           434:            OutP->Head.msgh_bits =
        !           435:                MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
        !           436:            OutP->Head.msgh_remote_port = InP->msgh_local_port;
        !           437:            OutP->Head.msgh_local_port  = MACH_PORT_NULL;
        !           438:            OutP->Head.msgh_id = InP->msgh_id + 100;
        !           439: #if    MACH_RT
        !           440:            if (reply_rt)
        !           441:                  KMSG_MARK_RT(reply);
        !           442: #endif /* MACH_RT */
        !           443: #undef InP
        !           444: #undef OutP
        !           445:        }
        !           446: 
        !           447:        /*
        !           448:         * Find the routine to call, and call it
        !           449:         * to perform the kernel function
        !           450:         */
        !           451:        {
        !           452:            if (ptr) {  
        !           453:                (*ptr->routine)(&request->ikm_header, &reply->ikm_header);
        !           454:                kernel_task->messages_received++;
        !           455:            }
        !           456:            else {
        !           457:                if (!ipc_kobject_notify(&request->ikm_header, &reply->ikm_header)){
        !           458: #if    MACH_IPC_TEST
        !           459:                    printf("ipc_kobject_server: bogus kernel message, id=%d\n",
        !           460:                        request->ikm_header.msgh_id);
        !           461: #endif /* MACH_IPC_TEST */
        !           462:                    _MIG_MSGID_INVALID(request->ikm_header.msgh_id);
        !           463: 
        !           464:                    ((mig_reply_error_t *) &reply->ikm_header)->RetCode
        !           465:                        = MIG_BAD_ID;
        !           466:                }
        !           467:                else
        !           468:                  kernel_task->messages_received++;
        !           469:            }
        !           470:            kernel_task->messages_sent++;
        !           471:        }
        !           472: 
        !           473:        /*
        !           474:         *      Destroy destination. The following code differs from
        !           475:         *      ipc_object_destroy in that we release the send-once
        !           476:         *      right instead of generating a send-once notification
        !           477:         *      (which would bring us here again, creating a loop).
        !           478:         *      It also differs in that we only expect send or
        !           479:         *      send-once rights, never receive rights.
        !           480:         *
        !           481:         *      We set msgh_remote_port to IP_NULL so that the kmsg
        !           482:         *      destroy routines don't try to destroy the port twice.
        !           483:         */
        !           484:        destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port;
        !           485:        switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) {
        !           486:                case MACH_MSG_TYPE_PORT_SEND:
        !           487:                    ipc_port_release_send(*destp);
        !           488:                    break;
        !           489:                
        !           490:                case MACH_MSG_TYPE_PORT_SEND_ONCE:
        !           491:                    ipc_port_release_sonce(*destp);
        !           492:                    break;
        !           493:                
        !           494:                default:
        !           495:                    panic("ipc_object_destroy: strange destination rights");
        !           496:        }
        !           497:        *destp = IP_NULL;
        !           498: 
        !           499:         if (!(reply->ikm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
        !           500:            ((mig_reply_error_t *) &reply->ikm_header)->RetCode != KERN_SUCCESS)
        !           501:                kr = ((mig_reply_error_t *) &reply->ikm_header)->RetCode;
        !           502:        else
        !           503:                kr = KERN_SUCCESS;
        !           504: 
        !           505:        if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
        !           506:                /*
        !           507:                 *      The server function is responsible for the contents
        !           508:                 *      of the message.  The reply port right is moved
        !           509:                 *      to the reply message, and we have deallocated
        !           510:                 *      the destination port right, so we just need
        !           511:                 *      to free the kmsg.
        !           512:                 */
        !           513: 
        !           514:                /*
        !           515:                 * Like ipc_kmsg_put, but without the copyout.  Also,
        !           516:                 * messages to the kernel will never have been allocated
        !           517:                 * from the rt_zone.
        !           518:                 */
        !           519: 
        !           520:                ikm_check_initialized(request, request->ikm_size);
        !           521:                if (request->ikm_size != IKM_SAVED_KMSG_SIZE ||
        !           522:                    !ikm_cache_put (request)) {
        !           523:                        ikm_free(request);
        !           524:                }
        !           525:        } else {
        !           526:                /*
        !           527:                 *      The message contents of the request are intact.
        !           528:                 *      Destroy everthing except the reply port right,
        !           529:                 *      which is needed in the reply message.
        !           530:                 */
        !           531: 
        !           532:                request->ikm_header.msgh_local_port = MACH_PORT_NULL;
        !           533:                ipc_kmsg_destroy(request);
        !           534:        }
        !           535: 
        !           536:        if (kr == MIG_NO_REPLY) {
        !           537:                /*
        !           538:                 *      The server function will send a reply message
        !           539:                 *      using the reply port right, which it has saved.
        !           540:                 */
        !           541: 
        !           542:                ikm_free(reply);
        !           543: 
        !           544:                ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH,
        !           545:                                EVENT_END,
        !           546:                                ((thread_t) th),
        !           547:                                &request->ikm_header.msgh_id,
        !           548:                                sizeof(int));
        !           549: 
        !           550:                return IKM_NULL;
        !           551:        } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) {
        !           552:                /*
        !           553:                 *      Can't queue the reply message if the destination
        !           554:                 *      (the reply port) isn't valid.
        !           555:                 */
        !           556: 
        !           557:                ipc_kmsg_destroy(reply);
        !           558: 
        !           559:                ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH,
        !           560:                                EVENT_END,
        !           561:                                ((thread_t) th),
        !           562:                                &request->ikm_header.msgh_id,
        !           563:                                sizeof(int));
        !           564: 
        !           565:                return IKM_NULL;
        !           566:        }
        !           567: 
        !           568:        trailer = (mach_msg_format_0_trailer_t *)
        !           569:                ((vm_offset_t)&reply->ikm_header + (int)reply->ikm_header.msgh_size);                
        !           570:        trailer->msgh_sender = KERNEL_SECURITY_TOKEN;
        !           571:        trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
        !           572:        trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
        !           573: 
        !           574:         ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH,
        !           575:                         EVENT_END,
        !           576:                        ((thread_t) th),
        !           577:                         &request->ikm_header.msgh_id,
        !           578:                         sizeof(int));
        !           579: 
        !           580:        return reply;
        !           581: }
        !           582: 
        !           583: /*
        !           584:  *     Routine:        ipc_kobject_set
        !           585:  *     Purpose:
        !           586:  *             Make a port represent a kernel object of the given type.
        !           587:  *             The caller is responsible for handling refs for the
        !           588:  *             kernel object, if necessary.
        !           589:  *     Conditions:
        !           590:  *             Nothing locked.  The port must be active.
        !           591:  */
        !           592: 
        !           593: void
        !           594: ipc_kobject_set(
        !           595:        ipc_port_t              port,
        !           596:        ipc_kobject_t           kobject,
        !           597:        ipc_kobject_type_t      type)
        !           598: {
        !           599:        ip_lock(port);
        !           600:        assert(ip_active(port));
        !           601: #if    MACH_ASSERT
        !           602:        port->ip_spares[2] = (port->ip_bits & IO_BITS_KOTYPE);
        !           603: #endif /* MACH_ASSERT */
        !           604:        port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type;
        !           605:        port->ip_kobject = kobject;
        !           606:        ip_unlock(port);
        !           607: }
        !           608: 
        !           609: /*
        !           610:  *     Routine:        ipc_kobject_destroy
        !           611:  *     Purpose:
        !           612:  *             Release any kernel object resources associated
        !           613:  *             with the port, which is being destroyed.
        !           614:  *
        !           615:  *             This should only be needed when resources are
        !           616:  *             associated with a user's port.  In the normal case,
        !           617:  *             when the kernel is the receiver, the code calling
        !           618:  *             ipc_port_dealloc_kernel should clean up the resources.
        !           619:  *     Conditions:
        !           620:  *             The port is not locked, but it is dead.
        !           621:  */
        !           622: 
        !           623: void
        !           624: ipc_kobject_destroy(
        !           625:        ipc_port_t      port)
        !           626: {
        !           627:        switch (ip_kotype(port)) {
        !           628:                case IKOT_NAMED_ENTRY:
        !           629:                        mach_destroy_memory_entry(port);
        !           630:                        return;
        !           631:                case IKOT_UPL:
        !           632:                        mach_destroy_upl(port);
        !           633:                        return;
        !           634:                default:
        !           635:                        vm_object_destroy(port);
        !           636:        }
        !           637: }
        !           638: 
        !           639: 
        !           640: extern int vnode_pager_workaround;
        !           641: 
        !           642: boolean_t
        !           643: ipc_kobject_notify(
        !           644:        mach_msg_header_t *request_header,
        !           645:        mach_msg_header_t *reply_header)
        !           646: {
        !           647:        ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port;
        !           648:        rpc_subsystem_t         paging_subsystem_object;
        !           649:        mach_port_seqno_t       seqno;
        !           650: 
        !           651:        ((mig_reply_error_t *) reply_header)->RetCode = MIG_NO_REPLY;
        !           652:        switch (request_header->msgh_id) {
        !           653:                case MACH_NOTIFY_NO_SENDERS:
        !           654:                   if(ip_kotype(port) == IKOT_NAMED_ENTRY) {
        !           655:                        ip_lock(port);
        !           656: 
        !           657:                        /*
        !           658:                         * Bring the sequence number and mscount in
        !           659:                         * line with ipc_port_destroy assertion.
        !           660:                         */
        !           661:                        port->ip_mscount = 0;
        !           662:                        port->ip_messages.imq_seqno = 0;
        !           663:                        ipc_port_destroy(port); /* releases lock */
        !           664:                        return TRUE;
        !           665:                   }
        !           666:                   paging_subsystem_object = pager_mux_hash_lookup(
        !           667:                                (ipc_port_t)request_header->msgh_remote_port);
        !           668:                   if(paging_subsystem_object == (rpc_subsystem_t)
        !           669:                                        &dp_memory_object_subsystem) {
        !           670:                      default_pager_no_senders(
        !           671:                         (ipc_port_t)request_header->msgh_remote_port, 
        !           672:                         seqno, 
        !           673:                         (mach_port_mscount_t) 
        !           674:                         ((mach_no_senders_notification_t *) 
        !           675:                         request_header)->not_count);
        !           676:                      (ipc_port_t)reply_header->msgh_remote_port
        !           677:                          = MACH_PORT_NULL;
        !           678:                      return TRUE;
        !           679:                   }
        !           680:                   if(paging_subsystem_object == (rpc_subsystem_t)
        !           681:                                        &vnode_pager_workaround) {
        !           682:                      vnode_pager_no_senders(
        !           683:                         (ipc_port_t)request_header->msgh_remote_port, 
        !           684:                         (mach_port_mscount_t) 
        !           685:                         ((mach_no_senders_notification_t *) 
        !           686:                         request_header)->not_count);
        !           687:                      (ipc_port_t)reply_header->msgh_remote_port
        !           688:                          = MACH_PORT_NULL;
        !           689:                      return TRUE;
        !           690:                   }
        !           691:                   break;
        !           692:                case MACH_NOTIFY_PORT_DELETED:
        !           693:                case MACH_NOTIFY_PORT_DESTROYED:
        !           694:                case MACH_NOTIFY_SEND_ONCE:
        !           695:                case MACH_NOTIFY_DEAD_NAME:
        !           696:                break;
        !           697: 
        !           698:                default:
        !           699:                return FALSE;
        !           700:        }
        !           701:        switch (ip_kotype(port)) {
        !           702: 
        !           703: #ifdef IOKIT
        !           704:                case IKOT_IOKIT_OBJECT:
        !           705:                case IKOT_IOKIT_CONNECT:
        !           706:                case IKOT_IOKIT_SPARE:
        !           707:                {
        !           708:                 extern boolean_t iokit_notify( mach_msg_header_t *msg);
        !           709: 
        !           710:                 return iokit_notify(request_header);
        !           711:                }
        !           712: #endif
        !           713:                default:
        !           714:                 return FALSE;
        !           715:         }
        !           716: }
        !           717: 
        !           718: 
        !           719: 
        !           720: #include <mach_kdb.h>
        !           721: #if    MACH_COUNTERS && MACH_KDB
        !           722: 
        !           723: #include <ddb/db_output.h>
        !           724: #include <ddb/db_sym.h>
        !           725: 
        !           726: #define printf  kdbprintf
        !           727: 
        !           728: extern void kobjserver_stats(void);
        !           729: extern void bucket_stats_print(mig_hash_t *bucket);
        !           730: 
        !           731: extern void kobjserver_stats_clear(void);
        !           732: 
        !           733: 
        !           734: void
        !           735: kobjserver_stats_clear(void)
        !           736: {
        !           737:        int i;
        !           738:        for (i = 0; i < MAX_MIG_ENTRIES; i++) {
        !           739:                mig_buckets[i].callcount = 0;
        !           740:        }
        !           741: }
        !           742: 
        !           743: void
        !           744: kobjserver_stats(void)
        !           745: {
        !           746:     register unsigned int i, n = sizeof(mig_e)/sizeof(rpc_subsystem_t);
        !           747:     register unsigned int howmany;
        !           748:     register mach_msg_id_t j, pos, nentry, range;
        !           749:        
        !           750:     db_printf("Kobject server call counts:\n");
        !           751:     for (i = 0; i < n; i++) {
        !           752:        db_printf("  ");
        !           753:        db_printsym((vm_offset_t)mig_e[i], DB_STGY_ANY);
        !           754:        db_printf(":\n");
        !           755:        range = mig_e[i]->end - mig_e[i]->start;
        !           756:        if (!mig_e[i]->start || range < 0) continue;
        !           757: 
        !           758:        for  (j = 0; j < range; j++) {
        !           759:            nentry = j + mig_e[i]->start;       
        !           760:            for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1;
        !           761:                 mig_buckets[pos].num;
        !           762:                 pos = ++pos % MAX_MIG_ENTRIES, howmany++) {
        !           763:                    if (mig_buckets[pos].num == nentry)
        !           764:                        bucket_stats_print(&mig_buckets[pos]);
        !           765:            }
        !           766:        }
        !           767:     }
        !           768: }
        !           769: 
        !           770: void
        !           771: bucket_stats_print(mig_hash_t *bucket)
        !           772: {
        !           773:        if (bucket->callcount) {
        !           774:                db_printf("    ");
        !           775:                db_printsym((vm_offset_t)bucket->routine, DB_STGY_ANY);
        !           776:                db_printf(" (%d):\t%d\n", bucket->num, bucket->callcount);
        !           777:        }
        !           778: }
        !           779: 
        !           780: 
        !           781: #endif /* MACH_COUNTERS && MACH_KDB */

unix.superglobalmegacorp.com

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