Annotation of XNU/osfmk/ipc/mach_msg.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:   ipc/mach_msg.c
        !            54:  *     Author: Rich Draves
        !            55:  *     Date:   1989
        !            56:  *
        !            57:  *     Exported message traps.  See mach/message.h.
        !            58:  */
        !            59: 
        !            60: #include <cpus.h>
        !            61: #include <dipc.h>
        !            62: #include <mach_rt.h>
        !            63: 
        !            64: #include <mach/kern_return.h>
        !            65: #include <mach/port.h>
        !            66: #include <mach/message.h>
        !            67: #include <mach/mig_errors.h>
        !            68: #include <kern/assert.h>
        !            69: #include <kern/counters.h>
        !            70: #include <kern/cpu_number.h>
        !            71: #include <kern/task.h>
        !            72: #include <kern/thread.h>
        !            73: #include <kern/lock.h>
        !            74: #include <kern/sched_prim.h>
        !            75: #include <kern/exception.h>
        !            76: #include <kern/misc_protos.h>
        !            77: #include <vm/vm_map.h>
        !            78: #include <ipc/ipc_kmsg.h>
        !            79: #include <ipc/ipc_mqueue.h>
        !            80: #include <ipc/ipc_object.h>
        !            81: #include <ipc/ipc_notify.h>
        !            82: #include <ipc/ipc_port.h>
        !            83: #include <ipc/ipc_pset.h>
        !            84: #include <ipc/ipc_space.h>
        !            85: #include <ipc/ipc_entry.h>
        !            86: #include <kern/kalloc.h>
        !            87: #include <kern/thread_swap.h>
        !            88: #include <kern/processor.h>
        !            89: #include <kern/rtmalloc.h>
        !            90: 
        !            91: #include <kern/sf.h>
        !            92: #include <kern/mk_sp.h>  /* JMM - to support handoff hack */
        !            93: 
        !            94: 
        !            95: /*
        !            96:  * Forward declarations
        !            97:  */
        !            98: 
        !            99: mach_msg_return_t mach_msg_send(
        !           100:        mach_msg_header_t       *msg,
        !           101:        mach_msg_option_t       option,
        !           102:        mach_msg_size_t         send_size,
        !           103:        mach_msg_timeout_t      timeout,
        !           104:        mach_port_name_t        notify);
        !           105: 
        !           106: mach_msg_return_t mach_msg_receive(
        !           107:        mach_msg_header_t       *msg,
        !           108:        mach_msg_option_t       option,
        !           109:        mach_msg_size_t         rcv_size,
        !           110:        mach_port_name_t        rcv_name,
        !           111:        mach_msg_timeout_t      timeout,
        !           112:        mach_port_name_t        notify,
        !           113:        mach_msg_size_t         slist_size);
        !           114: 
        !           115: mach_msg_return_t msg_receive_error(
        !           116:        ipc_kmsg_t              kmsg,
        !           117:        mach_msg_header_t       *msg,
        !           118:        mach_msg_option_t       option,
        !           119:        mach_port_seqno_t       seqno,
        !           120:        ipc_space_t             space);
        !           121: 
        !           122: /* the size of each trailer has to be listed here for copyout purposes */
        !           123: mach_msg_trailer_size_t trailer_size[] = {
        !           124:           sizeof(mach_msg_trailer_t), 
        !           125:          sizeof(mach_msg_seqno_trailer_t),
        !           126:          sizeof(mach_msg_security_trailer_t) };
        !           127: 
        !           128: security_token_t KERNEL_SECURITY_TOKEN = KERNEL_SECURITY_TOKEN_VALUE;
        !           129: 
        !           130: mach_msg_format_0_trailer_t trailer_template = {
        !           131:        /* mach_msg_trailer_type_t */ MACH_MSG_TRAILER_FORMAT_0,
        !           132:        /* mach_msg_trailer_size_t */ MACH_MSG_TRAILER_MINIMUM_SIZE,
        !           133:         /* mach_port_seqno_t */       0,
        !           134:        /* security_token_t */        KERNEL_SECURITY_TOKEN_VALUE
        !           135: };
        !           136: 
        !           137: /*
        !           138:  *     Routine:        mach_msg_send
        !           139:  *     Purpose:
        !           140:  *             Send a message.
        !           141:  *     Conditions:
        !           142:  *             Nothing locked.
        !           143:  *     Returns:
        !           144:  *             MACH_MSG_SUCCESS        Sent the message.
        !           145:  *             MACH_SEND_MSG_TOO_SMALL Message smaller than a header.
        !           146:  *             MACH_SEND_NO_BUFFER     Couldn't allocate buffer.
        !           147:  *             MACH_SEND_INVALID_DATA  Couldn't copy message data.
        !           148:  *             MACH_SEND_INVALID_HEADER
        !           149:  *                     Illegal value in the message header bits.
        !           150:  *             MACH_SEND_INVALID_DEST  The space is dead.
        !           151:  *             MACH_SEND_INVALID_NOTIFY        Bad notify port.
        !           152:  *             MACH_SEND_INVALID_DEST  Can't copyin destination port.
        !           153:  *             MACH_SEND_INVALID_REPLY Can't copyin reply port.
        !           154:  *             MACH_SEND_TIMED_OUT     Timeout expired without delivery.
        !           155:  *             MACH_SEND_INTERRUPTED   Delivery interrupted.
        !           156:  *             MACH_SEND_NO_NOTIFY     Can't allocate a msg-accepted request.
        !           157:  *             MACH_SEND_WILL_NOTIFY   Msg-accepted notif. requested.
        !           158:  *             MACH_SEND_NOTIFY_IN_PROGRESS
        !           159:  *                     This space has already forced a message to this port.
        !           160:  */
        !           161: 
        !           162: mach_msg_return_t
        !           163: mach_msg_send(
        !           164:        mach_msg_header_t       *msg,
        !           165:        mach_msg_option_t       option,
        !           166:        mach_msg_size_t         send_size,
        !           167:        mach_msg_timeout_t      timeout,
        !           168:        mach_port_name_t        notify)
        !           169: {
        !           170:        ipc_space_t space = current_space();
        !           171:        vm_map_t map = current_map();
        !           172:        ipc_kmsg_t kmsg;
        !           173:        mach_msg_return_t mr;
        !           174: 
        !           175:        mr = ipc_kmsg_get(msg, send_size, &kmsg, space);
        !           176: 
        !           177:        if (mr != MACH_MSG_SUCCESS)
        !           178:                return mr;
        !           179: 
        !           180:        if (option & MACH_SEND_CANCEL) {
        !           181:                if (notify == MACH_PORT_NULL)
        !           182:                        mr = MACH_SEND_INVALID_NOTIFY;
        !           183:                else
        !           184:                        mr = ipc_kmsg_copyin(kmsg, space, map, notify);
        !           185:        } else
        !           186:                mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
        !           187:        if (mr != MACH_MSG_SUCCESS) {
        !           188:                ikm_free(kmsg);
        !           189:                return mr;
        !           190:        }
        !           191: 
        !           192:        mr = ipc_kmsg_send(kmsg, option & MACH_SEND_TIMEOUT, timeout);
        !           193: 
        !           194:        if (mr != MACH_MSG_SUCCESS) {
        !           195:            mr |= ipc_kmsg_copyout_pseudo(kmsg, space, map, MACH_MSG_BODY_NULL);
        !           196:            (void) ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
        !           197:        }
        !           198: 
        !           199:        return mr;
        !           200: }
        !           201: 
        !           202: #define FREE_SCATTER_LIST(s, l, rt)                    \
        !           203: MACRO_BEGIN                                            \
        !           204:        if((s) != MACH_MSG_BODY_NULL) {                 \
        !           205:                KFREE(((vm_offset_t)(s)), (l), rt);     \
        !           206:        }                                               \
        !           207: MACRO_END
        !           208: 
        !           209: /*
        !           210:  *     Routine:        mach_msg_receive
        !           211:  *     Purpose:
        !           212:  *             Receive a message.
        !           213:  *     Conditions:
        !           214:  *             Nothing locked.
        !           215:  *     Returns:
        !           216:  *             MACH_MSG_SUCCESS        Received a message.
        !           217:  *             MACH_RCV_INVALID_NAME   The name doesn't denote a right,
        !           218:  *                     or the denoted right is not receive or port set.
        !           219:  *             MACH_RCV_IN_SET         Receive right is a member of a set.
        !           220:  *             MACH_RCV_TOO_LARGE      Message wouldn't fit into buffer.
        !           221:  *             MACH_RCV_TIMED_OUT      Timeout expired without a message.
        !           222:  *             MACH_RCV_INTERRUPTED    Reception interrupted.
        !           223:  *             MACH_RCV_PORT_DIED      Port/set died while receiving.
        !           224:  *             MACH_RCV_PORT_CHANGED   Port moved into set while receiving.
        !           225:  *             MACH_RCV_INVALID_DATA   Couldn't copy to user buffer.
        !           226:  *             MACH_RCV_INVALID_NOTIFY Bad notify port.
        !           227:  *             MACH_RCV_HEADER_ERROR
        !           228:  */
        !           229: 
        !           230: mach_msg_return_t
        !           231: mach_msg_receive(
        !           232:        mach_msg_header_t       *msg,
        !           233:        mach_msg_option_t       option,
        !           234:        mach_msg_size_t         rcv_size,
        !           235:        mach_port_name_t        rcv_name,
        !           236:        mach_msg_timeout_t      timeout,
        !           237:        mach_port_name_t        notify,
        !           238:        mach_msg_size_t         slist_size)
        !           239: {
        !           240:        thread_t self = current_thread();
        !           241:        ipc_space_t space = current_space();
        !           242:        vm_map_t map = current_map();
        !           243:        ipc_object_t object;
        !           244:        ipc_mqueue_t mqueue;
        !           245:        ipc_kmsg_t kmsg;
        !           246:        mach_port_seqno_t seqno;
        !           247:        mach_msg_return_t mr;
        !           248:        mach_msg_body_t *slist;
        !           249:        mach_msg_format_0_trailer_t *trailer;
        !           250: #if    MACH_RT
        !           251:        boolean_t slist_rt;
        !           252: #endif /* MACH_RT */
        !           253: 
        !           254:        mr = ipc_mqueue_copyin(space, rcv_name, &mqueue, &object);
        !           255:        if (mr != MACH_MSG_SUCCESS) {
        !           256:                return mr;
        !           257:        }
        !           258:        /* hold ref for object; mqueue is locked */
        !           259: 
        !           260: #if    MACH_RT
        !           261:        /* NOTE: This only works for true ports, and not port sets */
        !           262:        slist_rt = ipc_object_is_rt(object);
        !           263: #endif /* MACH_RT */
        !           264: 
        !           265:        /*
        !           266:         * If MACH_RCV_OVERWRITE was specified, both receive_msg (msg)
        !           267:         * and receive_msg_size (slist_size) need to be non NULL.
        !           268:         */
        !           269:        if (option & MACH_RCV_OVERWRITE) {
        !           270:                if (slist_size < sizeof(mach_msg_base_t)) {
        !           271:                        ipc_object_release(object);
        !           272:                        return MACH_RCV_SCATTER_SMALL;
        !           273:                } else {
        !           274:                        slist_size -= sizeof(mach_msg_header_t);
        !           275:                        slist = (mach_msg_body_t *)KALLOC(slist_size, slist_rt);
        !           276:                        if (slist == MACH_MSG_BODY_NULL ||
        !           277:                            copyin((char *) (msg + 1), (char *)slist,
        !           278:                                        slist_size)) {
        !           279:                                ipc_object_release(object);
        !           280:                                return MACH_RCV_INVALID_DATA;
        !           281:                        }
        !           282:                        if ((slist->msgh_descriptor_count*
        !           283:                             sizeof(mach_msg_descriptor_t)
        !           284:                             + sizeof(mach_msg_size_t)) > slist_size) {
        !           285:                                FREE_SCATTER_LIST(slist, slist_size, slist_rt);
        !           286:                                ipc_object_release(object);
        !           287:                                return MACH_RCV_INVALID_TYPE;
        !           288:                        }
        !           289:                }
        !           290:        } else {
        !           291:                slist = MACH_MSG_BODY_NULL;
        !           292:        }
        !           293:        
        !           294:        self->ith_option = option;
        !           295:        self->ith_scatter_list = slist;
        !           296:        self->ith_scatter_list_size = slist_size;
        !           297: 
        !           298:        mr = ipc_mqueue_receive(mqueue, option, rcv_size,
        !           299:                                timeout, THREAD_ABORTSAFE,
        !           300:                                &kmsg, &seqno);
        !           301:        
        !           302:        ipc_object_release(object);
        !           303: 
        !           304:        if (mr != MACH_MSG_SUCCESS) {
        !           305: 
        !           306:          if (mr == MACH_RCV_TOO_LARGE || mr == MACH_RCV_SCATTER_SMALL) {
        !           307:            if (option & MACH_RCV_LARGE) {
        !           308:              /*
        !           309:               * We need to inform the user-level code that it needs more
        !           310:               * space.  The value for how much space was returned in the
        !           311:               * kmsg pointer instead of the message (which was left on the
        !           312:               * queue).
        !           313:               */
        !           314:              if (copyout((char *) &kmsg,
        !           315:                          (char *) &msg->msgh_size,
        !           316:                          sizeof(mach_msg_size_t)))
        !           317:                mr = MACH_RCV_INVALID_DATA;
        !           318:              return mr;
        !           319:            }
        !           320:                  
        !           321:            if (msg_receive_error(kmsg, msg, option, seqno, space)
        !           322:                == MACH_RCV_INVALID_DATA)
        !           323:              mr = MACH_RCV_INVALID_DATA;
        !           324:          }
        !           325: 
        !           326:          FREE_SCATTER_LIST(slist, slist_size, slist_rt);
        !           327:          return mr;
        !           328:        }
        !           329: 
        !           330:        trailer = (mach_msg_format_0_trailer_t *)
        !           331:                        ((vm_offset_t)&kmsg->ikm_header +
        !           332:                        round_msg(kmsg->ikm_header.msgh_size));
        !           333:        if (option & MACH_RCV_TRAILER_MASK) {
        !           334:                trailer->msgh_seqno = seqno;
        !           335:                trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(option);
        !           336:        }
        !           337: 
        !           338:        if (option & MACH_RCV_NOTIFY) {
        !           339:                if (notify == MACH_PORT_NULL)
        !           340:                        mr = MACH_RCV_INVALID_NOTIFY;
        !           341:                else
        !           342:                        mr = ipc_kmsg_copyout(kmsg, space, map, notify, slist);
        !           343:        } else {
        !           344:                mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL, slist);
        !           345:        }
        !           346:        if (mr != MACH_MSG_SUCCESS) {
        !           347:                if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
        !           348:                        if (ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size +
        !           349:                           trailer->msgh_trailer_size) == MACH_RCV_INVALID_DATA)
        !           350:                                mr = MACH_RCV_INVALID_DATA;
        !           351:                } 
        !           352:                else {
        !           353:                        if (msg_receive_error(kmsg, msg, option, seqno, space) 
        !           354:                                                == MACH_RCV_INVALID_DATA)
        !           355:                                mr = MACH_RCV_INVALID_DATA;
        !           356:                }
        !           357: 
        !           358:                FREE_SCATTER_LIST(slist, slist_size, slist_rt);
        !           359:                return mr;
        !           360:        }
        !           361:        mr = ipc_kmsg_put(msg, kmsg, 
        !           362:                kmsg->ikm_header.msgh_size + trailer->msgh_trailer_size);
        !           363:        FREE_SCATTER_LIST(slist, slist_size, slist_rt);
        !           364: 
        !           365:        return mr;
        !           366: }
        !           367: 
        !           368: 
        !           369: /*
        !           370:  * Toggle this to compile the hotpath in/out
        !           371:  * If compiled in, the run-time toggle "enable_hotpath" below
        !           372:  * eases testing & debugging
        !           373:  */
        !           374: #define ENABLE_HOTPATH 1   /* Hacked on for now */
        !           375: 
        !           376: #ifndef ENABLE_HOTPATH
        !           377: #if    NCPUS == 1 && !MACH_RT
        !           378: #define ENABLE_HOTPATH 1
        !           379: #else  /* NCPUS == 1 && !MACH_RT */
        !           380: #define ENABLE_HOTPATH 0
        !           381: #endif /* NCPUS == 1 && !MACH_RT */
        !           382: #endif
        !           383: 
        !           384: #if    ENABLE_HOTPATH
        !           385: /*
        !           386:  * These counters allow tracing of hotpath behavior under test loads.
        !           387:  * A couple key counters are unconditional (see below).
        !           388:  */
        !           389: #define        HOTPATH_DEBUG   0       /* Toggle to include lots of counters   */
        !           390: #if    HOTPATH_DEBUG
        !           391: #define HOT(expr)      expr
        !           392: 
        !           393: unsigned int c_mmot_FIRST = 0;                 /* Unused First Counter */
        !           394: unsigned int c_mmot_combined_S_R = 0;          /* hotpath candidates   */
        !           395: unsigned int c_mach_msg_trap_switch_fast = 0;  /* hotpath successes    */
        !           396: unsigned int c_mmot_ikm_cache_miss = 0;                /* Reasons to Fall Off: */
        !           397: unsigned int c_mmot_kernel_send = 0;           /*    kernel server     */
        !           398: unsigned int c_mmot_cold_000 = 0;              /*    see below ...     */
        !           399: unsigned int c_mmot_smallsendsize = 0;
        !           400: unsigned int c_mmot_oddsendsize = 0;
        !           401: unsigned int c_mmot_bigsendsize = 0;
        !           402: unsigned int c_mmot_copyinmsg_fail = 0;
        !           403: unsigned int c_mmot_g_slow_copyin3 = 0;
        !           404: unsigned int c_mmot_cold_006 = 0;
        !           405: unsigned int c_mmot_cold_007 = 0;
        !           406: unsigned int c_mmot_cold_008 = 0;
        !           407: unsigned int c_mmot_cold_009 = 0;
        !           408: unsigned int c_mmot_cold_010 = 0;
        !           409: unsigned int c_mmot_cold_012 = 0;
        !           410: unsigned int c_mmot_cold_013 = 0;
        !           411: unsigned int c_mmot_cold_014 = 0;
        !           412: unsigned int c_mmot_cold_016 = 0;
        !           413: unsigned int c_mmot_cold_018 = 0;
        !           414: unsigned int c_mmot_cold_019 = 0;
        !           415: unsigned int c_mmot_cold_020 = 0;
        !           416: unsigned int c_mmot_cold_021 = 0;
        !           417: unsigned int c_mmot_cold_022 = 0;
        !           418: unsigned int c_mmot_cold_023 = 0;
        !           419: unsigned int c_mmot_cold_024 = 0;
        !           420: unsigned int c_mmot_cold_025 = 0;
        !           421: unsigned int c_mmot_cold_026 = 0;
        !           422: unsigned int c_mmot_cold_027 = 0;
        !           423: unsigned int c_mmot_hot_fSR_ok = 0;
        !           424: unsigned int c_mmot_cold_029 = 0;
        !           425: unsigned int c_mmot_cold_030 = 0;
        !           426: unsigned int c_mmot_cold_031 = 0;
        !           427: unsigned int c_mmot_cold_032 = 0;
        !           428: unsigned int c_mmot_cold_033 = 0;
        !           429: unsigned int c_mmot_bad_rcvr = 0;
        !           430: unsigned int c_mmot_rcvr_swapped = 0;
        !           431: unsigned int c_mmot_rcvr_locked = 0;
        !           432: unsigned int c_mmot_rcvr_tswapped = 0;
        !           433: unsigned int c_mmot_rcvr_freed = 0;
        !           434: unsigned int c_mmot_g_slow_copyout6 = 0;
        !           435: unsigned int c_mmot_g_slow_copyout5 = 0;
        !           436: unsigned int c_mmot_cold_037 = 0;
        !           437: unsigned int c_mmot_cold_038 = 0;
        !           438: unsigned int c_mmot_cold_039 = 0;
        !           439: unsigned int c_mmot_g_slow_copyout4 = 0;
        !           440: unsigned int c_mmot_g_slow_copyout3 = 0;
        !           441: unsigned int c_mmot_hot_ok1 = 0;
        !           442: unsigned int c_mmot_hot_ok2 = 0;
        !           443: unsigned int c_mmot_hot_ok3 = 0;
        !           444: unsigned int c_mmot_g_slow_copyout1 = 0;
        !           445: unsigned int c_mmot_g_slow_copyout2 = 0;
        !           446: unsigned int c_mmot_getback_fast_copyin = 0;
        !           447: unsigned int c_mmot_cold_048 = 0;
        !           448: unsigned int c_mmot_getback_FastSR = 0;
        !           449: unsigned int c_mmot_cold_050 = 0;
        !           450: unsigned int c_mmot_cold_051 = 0;
        !           451: unsigned int c_mmot_cold_052 = 0;
        !           452: unsigned int c_mmot_cold_053 = 0;
        !           453: unsigned int c_mmot_fastkernelreply = 0;
        !           454: unsigned int c_mmot_cold_055 = 0;
        !           455: unsigned int c_mmot_getback_fast_put = 0;
        !           456: unsigned int c_mmot_LAST = 0;                  /* End Marker - Unused */
        !           457: 
        !           458: void db_mmot_zero_counters(void);              /* forward; */
        !           459: void db_mmot_show_counters(void);              /* forward; */
        !           460: 
        !           461: void                   /* Call from the debugger to clear all counters */
        !           462: db_mmot_zero_counters(void)
        !           463: {
        !           464:        register unsigned int *ip = &c_mmot_FIRST;
        !           465:        while (ip <= &c_mmot_LAST)
        !           466:                *ip++ = 0;
        !           467: }
        !           468: 
        !           469: void                   /* Call from the debugger to show all counters */
        !           470: db_mmot_show_counters(void)
        !           471: {
        !           472: #define        xx(str) printf("%s: %d\n", # str, str);
        !           473: 
        !           474:        xx(c_mmot_combined_S_R);
        !           475:        xx(c_mach_msg_trap_switch_fast);
        !           476:        xx(c_mmot_ikm_cache_miss);      
        !           477:        xx(c_mmot_kernel_send);
        !           478:        xx(c_mmot_cold_000);
        !           479:        xx(c_mmot_smallsendsize);
        !           480:        xx(c_mmot_oddsendsize);
        !           481:        xx(c_mmot_bigsendsize);
        !           482:        xx(c_mmot_copyinmsg_fail);
        !           483:        xx(c_mmot_g_slow_copyin3);
        !           484:        xx(c_mmot_cold_006);
        !           485:        xx(c_mmot_cold_007);
        !           486:        xx(c_mmot_cold_008);
        !           487:        xx(c_mmot_cold_009);
        !           488:        xx(c_mmot_cold_010);
        !           489:        xx(c_mmot_cold_012);
        !           490:        xx(c_mmot_cold_013);
        !           491:        xx(c_mmot_cold_014);
        !           492:        xx(c_mmot_cold_016);
        !           493:        xx(c_mmot_cold_018);
        !           494:        xx(c_mmot_cold_019);
        !           495:        xx(c_mmot_cold_020);
        !           496:        xx(c_mmot_cold_021);
        !           497:        xx(c_mmot_cold_022);
        !           498:        xx(c_mmot_cold_023);
        !           499:        xx(c_mmot_cold_024);
        !           500:        xx(c_mmot_cold_025);
        !           501:        xx(c_mmot_cold_026);
        !           502:        xx(c_mmot_cold_027);
        !           503:        xx(c_mmot_hot_fSR_ok);
        !           504:        xx(c_mmot_cold_029);
        !           505:        xx(c_mmot_cold_030);
        !           506:        xx(c_mmot_cold_031);
        !           507:        xx(c_mmot_cold_032);
        !           508:        xx(c_mmot_cold_033);
        !           509:        xx(c_mmot_bad_rcvr);
        !           510:        xx(c_mmot_rcvr_swapped);
        !           511:        xx(c_mmot_rcvr_locked);
        !           512:        xx(c_mmot_rcvr_tswapped);
        !           513:        xx(c_mmot_rcvr_freed);
        !           514:        xx(c_mmot_g_slow_copyout6);
        !           515:        xx(c_mmot_g_slow_copyout5);
        !           516:        xx(c_mmot_cold_037);
        !           517:        xx(c_mmot_cold_038);
        !           518:        xx(c_mmot_cold_039);
        !           519:        xx(c_mmot_g_slow_copyout4);
        !           520:        xx(c_mmot_g_slow_copyout3);
        !           521:        xx(c_mmot_g_slow_copyout1);
        !           522:        xx(c_mmot_hot_ok3);
        !           523:        xx(c_mmot_hot_ok2);
        !           524:        xx(c_mmot_hot_ok1);
        !           525:        xx(c_mmot_g_slow_copyout2);
        !           526:        xx(c_mmot_getback_fast_copyin);
        !           527:        xx(c_mmot_cold_048);
        !           528:        xx(c_mmot_getback_FastSR);
        !           529:        xx(c_mmot_cold_050);
        !           530:        xx(c_mmot_cold_051);
        !           531:        xx(c_mmot_cold_052);
        !           532:        xx(c_mmot_cold_053);
        !           533:        xx(c_mmot_fastkernelreply);
        !           534:        xx(c_mmot_cold_055);
        !           535:        xx(c_mmot_getback_fast_put);
        !           536: 
        !           537: #undef xx
        !           538: }
        !           539: 
        !           540: #else  /* !HOTPATH_DEBUG */
        !           541: 
        !           542: /*
        !           543:  * Duplicate just these few so we can always do a quick sanity check
        !           544:  */
        !           545: unsigned int c_mmot_combined_S_R = 0;          /* hotpath candidates   */
        !           546: unsigned int c_mach_msg_trap_switch_fast = 0;  /* hotpath successes    */
        !           547: unsigned int c_mmot_kernel_send = 0;           /* kernel server calls  */
        !           548: #define HOT(expr)                              /* no optional counters */
        !           549: 
        !           550: #endif /* !HOTPATH_DEBUG */
        !           551: 
        !           552: boolean_t enable_hotpath = TRUE;       /* Patchable, just in case ...  */
        !           553: #endif /* HOTPATH_ENABLE */
        !           554: 
        !           555: /*
        !           556:  *     Routine:        mach_msg_overwrite_trap [mach trap]
        !           557:  *     Purpose:
        !           558:  *             Possibly send a message; possibly receive a message.
        !           559:  *     Conditions:
        !           560:  *             Nothing locked.
        !           561:  *     Returns:
        !           562:  *             All of mach_msg_send and mach_msg_receive error codes.
        !           563:  */
        !           564: 
        !           565: mach_msg_return_t
        !           566: mach_msg_overwrite_trap(
        !           567:        mach_msg_header_t       *msg,
        !           568:        mach_msg_option_t       option,
        !           569:        mach_msg_size_t         send_size,
        !           570:        mach_msg_size_t         rcv_size,
        !           571:        mach_port_name_t        rcv_name,
        !           572:        mach_msg_timeout_t      timeout,
        !           573:        mach_port_name_t        notify,
        !           574:        mach_msg_header_t       *rcv_msg,
        !           575:         mach_msg_size_t                scatter_list_size)
        !           576: {
        !           577:        register mach_msg_header_t *hdr;
        !           578:        mach_msg_return_t  mr = MACH_MSG_SUCCESS;
        !           579:        /* mask out some of the options before entering the hot path */
        !           580:        mach_msg_option_t  masked_option = 
        !           581:                option & ~(MACH_SEND_TRAILER|MACH_RCV_TRAILER_MASK|MACH_RCV_LARGE);
        !           582:        int i;
        !           583: 
        !           584: #if    ENABLE_HOTPATH
        !           585:        /* BEGINNING OF HOT PATH */
        !           586:        if ((masked_option == (MACH_SEND_MSG|MACH_RCV_MSG)) && enable_hotpath) {
        !           587:                register thread_t self = current_thread();
        !           588:                register mach_msg_format_0_trailer_t *trailer;
        !           589: 
        !           590:                ipc_space_t space = current_act()->task->itk_space;
        !           591:                ipc_kmsg_t kmsg;
        !           592:                register ipc_port_t dest_port;
        !           593:                ipc_object_t rcv_object;
        !           594:                register ipc_mqueue_t rcv_mqueue;
        !           595:                mach_msg_size_t reply_size;
        !           596:                ipc_kmsg_t rcv_kmsg;
        !           597: 
        !           598:                c_mmot_combined_S_R++;
        !           599:                self->ith_scatter_list = MACH_MSG_BODY_NULL;
        !           600: 
        !           601:                /*
        !           602:                 *      This case is divided into ten sections, each
        !           603:                 *      with a label.  There are five optimized
        !           604:                 *      sections and six unoptimized sections, which
        !           605:                 *      do the same thing but handle all possible
        !           606:                 *      cases and are slower.
        !           607:                 *
        !           608:                 *      The five sections for an RPC are
        !           609:                 *          1) Get request message into a buffer.
        !           610:                 *              (fast_get or slow_get)
        !           611:                 *          2) Copyin request message and rcv_name.
        !           612:                 *              (fast_copyin or slow_copyin)
        !           613:                 *          3) Enqueue request and dequeue reply.
        !           614:                 *              (fast_send_receive or
        !           615:                 *               slow_send and slow_receive)
        !           616:                 *          4) Copyout reply message.
        !           617:                 *              (fast_copyout or slow_copyout)
        !           618:                 *          5) Put reply message to user's buffer.
        !           619:                 *              (fast_put or slow_put)
        !           620:                 *
        !           621:                 *      Keep the locking hierarchy firmly in mind.
        !           622:                 *      (First spaces, then ports, then port sets,
        !           623:                 *      then message queues.)  Only a non-blocking
        !           624:                 *      attempt can be made to acquire locks out of
        !           625:                 *      order, or acquire two locks on the same level.
        !           626:                 *      Acquiring two locks on the same level will
        !           627:                 *      fail if the objects are really the same,
        !           628:                 *      unless simple locking is disabled.  This is OK,
        !           629:                 *      because then the extra unlock does nothing.
        !           630:                 *
        !           631:                 *      There are two major reasons these RPCs can't use
        !           632:                 *      ipc_thread_switch, and use slow_send/slow_receive:
        !           633:                 *              1) Kernel RPCs.
        !           634:                 *              2) Servers fall behind clients, so
        !           635:                 *              client doesn't find a blocked server thread and
        !           636:                 *              server finds waiting messages and can't block.
        !           637:                 */
        !           638: 
        !           639:            fast_get:
        !           640:                /*
        !           641:                 *      optimized ipc_kmsg_get
        !           642:                 *
        !           643:                 *      No locks, references, or messages held.
        !           644:                 *      We must clear ikm_cache before copyinmsg.
        !           645:                 */
        !           646: 
        !           647:                if ((send_size < sizeof(mach_msg_header_t)) ||
        !           648:                    (send_size & 3) ||
        !           649:                    (send_size > (IKM_SAVED_MSG_SIZE - MAX_TRAILER_SIZE)) ||
        !           650:                    !ikm_cache_get(&kmsg)) {
        !           651: #if    HOTPATH_DEBUG
        !           652:                        if (send_size < sizeof(mach_msg_header_t)) {
        !           653:                            HOT(c_mmot_smallsendsize++);
        !           654:                        } else if (send_size & 3) {
        !           655:                            HOT(c_mmot_oddsendsize++);
        !           656:                        } else if (send_size >
        !           657:                                (IKM_SAVED_MSG_SIZE - MAX_TRAILER_SIZE)) {
        !           658:                            HOT(c_mmot_bigsendsize++);
        !           659:                        } else if (!kmsg) {
        !           660:                            HOT(c_mmot_ikm_cache_miss++);
        !           661:                        }
        !           662: #endif
        !           663:                        goto slow_get;
        !           664:                }
        !           665: 
        !           666:                ikm_check_initialized(kmsg, IKM_SAVED_KMSG_SIZE);
        !           667: 
        !           668:                hdr = &kmsg->ikm_header;
        !           669:                if (copyinmsg((char *) msg, (char *) hdr, send_size)) {
        !           670:                        if (kmsg->ikm_size != IKM_SAVED_KMSG_SIZE ||
        !           671:                            KMSG_IS_RT(kmsg) || !ikm_cache_put(kmsg))
        !           672:                                ikm_free(kmsg);
        !           673:                        HOT(c_mmot_copyinmsg_fail++);
        !           674:                        goto slow_get;
        !           675:                }
        !           676: 
        !           677:                hdr->msgh_size = send_size;
        !           678: 
        !           679:                /* naturally align the message before tacking on the trailer */
        !           680:                trailer = (mach_msg_format_0_trailer_t *) ((vm_offset_t) hdr +
        !           681:                                                   send_size);
        !           682:                bcopy((char *)&trailer_template, (char *)trailer,
        !           683:                      sizeof(trailer_template));
        !           684:                trailer->msgh_sender = current_act()->task->sec_token;
        !           685: 
        !           686:            fast_copyin:
        !           687:                /*
        !           688:                 *      optimized ipc_kmsg_copyin/ipc_mqueue_copyin
        !           689:                 *
        !           690:                 *      We have the request message data in kmsg.
        !           691:                 *      Must still do copyin, send, receive, etc.
        !           692:                 *
        !           693:                 *      If the message isn't simple, we can't combine
        !           694:                 *      ipc_kmsg_copyin_header and ipc_mqueue_copyin,
        !           695:                 *      because copyin of the message body might
        !           696:                 *      affect rcv_name.
        !           697:                 */
        !           698: 
        !           699:                switch (hdr->msgh_bits) {
        !           700:                    case MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
        !           701:                                        MACH_MSG_TYPE_MAKE_SEND_ONCE): {
        !           702:                        register ipc_entry_t table;
        !           703:                        register ipc_entry_num_t size;
        !           704:                        register ipc_port_t reply_port;
        !           705: 
        !           706:                        /* sending a request message */
        !           707: 
        !           708:                    {
        !           709:                        register mach_port_index_t index;
        !           710:                        register mach_port_gen_t gen;
        !           711: 
        !           712:                    {
        !           713:                        register mach_port_name_t reply_name =
        !           714:                                (mach_port_name_t)hdr->msgh_local_port;
        !           715: 
        !           716:                        if (reply_name != rcv_name) {
        !           717:                                HOT(c_mmot_g_slow_copyin3++);
        !           718:                                goto slow_copyin;
        !           719:                        }
        !           720: 
        !           721:                        /* optimized ipc_entry_lookup of reply_name */
        !           722: 
        !           723:                        index = MACH_PORT_INDEX(reply_name);
        !           724:                        gen = MACH_PORT_GEN(reply_name);
        !           725: 
        !           726:                        is_read_lock(space);
        !           727:                        assert(space->is_active);
        !           728: 
        !           729:                        size = space->is_table_size;
        !           730:                        table = space->is_table;
        !           731: 
        !           732:                    {
        !           733:                        register ipc_entry_t entry;
        !           734:                        register ipc_entry_bits_t bits;
        !           735: 
        !           736:                        if (index < size) {
        !           737:                                entry = &table[index];
        !           738:                                bits = entry->ie_bits;
        !           739:                                if (IE_BITS_GEN(bits) != gen ||
        !           740:                                    (bits & IE_BITS_COLLISION)) {
        !           741:                                        entry = IE_NULL;
        !           742:                                }
        !           743:                        } else {
        !           744:                                entry = IE_NULL;
        !           745:                        }
        !           746:                        if (entry == IE_NULL) {
        !           747:                                entry = ipc_entry_lookup(space, reply_name);
        !           748:                                if (entry == IE_NULL) {
        !           749:                                        HOT(c_mmot_cold_006++);
        !           750:                                        goto abort_request_copyin;
        !           751:                                }
        !           752:                                bits = entry->ie_bits;
        !           753:                        }
        !           754: 
        !           755:                        /* check type bit */
        !           756: 
        !           757:                        if (! (bits & MACH_PORT_TYPE_RECEIVE)) {
        !           758:                                HOT(c_mmot_cold_007++);
        !           759:                                goto abort_request_copyin;
        !           760:                        }
        !           761: 
        !           762:                        reply_port = (ipc_port_t) entry->ie_object;
        !           763:                        assert(reply_port != IP_NULL);
        !           764:                    }
        !           765:                    }
        !           766:                    }
        !           767: 
        !           768:                        /* optimized ipc_entry_lookup of dest_name */
        !           769: 
        !           770:                    {
        !           771:                        register mach_port_index_t index;
        !           772:                        register mach_port_gen_t gen;
        !           773: 
        !           774:                    {
        !           775:                        register mach_port_name_t dest_name =
        !           776:                                (mach_port_name_t)hdr->msgh_remote_port;
        !           777: 
        !           778:                        index = MACH_PORT_INDEX(dest_name);
        !           779:                        gen = MACH_PORT_GEN(dest_name);
        !           780: 
        !           781:                    {
        !           782:                        register ipc_entry_t entry;
        !           783:                        register ipc_entry_bits_t bits;
        !           784: 
        !           785:                        if (index < size) {
        !           786:                                entry = &table[index];
        !           787:                                bits = entry->ie_bits;
        !           788:                                if (IE_BITS_GEN(bits) != gen ||
        !           789:                                    (bits & IE_BITS_COLLISION)) {
        !           790:                                        entry = IE_NULL;
        !           791:                                }
        !           792:                        } else {
        !           793:                                entry = IE_NULL;
        !           794:                        }
        !           795:                        if (entry == IE_NULL) {
        !           796:                                entry = ipc_entry_lookup(space, dest_name);
        !           797:                                if (entry == IE_NULL) {
        !           798:                                        HOT(c_mmot_cold_008++);
        !           799:                                        goto abort_request_copyin;
        !           800:                                }
        !           801:                                bits = entry->ie_bits;
        !           802:                        }
        !           803: 
        !           804:                        /* check type bit */
        !           805: 
        !           806:                        if (! (bits & MACH_PORT_TYPE_SEND)) {
        !           807:                                HOT(c_mmot_cold_009++);
        !           808:                                goto abort_request_copyin;
        !           809:                        }
        !           810: 
        !           811:                        assert(IE_BITS_UREFS(bits) > 0);
        !           812: 
        !           813:                        dest_port = (ipc_port_t) entry->ie_object;
        !           814:                        assert(dest_port != IP_NULL);
        !           815:                    }
        !           816:                    }
        !           817:                    }
        !           818: 
        !           819:                        /*
        !           820:                         *      To do an atomic copyin, need simultaneous
        !           821:                         *      locks on both ports and the space.  If
        !           822:                         *      dest_port == reply_port, and simple locking is
        !           823:                         *      enabled, then we will abort.  Otherwise it's
        !           824:                         *      OK to unlock twice.
        !           825:                         */
        !           826: 
        !           827:                        ip_lock(dest_port);
        !           828:                        if (!ip_active(dest_port) ||
        !           829:                            !ip_lock_try(reply_port)) {
        !           830:                                ip_unlock(dest_port);
        !           831:                                HOT(c_mmot_cold_010++);
        !           832:                                goto abort_request_copyin;
        !           833:                        }
        !           834:                        is_read_unlock(space);
        !           835: 
        !           836:                        assert(dest_port->ip_srights > 0);
        !           837:                        dest_port->ip_srights++;
        !           838:                        ip_reference(dest_port);
        !           839: 
        !           840:                        assert(ip_active(reply_port));
        !           841:                        assert(reply_port->ip_receiver_name ==
        !           842:                               (mach_port_name_t)hdr->msgh_local_port);
        !           843:                        assert(reply_port->ip_receiver == space);
        !           844: 
        !           845:                        reply_port->ip_sorights++;
        !           846:                        ip_reference(reply_port);
        !           847: 
        !           848:                        hdr->msgh_bits =
        !           849:                                MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND,
        !           850:                                               MACH_MSG_TYPE_PORT_SEND_ONCE);
        !           851:                        hdr->msgh_remote_port = dest_port;
        !           852:                        hdr->msgh_local_port = reply_port;
        !           853: 
        !           854:                        /* make sure we can queue to the destination */
        !           855: 
        !           856:                        if (dest_port->ip_receiver == ipc_space_kernel) {
        !           857:                                /*
        !           858:                                 * The kernel server has a reference to
        !           859:                                 * the reply port, which it hands back
        !           860:                                 * to us in the reply message.  We do
        !           861:                                 * not need to keep another reference to
        !           862:                                 * it.
        !           863:                                 */
        !           864:                                ip_unlock(reply_port);
        !           865: 
        !           866:                                assert(ip_active(dest_port));
        !           867:                                dest_port->ip_messages.imq_seqno++;
        !           868:                                ip_unlock(dest_port);
        !           869:                                goto kernel_send;
        !           870:                        }
        !           871: 
        !           872:                        if (imq_full(&dest_port->ip_messages)) {
        !           873:                                HOT(c_mmot_cold_013++);
        !           874:                                goto abort_request_send_receive;
        !           875:                        }
        !           876: 
        !           877:                        /* optimized ipc_mqueue_copyin */
        !           878: 
        !           879:                        if (reply_port->ip_pset_count != 0) {
        !           880:                                HOT(c_mmot_cold_014++);
        !           881:                                goto abort_request_send_receive;
        !           882:                        }
        !           883: 
        !           884:                        rcv_object = (ipc_object_t) reply_port;
        !           885:                        io_reference(rcv_object);
        !           886:                        rcv_mqueue = &reply_port->ip_messages;
        !           887:                        imq_lock(rcv_mqueue);
        !           888:                        io_unlock(rcv_object);
        !           889:                        HOT(c_mmot_hot_fSR_ok++);
        !           890:                        goto fast_send_receive;
        !           891: 
        !           892:                    abort_request_copyin:
        !           893:                        is_read_unlock(space);
        !           894:                        goto slow_copyin;
        !           895: 
        !           896:                    abort_request_send_receive:
        !           897:                        ip_unlock(dest_port);
        !           898:                        ip_unlock(reply_port);
        !           899:                        goto slow_send;
        !           900:                    }
        !           901: 
        !           902:                    case MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0): {
        !           903:                        register ipc_entry_num_t size;
        !           904:                        register ipc_entry_t table;
        !           905: 
        !           906:                        /* sending a reply message */
        !           907: 
        !           908:                    {
        !           909:                        register mach_port_name_t reply_name =
        !           910:                                (mach_port_name_t)hdr->msgh_local_port;
        !           911: 
        !           912:                        if (reply_name != MACH_PORT_NULL) {
        !           913:                                HOT(c_mmot_cold_018++);
        !           914:                                goto slow_copyin;
        !           915:                        }
        !           916:                    }
        !           917: 
        !           918:                        is_write_lock(space);
        !           919:                        assert(space->is_active);
        !           920: 
        !           921:                        /* optimized ipc_entry_lookup */
        !           922: 
        !           923:                        size = space->is_table_size;
        !           924:                        table = space->is_table;
        !           925: 
        !           926:                    {
        !           927:                        register ipc_entry_t entry;
        !           928:                        register mach_port_gen_t gen;
        !           929:                        register mach_port_index_t index;
        !           930:                        ipc_table_index_t *requests;
        !           931: 
        !           932:                    {
        !           933:                        register mach_port_name_t dest_name =
        !           934:                                (mach_port_name_t)hdr->msgh_remote_port;
        !           935: 
        !           936:                        index = MACH_PORT_INDEX(dest_name);
        !           937:                        gen = MACH_PORT_GEN(dest_name);
        !           938:                    }
        !           939: 
        !           940:                        if (index >= size) {
        !           941:                                HOT(c_mmot_cold_019++);
        !           942:                                goto abort_reply_dest_copyin;
        !           943:                        }
        !           944: 
        !           945:                        entry = &table[index];
        !           946: 
        !           947:                        /* check generation, collision bit, and type bit */
        !           948: 
        !           949:                        if ((entry->ie_bits & (IE_BITS_GEN_MASK|
        !           950:                                               IE_BITS_COLLISION|
        !           951:                                               MACH_PORT_TYPE_SEND_ONCE)) !=
        !           952:                            (gen | MACH_PORT_TYPE_SEND_ONCE)) {
        !           953:                                HOT(c_mmot_cold_020++);
        !           954:                                goto abort_reply_dest_copyin;
        !           955:                        }
        !           956: 
        !           957:                        /* optimized ipc_right_copyin */
        !           958: 
        !           959:                        assert(IE_BITS_TYPE(entry->ie_bits) ==
        !           960:                                            MACH_PORT_TYPE_SEND_ONCE);
        !           961:                        assert(IE_BITS_UREFS(entry->ie_bits) == 1);
        !           962:                        
        !           963:                        if (entry->ie_request != 0) {
        !           964:                                HOT(c_mmot_cold_021++);
        !           965:                                goto abort_reply_dest_copyin;
        !           966:                        }
        !           967: 
        !           968:                        dest_port = (ipc_port_t) entry->ie_object;
        !           969:                        assert(dest_port != IP_NULL);
        !           970: 
        !           971:                        ip_lock(dest_port);
        !           972:                        if (!ip_active(dest_port)) {
        !           973:                                ip_unlock(dest_port);
        !           974:                                HOT(c_mmot_cold_022++);
        !           975:                                goto abort_reply_dest_copyin;
        !           976:                        }
        !           977: 
        !           978:                        assert(dest_port->ip_sorights > 0);
        !           979: 
        !           980:                        /* optimized ipc_entry_dealloc */
        !           981: 
        !           982:                 
        !           983:                        entry->ie_bits = gen;
        !           984:                        entry->ie_next = table->ie_next;
        !           985:                        table->ie_next = index;
        !           986:                        entry->ie_object = IO_NULL;
        !           987:                    }
        !           988: 
        !           989:                        hdr->msgh_bits =
        !           990:                                MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE,
        !           991:                                               0);
        !           992:                        hdr->msgh_remote_port = dest_port;
        !           993: 
        !           994:                        /* make sure we can queue to the destination */
        !           995: 
        !           996:                        assert(dest_port->ip_receiver != ipc_space_kernel);
        !           997: 
        !           998:                        /* optimized ipc_entry_lookup/ipc_mqueue_copyin */
        !           999: 
        !          1000:                    {
        !          1001:                        register ipc_entry_t entry;
        !          1002:                        register ipc_entry_bits_t bits;
        !          1003: 
        !          1004:                    {
        !          1005:                        register mach_port_index_t index;
        !          1006:                        register mach_port_gen_t gen;
        !          1007: 
        !          1008:                        index = MACH_PORT_INDEX(rcv_name);
        !          1009:                        gen = MACH_PORT_GEN(rcv_name);
        !          1010: 
        !          1011:                        if (index < size) {
        !          1012:                                entry = &table[index];
        !          1013:                                bits = entry->ie_bits;
        !          1014:                                if (IE_BITS_GEN(bits) != gen ||
        !          1015:                                    (bits & IE_BITS_COLLISION)) {
        !          1016:                                        entry = IE_NULL;
        !          1017:                                }
        !          1018:                        } else {
        !          1019:                                entry = IE_NULL;
        !          1020:                        }
        !          1021:                        if (entry == IE_NULL) {
        !          1022:                                entry = ipc_entry_lookup(space, rcv_name);
        !          1023:                                if (entry == IE_NULL) {
        !          1024:                                        HOT(c_mmot_cold_024++);
        !          1025:                                        goto abort_reply_rcv_copyin;
        !          1026:                                }
        !          1027:                                bits = entry->ie_bits;
        !          1028:                        }
        !          1029: 
        !          1030:                    }
        !          1031: 
        !          1032:                        /* check type bits; looking for receive or set */
        !          1033: 
        !          1034:                        if (bits & MACH_PORT_TYPE_PORT_SET) {
        !          1035:                                register ipc_pset_t rcv_pset;
        !          1036: 
        !          1037:                                rcv_pset = (ipc_pset_t) entry->ie_object;
        !          1038:                                assert(rcv_pset != IPS_NULL);
        !          1039: 
        !          1040:                                ips_lock(rcv_pset);
        !          1041:                                assert(ips_active(rcv_pset));
        !          1042: 
        !          1043:                                rcv_object = (ipc_object_t) rcv_pset;
        !          1044:                                rcv_mqueue = &rcv_pset->ips_messages;
        !          1045:                        } else if (bits & MACH_PORT_TYPE_RECEIVE) {
        !          1046:                                register ipc_port_t rcv_port;
        !          1047: 
        !          1048:                                rcv_port = (ipc_port_t) entry->ie_object;
        !          1049:                                assert(rcv_port != IP_NULL);
        !          1050: 
        !          1051:                                if (!ip_lock_try(rcv_port)) {
        !          1052:                                        HOT(c_mmot_cold_025++);
        !          1053:                                        goto abort_reply_rcv_copyin;
        !          1054:                                }
        !          1055:                                assert(ip_active(rcv_port));
        !          1056: 
        !          1057:                                if (rcv_port->ip_pset_count != 0) {
        !          1058:                                        ip_unlock(rcv_port);
        !          1059:                                        HOT(c_mmot_cold_026++);
        !          1060:                                        goto abort_reply_rcv_copyin;
        !          1061:                                }
        !          1062: 
        !          1063:                                rcv_object = (ipc_object_t) rcv_port;
        !          1064:                                rcv_mqueue = &rcv_port->ip_messages;
        !          1065:                        } else {
        !          1066:                                HOT(c_mmot_cold_027++);
        !          1067:                                goto abort_reply_rcv_copyin;
        !          1068:                        }
        !          1069:                    }
        !          1070: 
        !          1071:                        is_write_unlock(space);
        !          1072:                        io_reference(rcv_object);
        !          1073:                        imq_lock(rcv_mqueue);
        !          1074:                        io_unlock(rcv_object);
        !          1075:                        HOT(c_mmot_hot_fSR_ok++);
        !          1076:                        goto fast_send_receive;
        !          1077: 
        !          1078:                    abort_reply_dest_copyin:
        !          1079:                        is_write_unlock(space);
        !          1080:                        HOT(c_mmot_cold_029++);
        !          1081:                        goto slow_copyin;
        !          1082: 
        !          1083:                    abort_reply_rcv_copyin:
        !          1084:                        ip_unlock(dest_port);
        !          1085:                        is_write_unlock(space);
        !          1086:                        HOT(c_mmot_cold_030++);
        !          1087:                        goto slow_send;
        !          1088:                    }
        !          1089: 
        !          1090:                    default:
        !          1091:                        HOT(c_mmot_cold_031++);
        !          1092:                        goto slow_copyin;
        !          1093:                }
        !          1094:                /*NOTREACHED*/
        !          1095: 
        !          1096:            fast_send_receive:
        !          1097:                /*
        !          1098:                 *      optimized ipc_mqueue_send/ipc_mqueue_receive
        !          1099:                 *
        !          1100:                 *      Finished get/copyin of kmsg and copyin of rcv_name.
        !          1101:                 *      space is unlocked, dest_port is locked,
        !          1102:                 *      we can queue kmsg to dest_port,
        !          1103:                 *      rcv_mqueue is locked, rcv_object holds a ref,
        !          1104:                 *      if rcv_object is a port it isn't in a port set
        !          1105:                 */
        !          1106: 
        !          1107:                assert(ip_active(dest_port));
        !          1108:                assert(dest_port->ip_receiver != ipc_space_kernel);
        !          1109:                assert(!imq_full(&dest_port->ip_messages) ||
        !          1110:                       (MACH_MSGH_BITS_REMOTE(hdr->msgh_bits) ==
        !          1111:                                                MACH_MSG_TYPE_PORT_SEND_ONCE));
        !          1112:                assert((hdr->msgh_bits & MACH_MSGH_BITS_CIRCULAR) == 0);
        !          1113: 
        !          1114:            {
        !          1115:                register ipc_mqueue_t dest_mqueue;
        !          1116:                wait_queue_t waitq;
        !          1117:                thread_t receiver;
        !          1118:                spl_t s;
        !          1119: #if    THREAD_SWAPPER
        !          1120:                thread_act_t rcv_act;
        !          1121: #endif
        !          1122: 
        !          1123:                dest_mqueue = &dest_port->ip_messages;
        !          1124: 
        !          1125:                if (!imq_lock_try(dest_mqueue)) {
        !          1126:                    abort_send_receive:
        !          1127:                        ip_unlock(dest_port);
        !          1128:                        imq_unlock(rcv_mqueue);
        !          1129:                        ipc_object_release(rcv_object);
        !          1130:                        HOT(c_mmot_cold_032++);
        !          1131:                        goto slow_send;
        !          1132:                }
        !          1133:                if (ipc_kmsg_queue_first(&rcv_mqueue->imq_messages) != IKM_NULL) {
        !          1134:                        imq_unlock(dest_mqueue);
        !          1135:                        HOT(c_mmot_cold_033++);
        !          1136:                        goto abort_send_receive;
        !          1137:                }
        !          1138: 
        !          1139:                waitq = &dest_mqueue->imq_wait_queue;
        !          1140:                s = splsched();
        !          1141:                wait_queue_peek_locked(waitq, IPC_MQUEUE_RECEIVE, &receiver, &waitq);
        !          1142:                /* queue still locked, thread locked - but still on q */
        !          1143: 
        !          1144:                if (receiver == THREAD_NULL) {
        !          1145:                        splx(s);
        !          1146:                        imq_unlock(dest_mqueue);
        !          1147:                        HOT(c_mmot_cold_033++);
        !          1148:                        goto abort_send_receive;
        !          1149:                }
        !          1150: 
        !          1151:                assert(receiver->wait_queue == waitq);
        !          1152:                assert(receiver->wait_event == IPC_MQUEUE_RECEIVE);
        !          1153:                
        !          1154:                /*
        !          1155:                 * See if it is still running on another processor (trying to
        !          1156:                 * block itself).  If so, fall off.
        !          1157:                 *
        !          1158:                 * JMM - We have an opportunity here.  Since the thread is locked
        !          1159:                 * and we find it runnable, it must still be trying to get into
        !          1160:                 * thread_block on itself.  We could just "hand him the message"
        !          1161:                 * and let him go (thread_go_locked()) and then fall down into a
        !          1162:                 * slow receive for ourselves.  Only his RECEIVE_TOO_LARGE handling
        !          1163:                 * runs afoul of that.  Clean this up!
        !          1164:                 */
        !          1165:                if ((receiver->state & TH_RUN) != TH_WAIT) {
        !          1166:                        assert(NCPUS > 1);
        !          1167:                        HOT(c_mmot_cold_033++);
        !          1168:                fall_off:
        !          1169:                        thread_unlock(receiver);
        !          1170:                        if (waitq != &dest_mqueue->imq_wait_queue)
        !          1171:                                wait_queue_unlock(waitq);
        !          1172:                        splx(s);
        !          1173:                        imq_unlock(dest_mqueue);
        !          1174:                        goto abort_send_receive;
        !          1175:                }
        !          1176: 
        !          1177:                /*
        !          1178:                 * Check that the receiver can stay on the hot path.
        !          1179:                 */
        !          1180:                if ((send_size + REQUESTED_TRAILER_SIZE(receiver->ith_option)
        !          1181:                         > receiver->ith_msize) ||
        !          1182:                    (receiver->ith_option & MACH_RCV_NOTIFY) ||
        !          1183:                    (receiver->ith_scatter_list != MACH_MSG_BODY_NULL)) {
        !          1184:                        /*
        !          1185:                         *      The receiver can't accept the message.
        !          1186:                         */
        !          1187:                        HOT(c_mmot_bad_rcvr++);
        !          1188:                        goto fall_off;
        !          1189:                }
        !          1190: 
        !          1191: #if    THREAD_SWAPPER
        !          1192:                /*
        !          1193:                 * Receiver looks okay -- is it swapped in?
        !          1194:                 */
        !          1195:                rpc_lock(receiver);
        !          1196:                rcv_act = receiver->top_act;
        !          1197:                if (rcv_act->swap_state != TH_SW_IN &&
        !          1198:                        rcv_act->swap_state != TH_SW_UNSWAPPABLE) {
        !          1199:                        rpc_unlock(receiver);
        !          1200:                        HOT(c_mmot_rcvr_swapped++);
        !          1201:                        goto fall_off;
        !          1202:                }
        !          1203: 
        !          1204:                /*
        !          1205:                 * Make sure receiver stays swapped in (if we can).
        !          1206:                 */
        !          1207:                if (!act_lock_try(rcv_act)) {   /* out of order! */
        !          1208:                        rpc_unlock(receiver);
        !          1209:                        HOT(c_mmot_rcvr_locked++);
        !          1210:                        goto fall_off;
        !          1211:                }
        !          1212:                
        !          1213:                /*
        !          1214:                 * Check for task swapping in progress affecting
        !          1215:                 * receiver.  Since rcv_act is attached to a shuttle,
        !          1216:                 * its swap_state is covered by shuttle's thread_lock()
        !          1217:                 * (sigh).
        !          1218:                 */
        !          1219:                if ((rcv_act->swap_state != TH_SW_IN &&
        !          1220:                        rcv_act->swap_state != TH_SW_UNSWAPPABLE) ||
        !          1221:                        rcv_act->ast & AST_SWAPOUT) {
        !          1222:                        act_unlock(rcv_act);
        !          1223:                        rpc_unlock(receiver);
        !          1224:                        HOT(c_mmot_rcvr_tswapped++);
        !          1225:                        goto fall_off;
        !          1226:                }
        !          1227: 
        !          1228:                /*
        !          1229:                 * We don't need to make receiver unswappable here -- holding
        !          1230:                 * act_lock() of rcv_act is sufficient to prevent either thread
        !          1231:                 * or task swapping from changing its state (see swapout_scan(),
        !          1232:                 * task_swapout()).  Don't release lock till receiver's state
        !          1233:                 * is consistent.  Its task may then be marked for swapout,
        !          1234:                 * but that's life.
        !          1235:                 */
        !          1236:                rpc_unlock(receiver);
        !          1237:                /*
        !          1238:                 * NB:  act_lock(rcv_act) still held
        !          1239:                 */
        !          1240: #endif /* THREAD_SWAPPER */
        !          1241: 
        !          1242:                /* At this point we are committed to do the "handoff". */
        !          1243:                c_mach_msg_trap_switch_fast++;
        !          1244: 
        !          1245:                /*
        !          1246:                 * JMM - Go ahead and pull the receiver from the runq.  If the
        !          1247:                 * runq wasn't the one for the mqueue, unlock it.
        !          1248:                 */
        !          1249:                wait_queue_pull_thread_locked(waitq,
        !          1250:                                              receiver,
        !          1251:                                              (waitq != &dest_mqueue->imq_wait_queue));
        !          1252: 
        !          1253:                /*
        !          1254:                 *      Store the kmsg and seqno where the receiver can pick it up.
        !          1255:                 */
        !          1256:                receiver->ith_state = MACH_MSG_SUCCESS;
        !          1257:                receiver->ith_kmsg = kmsg;
        !          1258:                receiver->ith_seqno = dest_mqueue->imq_seqno++;
        !          1259:                ipc_mqueue_release_msgcount(dest_mqueue);
        !          1260:                imq_unlock(dest_mqueue);
        !          1261:                ip_unlock(dest_port);
        !          1262: 
        !          1263: 
        !          1264:                /*
        !          1265:                 *      Put sender on reply port's queue.
        !          1266:                 *      Also save state that the sender of
        !          1267:                 *      our reply message needs to determine if it
        !          1268:                 *      can hand off directly back to us.
        !          1269:                 */
        !          1270: 
        !          1271:                self->ith_state = MACH_RCV_IN_PROGRESS;
        !          1272:                self->ith_msize = rcv_size;
        !          1273: 
        !          1274:                self->ith_option = option;
        !          1275:                self->ith_scatter_list = MACH_MSG_BODY_NULL;
        !          1276:                self->ith_scatter_list_size = scatter_list_size;
        !          1277: 
        !          1278:                waitq = &rcv_mqueue->imq_wait_queue;
        !          1279:                wait_queue_assert_wait_locked(waitq,
        !          1280:                                                                          IPC_MQUEUE_RECEIVE,
        !          1281:                                                                          THREAD_ABORTSAFE,
        !          1282:                                                                          TRUE); /* unlock? */
        !          1283:                /* rcv_mqueue is unlocked */
        !          1284: 
        !          1285:                current_task()->messages_sent++;
        !          1286: 
        !          1287:                /*
        !          1288:                 * Switch directly to receiving thread, and block
        !          1289:                 * this thread as though it had called ipc_mqueue_receive.
        !          1290:                 */
        !          1291:                {
        !          1292:                        extern unsigned sched_tick; /* kern/sched_prim.c */
        !          1293:        
        !          1294:                        /* from thread_block_reason() */
        !          1295:                        ast_off(AST_QUANTUM|AST_BLOCK|AST_URGENT);
        !          1296: 
        !          1297:                        /*
        !          1298:                         * JMM - Hacked in version of setrun scheduler op
        !          1299:                         * that doesn't try to put thread on a runq.  Safe
        !          1300:                         * for now because we only do this for sp_mk threads.
        !          1301:                         */
        !          1302:                        {
        !          1303:                                mk_sp_info_t sched_info;
        !          1304: 
        !          1305:                                assert(receiver->sp_info != SP_INFO_NULL);
        !          1306:                                sched_info = (mk_sp_info_t)receiver->sp_info;
        !          1307:                                sched_info->th_state = MK_SP_RUNNABLE;
        !          1308:                        }
        !          1309: 
        !          1310:                        assert((receiver->state & (TH_RUN|TH_WAIT)) == TH_WAIT);
        !          1311:                        assert(receiver != self);
        !          1312: 
        !          1313:                        receiver->state &= ~(TH_WAIT|TH_UNINT);
        !          1314: 
        !          1315:                        receiver->state |= TH_RUN;
        !          1316:                        receiver->wait_result = THREAD_AWAKENED;
        !          1317: #if    NCPUS > 1       /* from thread_invoke inline */
        !          1318:                        mp_disable_preemption();
        !          1319:                        receiver->last_processor = current_processor();
        !          1320:                        mp_enable_preemption();
        !          1321: #endif /* NCPUS > 1 */
        !          1322:                        thread_unlock(receiver);
        !          1323:                        assert( receiver != self );
        !          1324: #if    THREAD_SWAPPER
        !          1325:                        act_unlock(rcv_act);
        !          1326: #endif /* THREAD_SWAPPER */
        !          1327:        
        !          1328:                        /*
        !          1329:                         * Prepare self (the sender) to block.
        !          1330:                         */
        !          1331:                        thread_lock(self);
        !          1332: 
        !          1333:                        assert(!(self->state & TH_ABORT));
        !          1334:                        assert(self->wait_result = -1); /* for assertions */
        !          1335:                        assert(self->state & TH_RUN);
        !          1336:                        self->state |= TH_WAIT;
        !          1337:                        self->reason = 0;       /* inline thread_invoke */
        !          1338:                        thread_unlock(self);
        !          1339: 
        !          1340:                        /*
        !          1341:                         * Switch to the receiver now.
        !          1342:                         * Inlined: thread_invoke(self, receiver, 0);
        !          1343:                         */
        !          1344:                        {   
        !          1345:                            thread_t old_thread;
        !          1346:                            sched_policy_t *policy;
        !          1347:                            sf_return_t sfr;
        !          1348: 
        !          1349:                            mp_disable_preemption();
        !          1350:                            ast_context(receiver->top_act, cpu_number());
        !          1351:                            timer_switch(&receiver->system_timer);
        !          1352: 
        !          1353:                            current_task()->csw++;
        !          1354: 
        !          1355:                            policy = &sched_policy[self->policy];
        !          1356:                            sfr = policy->sp_ops.sp_thread_done(policy, self);
        !          1357:                            assert(sfr == SF_SUCCESS);
        !          1358: 
        !          1359:                            old_thread = switch_context(self, 0, receiver);
        !          1360: 
        !          1361:                            /* We're back! */
        !          1362:                            assert(current_thread() == self);
        !          1363:                            policy = &sched_policy[self->policy];
        !          1364:                            sfr = policy->sp_ops.sp_thread_begin(policy, self);
        !          1365:                            assert(sfr == SF_SUCCESS);
        !          1366: 
        !          1367:                            assert(old_thread != self);
        !          1368:                            thread_dispatch(old_thread);
        !          1369:                            enable_preemption();
        !          1370:                        }
        !          1371: 
        !          1372:                        splx(s);
        !          1373:                }
        !          1374: 
        !          1375:                switch (self->wait_result) {
        !          1376: 
        !          1377:                case THREAD_INTERRUPTED:
        !          1378:                        ipc_object_release(rcv_object); 
        !          1379:                        return MACH_RCV_INTERRUPTED;
        !          1380: 
        !          1381:                case THREAD_RESTART:
        !          1382:                        /* 
        !          1383:                         * something bad happened to the port/set.  If the port
        !          1384:                         * is still active, it must have just changed membership.
        !          1385:                         */
        !          1386:                        if (!io_active(rcv_object)) {
        !          1387:                                ipc_object_release(rcv_object);
        !          1388:                                return MACH_RCV_PORT_DIED;
        !          1389:                        } else {
        !          1390:                                ipc_object_release(rcv_object);
        !          1391:                                return MACH_RCV_PORT_CHANGED;
        !          1392:                        }
        !          1393: 
        !          1394:                case THREAD_AWAKENED:
        !          1395:                        ipc_object_release(rcv_object);
        !          1396:                        break;
        !          1397: 
        !          1398:                default:
        !          1399:                        panic("mmot_hotpath: bad wait result");
        !          1400:                }
        !          1401: 
        !          1402: 
        !          1403:                /*
        !          1404:                 * If we allowed for just a receive too large indication
        !          1405:                 * and we got one, copy out the size (stored in our kmsg
        !          1406:                 * pointer) instead of the message.  If we got the error,
        !          1407:                 * but didn't set the flag, we just need to try the copy
        !          1408:                 * out of the message and see where that takes us.
        !          1409:                 */
        !          1410:                if ((option & MACH_RCV_LARGE) && 
        !          1411:                    (self->ith_state == MACH_RCV_TOO_LARGE)) {
        !          1412:                        mach_msg_header_t *out_msg;
        !          1413: 
        !          1414:                        out_msg = (rcv_msg != MACH_MSG_NULL)?rcv_msg:msg;
        !          1415:                        if (copyout((char *) &self->ith_kmsg,
        !          1416:                                    (char *) &msg->msgh_size,
        !          1417:                                    sizeof(mach_msg_size_t)))
        !          1418:                                return MACH_RCV_INVALID_DATA;
        !          1419:                        return MACH_RCV_TOO_LARGE;
        !          1420:                }
        !          1421: 
        !          1422: 
        !          1423:                /*
        !          1424:                 * Restore state saved in sending thread's send path.
        !          1425:                 */
        !          1426:                kmsg = self->ith_kmsg;
        !          1427:                assert(kmsg != IKM_NULL);
        !          1428:                dest_port = (ipc_port_t)kmsg->ikm_header.msgh_remote_port;
        !          1429: 
        !          1430:                {
        !          1431:                        ip_lock(dest_port);
        !          1432:                        assert(dest_port->ip_messages.imq_msgcount > 0);
        !          1433:                        dest_port->ip_messages.imq_msgcount--;
        !          1434:                        ip_unlock(dest_port);
        !          1435:                }
        !          1436: 
        !          1437:                hdr = &kmsg->ikm_header;
        !          1438:                send_size = hdr->msgh_size;
        !          1439:                trailer = (mach_msg_format_0_trailer_t *) ((vm_offset_t) hdr +
        !          1440:                        round_msg(send_size));
        !          1441: 
        !          1442:                if (option & MACH_RCV_TRAILER_MASK) {
        !          1443:                        trailer->msgh_seqno = self->ith_seqno;  
        !          1444:                        trailer->msgh_trailer_size =
        !          1445:                                        REQUESTED_TRAILER_SIZE(option);
        !          1446:                }
        !          1447:            }
        !          1448: 
        !          1449:            fast_copyout:
        !          1450:                /*
        !          1451:                 *      Nothing locked and no references held, except
        !          1452:                 *      we have kmsg with msgh_seqno filled in.  Must
        !          1453:                 *      still check against rcv_size and do
        !          1454:                 *      ipc_kmsg_copyout/ipc_kmsg_put.
        !          1455:                 */
        !          1456: 
        !          1457:                reply_size = send_size + trailer->msgh_trailer_size;
        !          1458:                if (rcv_size < reply_size) {
        !          1459:                        HOT(c_mmot_g_slow_copyout6++);
        !          1460:                        goto slow_copyout;
        !          1461:                }
        !          1462: 
        !          1463:                /* optimized ipc_kmsg_copyout/ipc_kmsg_copyout_header */
        !          1464: 
        !          1465:                switch (hdr->msgh_bits) {
        !          1466:                    case MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND,
        !          1467:                                        MACH_MSG_TYPE_PORT_SEND_ONCE): {
        !          1468:                        ipc_port_t reply_port =
        !          1469:                                (ipc_port_t) hdr->msgh_local_port;
        !          1470:                        mach_port_name_t dest_name, reply_name;
        !          1471: 
        !          1472:                        /* receiving a request message */
        !          1473: 
        !          1474:                        if (!IP_VALID(reply_port)) {
        !          1475:                                HOT(c_mmot_g_slow_copyout5++);
        !          1476:                                goto slow_copyout;
        !          1477:                        }
        !          1478: 
        !          1479:                        is_write_lock(space);
        !          1480:                        assert(space->is_active);
        !          1481: 
        !          1482:                        /*
        !          1483:                         *      To do an atomic copyout, need simultaneous
        !          1484:                         *      locks on both ports and the space.  If
        !          1485:                         *      dest_port == reply_port, and simple locking is
        !          1486:                         *      enabled, then we will abort.  Otherwise it's
        !          1487:                         *      OK to unlock twice.
        !          1488:                         */
        !          1489: 
        !          1490:                        ip_lock(dest_port);
        !          1491:                        if (!ip_active(dest_port) ||
        !          1492:                            !ip_lock_try(reply_port)) {
        !          1493:                                HOT(c_mmot_cold_037++);
        !          1494:                                goto abort_request_copyout;
        !          1495:                        }
        !          1496: 
        !          1497:                        if (!ip_active(reply_port)) {
        !          1498:                                ip_unlock(reply_port);
        !          1499:                                HOT(c_mmot_cold_038++);
        !          1500:                                goto abort_request_copyout;
        !          1501:                        }
        !          1502: 
        !          1503:                        assert(reply_port->ip_sorights > 0);
        !          1504:                        ip_unlock(reply_port);
        !          1505: 
        !          1506:                    {
        !          1507:                        register ipc_entry_t table;
        !          1508:                        register ipc_entry_t entry;
        !          1509:                        register mach_port_index_t index;
        !          1510: 
        !          1511:                        /* optimized ipc_entry_get */
        !          1512: 
        !          1513:                        table = space->is_table;
        !          1514:                        index = table->ie_next;
        !          1515: 
        !          1516:                        if (index == 0) {
        !          1517:                                HOT(c_mmot_cold_039++);
        !          1518:                                goto abort_request_copyout;
        !          1519:                        }
        !          1520: 
        !          1521:                        entry = &table[index];
        !          1522:                        table->ie_next = entry->ie_next;
        !          1523:                        entry->ie_request = 0;
        !          1524: 
        !          1525:                    {
        !          1526:                        register mach_port_gen_t gen;
        !          1527: 
        !          1528:                        assert((entry->ie_bits &~ IE_BITS_GEN_MASK) == 0);
        !          1529:                        gen = IE_BITS_NEW_GEN(entry->ie_bits);
        !          1530: 
        !          1531:                        reply_name = MACH_PORT_MAKE(index, gen);
        !          1532: 
        !          1533:                        /* optimized ipc_right_copyout */
        !          1534: 
        !          1535:                        entry->ie_bits = gen | (MACH_PORT_TYPE_SEND_ONCE | 1);
        !          1536:                    }
        !          1537: 
        !          1538:                        assert(MACH_PORT_VALID(reply_name));
        !          1539:                        entry->ie_object = (ipc_object_t) reply_port;
        !          1540:                        is_write_unlock(space);
        !          1541:                    }
        !          1542: 
        !          1543:                        /* optimized ipc_object_copyout_dest */
        !          1544: 
        !          1545:                        assert(dest_port->ip_srights > 0);
        !          1546:                        ip_release(dest_port);
        !          1547: 
        !          1548:                        if (dest_port->ip_receiver == space)
        !          1549:                                dest_name = dest_port->ip_receiver_name;
        !          1550:                        else
        !          1551:                                dest_name = MACH_PORT_NULL;
        !          1552: 
        !          1553:                        if ((--dest_port->ip_srights == 0) &&
        !          1554:                            (dest_port->ip_nsrequest != IP_NULL)) {
        !          1555:                                ipc_port_t nsrequest;
        !          1556:                                mach_port_mscount_t mscount;
        !          1557: 
        !          1558:                                /* a rather rare case */
        !          1559: 
        !          1560:                                nsrequest = dest_port->ip_nsrequest;
        !          1561:                                mscount = dest_port->ip_mscount;
        !          1562:                                dest_port->ip_nsrequest = IP_NULL;
        !          1563:                                ip_unlock(dest_port);
        !          1564:                                ipc_notify_no_senders(nsrequest, mscount);
        !          1565:                        } else
        !          1566:                                ip_unlock(dest_port);
        !          1567: 
        !          1568:                        hdr->msgh_bits =
        !          1569:                                MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE,
        !          1570:                                               MACH_MSG_TYPE_PORT_SEND);
        !          1571:                        hdr->msgh_remote_port = (mach_port_t)reply_name;
        !          1572:                        hdr->msgh_local_port = (mach_port_t)dest_name;
        !          1573:                        HOT(c_mmot_hot_ok1++);
        !          1574:                        goto fast_put;
        !          1575: 
        !          1576:                    abort_request_copyout:
        !          1577:                        ip_unlock(dest_port);
        !          1578:                        is_write_unlock(space);
        !          1579:                        HOT(c_mmot_g_slow_copyout4++);
        !          1580:                        goto slow_copyout;
        !          1581:                    }
        !          1582: 
        !          1583:                    case MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0): {
        !          1584:                        register mach_port_name_t dest_name;
        !          1585: 
        !          1586:                        /* receiving a reply message */
        !          1587: 
        !          1588:                        ip_lock(dest_port);
        !          1589:                        if (!ip_active(dest_port)) {
        !          1590:                                ip_unlock(dest_port);
        !          1591:                                HOT(c_mmot_g_slow_copyout3++);
        !          1592:                                goto slow_copyout;
        !          1593:                        }
        !          1594: 
        !          1595:                        /* optimized ipc_object_copyout_dest */
        !          1596: 
        !          1597:                        assert(dest_port->ip_sorights > 0);
        !          1598: 
        !          1599:                        if (dest_port->ip_receiver == space) {
        !          1600:                                ip_release(dest_port);
        !          1601:                                dest_port->ip_sorights--;
        !          1602:                                dest_name = dest_port->ip_receiver_name;
        !          1603:                                ip_unlock(dest_port);
        !          1604:                        } else {
        !          1605:                                ip_unlock(dest_port);
        !          1606: 
        !          1607:                                ipc_notify_send_once(dest_port);
        !          1608:                                dest_name = MACH_PORT_NULL;
        !          1609:                        }
        !          1610: 
        !          1611:                        hdr->msgh_bits = MACH_MSGH_BITS(0,
        !          1612:                                               MACH_MSG_TYPE_PORT_SEND_ONCE);
        !          1613:                        hdr->msgh_remote_port = MACH_PORT_NULL;
        !          1614:                        hdr->msgh_local_port = (ipc_port_t)dest_name;
        !          1615:                        HOT(c_mmot_hot_ok2++);
        !          1616:                        goto fast_put;
        !          1617:                    }
        !          1618: 
        !          1619:                    case MACH_MSGH_BITS_COMPLEX|
        !          1620:                         MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0): {
        !          1621:                        register mach_port_name_t dest_name;
        !          1622: 
        !          1623:                        /* receiving a complex reply message */
        !          1624: 
        !          1625:                        ip_lock(dest_port);
        !          1626:                        if (!ip_active(dest_port)) {
        !          1627:                                ip_unlock(dest_port);
        !          1628:                                HOT(c_mmot_g_slow_copyout1++);
        !          1629:                                goto slow_copyout;
        !          1630:                        }
        !          1631: 
        !          1632:                        /* optimized ipc_object_copyout_dest */
        !          1633: 
        !          1634:                        assert(dest_port->ip_sorights > 0);
        !          1635: 
        !          1636:                        if (dest_port->ip_receiver == space) {
        !          1637:                                ip_release(dest_port);
        !          1638:                                dest_port->ip_sorights--;
        !          1639:                                dest_name = dest_port->ip_receiver_name;
        !          1640:                                ip_unlock(dest_port);
        !          1641:                        } else {
        !          1642:                                ip_unlock(dest_port);
        !          1643: 
        !          1644:                                ipc_notify_send_once(dest_port);
        !          1645:                                dest_name = MACH_PORT_NULL;
        !          1646:                        }
        !          1647: 
        !          1648:                        hdr->msgh_bits =
        !          1649:                                MACH_MSGH_BITS_COMPLEX |
        !          1650:                                MACH_MSGH_BITS(0, MACH_MSG_TYPE_PORT_SEND_ONCE);
        !          1651:                        hdr->msgh_remote_port = MACH_PORT_NULL;
        !          1652:                        hdr->msgh_local_port = (mach_port_t)dest_name;
        !          1653: 
        !          1654:                        mr = ipc_kmsg_copyout_body(kmsg, space,
        !          1655:                                                   current_map(), 
        !          1656:                                                   MACH_MSG_BODY_NULL);
        !          1657:                        if (mr != MACH_MSG_SUCCESS) {
        !          1658:                                if (ipc_kmsg_put(msg, kmsg, hdr->msgh_size +
        !          1659:                                               trailer->msgh_trailer_size) == 
        !          1660:                                                        MACH_RCV_INVALID_DATA)
        !          1661:                                        return MACH_RCV_INVALID_DATA;
        !          1662:                                else
        !          1663:                                        return mr | MACH_RCV_BODY_ERROR;
        !          1664:                        }
        !          1665:                        HOT(c_mmot_hot_ok3++);
        !          1666:                        goto fast_put;
        !          1667:                    }
        !          1668: 
        !          1669:                    default:
        !          1670:                        HOT(c_mmot_g_slow_copyout2++);
        !          1671:                        goto slow_copyout;
        !          1672:                }
        !          1673:                /*NOTREACHED*/ panic("happy birthday rwd");
        !          1674: 
        !          1675:            fast_put:
        !          1676:                /*
        !          1677:                 * We have the reply message data in kmsg,
        !          1678:                 * and the reply message size (plus trailer size)
        !          1679:                 * in reply_size.  Just need to copy it out to the
        !          1680:                 * user and free kmsg.  Must check ikm_cache after
        !          1681:                 * copyoutmsg.  Inlined ipc_kmsg_put() here.
        !          1682:                 */
        !          1683:                mr = MACH_MSG_SUCCESS;
        !          1684:                if (copyoutmsg((char *) &kmsg->ikm_header,
        !          1685:                                (char *)(rcv_msg ? rcv_msg : msg),
        !          1686:                                hdr->msgh_size + trailer->msgh_trailer_size))
        !          1687:                        mr = MACH_RCV_INVALID_DATA;
        !          1688:                else 
        !          1689:                        current_task()->messages_received++;
        !          1690: 
        !          1691:                if ((kmsg->ikm_size != IKM_SAVED_KMSG_SIZE) ||
        !          1692:                    KMSG_IS_RT(kmsg) || !ikm_cache_put(kmsg)) {
        !          1693:                        ikm_free(kmsg);
        !          1694:                }
        !          1695: 
        !          1696:                return(mr);
        !          1697: 
        !          1698: 
        !          1699:                /* BEGINNING OF WARM PATH */
        !          1700: 
        !          1701:                /*
        !          1702:                 *      The slow path has a few non-register temporary
        !          1703:                 *      variables used only for call-by-reference.
        !          1704:                 */
        !          1705: 
        !          1706:            {
        !          1707:                ipc_kmsg_t temp_kmsg;
        !          1708:                mach_port_seqno_t temp_seqno;
        !          1709:                ipc_object_t temp_rcv_object;
        !          1710:                ipc_mqueue_t temp_rcv_mqueue;
        !          1711: 
        !          1712:            slow_get:
        !          1713:                /*
        !          1714:                 *      No locks, references, or messages held.
        !          1715:                 *      Still have to get the request, send it,
        !          1716:                 *      receive reply, etc.
        !          1717:                 */
        !          1718: 
        !          1719:                mr = ipc_kmsg_get(msg, send_size, &temp_kmsg, current_space());
        !          1720:                if (mr != MACH_MSG_SUCCESS) {
        !          1721:                        return(mr);
        !          1722:                        /*NOTREACHED*/
        !          1723:                }
        !          1724:                kmsg = temp_kmsg;
        !          1725:                hdr = &kmsg->ikm_header;              
        !          1726:                /* naturally align the message before tacking on the trailer */
        !          1727:                trailer = (mach_msg_format_0_trailer_t *) ((vm_offset_t) hdr +
        !          1728:                                                   send_size);
        !          1729:                /* try to get back on optimized path */
        !          1730:                HOT(c_mmot_getback_fast_copyin++);
        !          1731:                goto fast_copyin;
        !          1732: 
        !          1733:            slow_copyin:
        !          1734:                /*
        !          1735:                 *      We have the message data in kmsg, but
        !          1736:                 *      we still need to copyin, send it,
        !          1737:                 *      receive a reply, and do copyout.
        !          1738:                 */
        !          1739: 
        !          1740:                mr = ipc_kmsg_copyin(kmsg, space, current_map(),
        !          1741:                                     MACH_PORT_NULL);
        !          1742:                if (mr != MACH_MSG_SUCCESS) {
        !          1743:                        if (kmsg->ikm_size != IKM_SAVED_KMSG_SIZE ||
        !          1744:                            KMSG_IS_RT(kmsg) || !ikm_cache_put(kmsg))
        !          1745:                                ikm_free(kmsg);
        !          1746:                        return(mr);
        !          1747:                }
        !          1748: 
        !          1749:                /* try to get back on optimized path */
        !          1750: 
        !          1751:                if (hdr->msgh_bits & MACH_MSGH_BITS_CIRCULAR) {
        !          1752:                        HOT(c_mmot_cold_048++);
        !          1753:                        goto slow_send;
        !          1754:                }
        !          1755: 
        !          1756:                dest_port = (ipc_port_t) hdr->msgh_remote_port;
        !          1757:                assert(IP_VALID(dest_port));
        !          1758: 
        !          1759:                ip_lock(dest_port);
        !          1760:                if (!ip_active(dest_port)) {
        !          1761:                    ip_unlock(dest_port);
        !          1762:                    goto slow_send;
        !          1763:                }
        !          1764:                
        !          1765:                if (dest_port->ip_receiver == ipc_space_kernel) {
        !          1766:                        dest_port->ip_messages.imq_seqno++;
        !          1767:                        ip_unlock(dest_port);
        !          1768:                        goto kernel_send;
        !          1769:                }
        !          1770: 
        !          1771:                if (!imq_full(&dest_port->ip_messages) ||
        !          1772:                     (MACH_MSGH_BITS_REMOTE(hdr->msgh_bits) ==
        !          1773:                                        MACH_MSG_TYPE_PORT_SEND_ONCE))
        !          1774:                {
        !          1775:                    /*
        !          1776:                     *  Try an optimized ipc_mqueue_copyin.
        !          1777:                     *  It will work if this is a request message.
        !          1778:                     */
        !          1779: 
        !          1780:                    register ipc_port_t reply_port;
        !          1781: 
        !          1782:                    reply_port = (ipc_port_t) hdr->msgh_local_port;
        !          1783:                    if (IP_VALID(reply_port)) {
        !          1784:                        if (ip_lock_try(reply_port)) {
        !          1785:                            if (ip_active(reply_port) &&
        !          1786:                                reply_port->ip_receiver == space &&
        !          1787:                                reply_port->ip_receiver_name == rcv_name &&
        !          1788:                                reply_port->ip_pset_count == 0)
        !          1789:                            {
        !          1790:                                /* Grab a reference to the reply port. */
        !          1791:                                rcv_object = (ipc_object_t) reply_port;
        !          1792:                                io_reference(rcv_object);
        !          1793:                                rcv_mqueue = &reply_port->ip_messages;
        !          1794:                                imq_lock(rcv_mqueue);
        !          1795:                                io_unlock(rcv_object);
        !          1796:                                HOT(c_mmot_getback_FastSR++);
        !          1797:                                goto fast_send_receive;
        !          1798:                            }
        !          1799:                            ip_unlock(reply_port);
        !          1800:                        }
        !          1801:                    }
        !          1802:                }
        !          1803: 
        !          1804:                ip_unlock(dest_port);
        !          1805:                HOT(c_mmot_cold_050++);
        !          1806:                goto slow_send;
        !          1807: 
        !          1808:            kernel_send:
        !          1809:                /*
        !          1810:                 *      Special case: send message to kernel services.
        !          1811:                 *      The request message has been copied into the
        !          1812:                 *      kmsg.  Nothing is locked.
        !          1813:                 */
        !          1814: 
        !          1815:            {
        !          1816:                register ipc_port_t     reply_port;
        !          1817:                mach_port_seqno_t       local_seqno;
        !          1818: 
        !          1819:                /*
        !          1820:                 * Perform the kernel function.
        !          1821:                 */
        !          1822:                c_mmot_kernel_send++;
        !          1823: 
        !          1824:                current_task()->messages_sent++;
        !          1825: 
        !          1826:                kmsg = ipc_kobject_server(kmsg);
        !          1827:                if (kmsg == IKM_NULL) {
        !          1828:                        /*
        !          1829:                         * No reply.  Take the
        !          1830:                         * slow receive path.
        !          1831:                         */
        !          1832:                        HOT(c_mmot_cold_051++);
        !          1833:                        goto slow_get_rcv_port;
        !          1834:                }
        !          1835: 
        !          1836:                /*
        !          1837:                 * Check that:
        !          1838:                 *      the reply port is alive
        !          1839:                 *      we hold the receive right
        !          1840:                 *      the name has not changed.
        !          1841:                 *      the port is not in a set
        !          1842:                 * If any of these are not true,
        !          1843:                 * we cannot directly receive the reply
        !          1844:                 * message.
        !          1845:                 */
        !          1846:                hdr = &kmsg->ikm_header;
        !          1847:                send_size = hdr->msgh_size;
        !          1848:                trailer = (mach_msg_format_0_trailer_t *) ((vm_offset_t) hdr +
        !          1849:                        round_msg(send_size));
        !          1850:                reply_port = (ipc_port_t) hdr->msgh_remote_port;
        !          1851:                ip_lock(reply_port);
        !          1852: 
        !          1853:                if ((!ip_active(reply_port)) ||
        !          1854:                    (reply_port->ip_receiver != space) ||
        !          1855:                    (reply_port->ip_receiver_name != rcv_name) ||
        !          1856:                    (reply_port->ip_pset_count != 0))
        !          1857:                {
        !          1858:                        ip_unlock(reply_port);
        !          1859:                        ipc_kmsg_send_always(kmsg);
        !          1860:                        HOT(c_mmot_cold_052++);
        !          1861:                        goto slow_get_rcv_port;
        !          1862:                }
        !          1863: 
        !          1864:                rcv_mqueue = &reply_port->ip_messages;
        !          1865:                imq_lock(rcv_mqueue);
        !          1866:                /* keep port locked, and don`t change ref count yet */
        !          1867: 
        !          1868:                /*
        !          1869:                 * If there are messages on the port
        !          1870:                 * or other threads waiting for a message,
        !          1871:                 * we cannot directly receive the reply.
        !          1872:                 */
        !          1873:                if (!wait_queue_empty(&rcv_mqueue->imq_wait_queue) ||
        !          1874:                    (ipc_kmsg_queue_first(&rcv_mqueue->imq_messages) != IKM_NULL))
        !          1875:                {
        !          1876:                        imq_unlock(rcv_mqueue);
        !          1877:                        ip_unlock(reply_port);
        !          1878:                        ipc_kmsg_send_always(kmsg);
        !          1879:                        HOT(c_mmot_cold_053++);
        !          1880:                        goto slow_get_rcv_port;
        !          1881:                }
        !          1882: 
        !          1883:                /*
        !          1884:                 * We can directly receive this reply.
        !          1885:                 * Since there were no messages queued
        !          1886:                 * on the reply port, there should be
        !          1887:                 * no threads blocked waiting to send.
        !          1888:                 */
        !          1889:                dest_port = reply_port;
        !          1890:                local_seqno = rcv_mqueue->imq_seqno++;
        !          1891:                imq_unlock(rcv_mqueue);
        !          1892: 
        !          1893:                /*
        !          1894:                 * inline ipc_object_release.
        !          1895:                 * Port is still locked.
        !          1896:                 * Reference count was not incremented.
        !          1897:                 */
        !          1898:                ip_check_unlock(reply_port);
        !          1899: 
        !          1900:                if (option & MACH_RCV_TRAILER_MASK) {
        !          1901:                        trailer->msgh_seqno = local_seqno;      
        !          1902:                        trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(option);
        !          1903:                }
        !          1904:                /* copy out the kernel reply */
        !          1905:                HOT(c_mmot_fastkernelreply++);
        !          1906:                goto fast_copyout;
        !          1907:            }
        !          1908: 
        !          1909:            slow_send:
        !          1910:                /*
        !          1911:                 *      Nothing is locked.  We have acquired kmsg, but
        !          1912:                 *      we still need to send it and receive a reply.
        !          1913:                 */
        !          1914: 
        !          1915:                mr = ipc_kmsg_send(kmsg, MACH_MSG_OPTION_NONE,
        !          1916:                                     MACH_MSG_TIMEOUT_NONE);
        !          1917:                if (mr != MACH_MSG_SUCCESS) {
        !          1918:                        mr |= ipc_kmsg_copyout_pseudo(kmsg, space,
        !          1919:                                                      current_map(),
        !          1920:                                                      MACH_MSG_BODY_NULL);
        !          1921: 
        !          1922:                        (void) ipc_kmsg_put(msg, kmsg, hdr->msgh_size);
        !          1923:                        return(mr);
        !          1924:                }
        !          1925: 
        !          1926:            slow_get_rcv_port:
        !          1927:                /*
        !          1928:                 * We have sent the message.  Copy in the receive port.
        !          1929:                 */
        !          1930:                mr = ipc_mqueue_copyin(space, rcv_name,
        !          1931:                                       &temp_rcv_mqueue, &temp_rcv_object);
        !          1932:                if (mr != MACH_MSG_SUCCESS) {
        !          1933:                        return(mr);
        !          1934:                }
        !          1935:                rcv_mqueue = temp_rcv_mqueue;
        !          1936:                rcv_object = temp_rcv_object;
        !          1937:                /* hold ref for rcv_object */
        !          1938: 
        !          1939:            slow_receive:
        !          1940:                /*
        !          1941:                 *      Now we have sent the request and copied in rcv_name,
        !          1942:                 *      so rcv_mqueue is locked and hold ref for rcv_object.
        !          1943:                 *      Just receive a reply and try to get back to fast path.
        !          1944:                 */
        !          1945: 
        !          1946:                self->ith_option = option;
        !          1947:                self->ith_scatter_list = MACH_MSG_BODY_NULL;
        !          1948:                self->ith_scatter_list_size = scatter_list_size;
        !          1949: 
        !          1950:                mr = ipc_mqueue_receive(rcv_mqueue,
        !          1951:                                        MACH_MSG_OPTION_NONE,
        !          1952:                                        MACH_MSG_SIZE_MAX,
        !          1953:                                        MACH_MSG_TIMEOUT_NONE,
        !          1954:                                        THREAD_ABORTSAFE,
        !          1955:                                        &temp_kmsg, &temp_seqno); 
        !          1956:                ipc_object_release(rcv_object);
        !          1957: 
        !          1958:                  if (mr != MACH_MSG_SUCCESS) {
        !          1959:                    return(mr);
        !          1960:                  }
        !          1961: 
        !          1962:                  kmsg = temp_kmsg;
        !          1963:                  hdr = &kmsg->ikm_header;
        !          1964:                  send_size = hdr->msgh_size;
        !          1965:                  trailer = (mach_msg_format_0_trailer_t *) ((vm_offset_t) hdr +
        !          1966:                                                             round_msg(send_size));
        !          1967:                  if (option & MACH_RCV_TRAILER_MASK) {
        !          1968:                    trailer->msgh_seqno = temp_seqno;   
        !          1969:                    trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(option);
        !          1970:                  }
        !          1971:                  dest_port = (ipc_port_t) hdr->msgh_remote_port;
        !          1972:                  HOT(c_mmot_cold_055++);
        !          1973:                  goto fast_copyout;
        !          1974: 
        !          1975:            slow_copyout:
        !          1976:                /*
        !          1977:                 *      Nothing locked and no references held, except
        !          1978:                 *      we have kmsg with msgh_seqno filled in.  Must
        !          1979:                 *      still check against rcv_size and do
        !          1980:                 *      ipc_kmsg_copyout/ipc_kmsg_put.
        !          1981:                 */
        !          1982: 
        !          1983:                reply_size = send_size + trailer->msgh_trailer_size;
        !          1984:                if (rcv_size < reply_size) {
        !          1985:                        if (msg_receive_error(kmsg, msg, option, temp_seqno,
        !          1986:                                        space) == MACH_RCV_INVALID_DATA) {
        !          1987:                                mr = MACH_RCV_INVALID_DATA;
        !          1988:                                return(mr);
        !          1989:                        }
        !          1990:                        else {
        !          1991:                                mr = MACH_RCV_TOO_LARGE;
        !          1992:                                return(mr);
        !          1993:                        }
        !          1994:                }
        !          1995: 
        !          1996:                mr = ipc_kmsg_copyout(kmsg, space, current_map(),
        !          1997:                                      MACH_PORT_NULL, MACH_MSG_BODY_NULL);
        !          1998:                if (mr != MACH_MSG_SUCCESS) {
        !          1999:                        if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
        !          2000:                                if (ipc_kmsg_put(msg, kmsg, reply_size) == 
        !          2001:                                                        MACH_RCV_INVALID_DATA)
        !          2002:                                        mr = MACH_RCV_INVALID_DATA;
        !          2003:                        } 
        !          2004:                        else {
        !          2005:                                if (msg_receive_error(kmsg, msg, option,
        !          2006:                                    temp_seqno, space) == MACH_RCV_INVALID_DATA)
        !          2007:                                        mr = MACH_RCV_INVALID_DATA;
        !          2008:                        }
        !          2009: 
        !          2010:                        return(mr);
        !          2011:                }
        !          2012: 
        !          2013:                /* try to get back on optimized path */
        !          2014:                HOT(c_mmot_getback_fast_put++);
        !          2015:                goto fast_put;
        !          2016: 
        !          2017:            slow_put:
        !          2018:                mr = ipc_kmsg_put((rcv_msg != MACH_MSG_NULL)?rcv_msg:msg,
        !          2019:                                  kmsg, 
        !          2020:                                  hdr->msgh_size + trailer->msgh_trailer_size);
        !          2021:                return(mr);
        !          2022:                /*NOTREACHED*/
        !          2023:            }
        !          2024:        } /* END OF HOT PATH */
        !          2025: #endif /* ENABLE_HOTPATH */
        !          2026: 
        !          2027:        if (option & MACH_SEND_MSG) {
        !          2028:                mr = mach_msg_send(msg, option, send_size,
        !          2029:                                   timeout, notify);
        !          2030:                if (mr != MACH_MSG_SUCCESS) {
        !          2031:                        return mr;
        !          2032:                }
        !          2033:        }
        !          2034: 
        !          2035:        if (option & MACH_RCV_MSG) {
        !          2036:                mach_msg_header_t *rcv;
        !          2037: 
        !          2038:                /*
        !          2039:                 * 1. MACH_RCV_OVERWRITE is on, and rcv_msg is our scatter list
        !          2040:                 *    and receive buffer
        !          2041:                 * 2. MACH_RCV_OVERWRITE is off, and rcv_msg might be the
        !          2042:                 *    alternate receive buffer (separate send and receive buffers).
        !          2043:                 */
        !          2044:                if (option & MACH_RCV_OVERWRITE) 
        !          2045:                    rcv = rcv_msg;
        !          2046:                else if (rcv_msg != MACH_MSG_NULL)
        !          2047:                    rcv = rcv_msg;
        !          2048:                else
        !          2049:                    rcv = msg;
        !          2050:                mr = mach_msg_receive(rcv, option, rcv_size, rcv_name, 
        !          2051:                                      timeout, notify, scatter_list_size);
        !          2052:                if (mr != MACH_MSG_SUCCESS) {
        !          2053:                        return mr;
        !          2054:                }
        !          2055:        }
        !          2056: 
        !          2057:        return MACH_MSG_SUCCESS;
        !          2058: }
        !          2059: 
        !          2060: /*
        !          2061:  *     Routine:        msg_receive_error       [internal]
        !          2062:  *     Purpose:
        !          2063:  *             Builds a minimal header/trailer and copies it to
        !          2064:  *             the user message buffer.  Invoked when in the case of a
        !          2065:  *             MACH_RCV_TOO_LARGE or MACH_RCV_BODY_ERROR error.
        !          2066:  *     Conditions:
        !          2067:  *             Nothing locked.
        !          2068:  *     Returns:
        !          2069:  *             MACH_MSG_SUCCESS        minimal header/trailer copied
        !          2070:  *             MACH_RCV_INVALID_DATA   copyout to user buffer failed
        !          2071:  */
        !          2072:        
        !          2073: mach_msg_return_t
        !          2074: msg_receive_error(
        !          2075:        ipc_kmsg_t              kmsg,
        !          2076:        mach_msg_header_t       *msg,
        !          2077:        mach_msg_option_t       option,
        !          2078:        mach_port_seqno_t       seqno,
        !          2079:        ipc_space_t             space)
        !          2080: {
        !          2081:        mach_msg_format_0_trailer_t *trailer;
        !          2082: 
        !          2083:        /*
        !          2084:         * Copy out the destination port in the message.
        !          2085:         * Destroy all other rights and memory in the message.
        !          2086:         */
        !          2087:        ipc_kmsg_copyout_dest(kmsg, space);
        !          2088: 
        !          2089:        /*
        !          2090:         * Build a minimal message with the requested trailer.
        !          2091:         */
        !          2092:        trailer = (mach_msg_format_0_trailer_t *) 
        !          2093:                        ((vm_offset_t)&kmsg->ikm_header +
        !          2094:                        round_msg(sizeof(mach_msg_header_t)));
        !          2095:        kmsg->ikm_header.msgh_size = sizeof(mach_msg_header_t);
        !          2096:        bcopy(  (char *)&trailer_template, 
        !          2097:                (char *)trailer, 
        !          2098:                sizeof(trailer_template));
        !          2099:        if (option & MACH_RCV_TRAILER_MASK) {
        !          2100:                trailer->msgh_seqno = seqno;
        !          2101:                trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(option);
        !          2102:        }
        !          2103: 
        !          2104:        /*
        !          2105:         * Copy the message to user space
        !          2106:         */
        !          2107:        if (ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size +
        !          2108:                        trailer->msgh_trailer_size) == MACH_RCV_INVALID_DATA)
        !          2109:                return(MACH_RCV_INVALID_DATA);
        !          2110:        else 
        !          2111:                return(MACH_MSG_SUCCESS);
        !          2112: }

unix.superglobalmegacorp.com

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