Annotation of XNU/osfmk/kern/ipc_kobject.c, revision 1.1.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.