Annotation of kernel/kern/ipc_mig.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /* 
        !            26:  * Mach Operating System
        !            27:  * Copyright (c) 1991,1990 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: #include <mach/boolean.h>
        !            52: #include <mach/port.h>
        !            53: #include <mach/message.h>
        !            54: #include <mach/thread_status.h>
        !            55: #include <kern/ast.h>
        !            56: #include <kern/ipc_tt.h>
        !            57: #include <kern/thread.h>
        !            58: #include <kern/task.h>
        !            59: #include <kern/ipc_kobject.h>
        !            60: #include <vm/vm_map.h>
        !            61: #include <vm/vm_user.h>
        !            62: #include <ipc/port.h>
        !            63: #include <ipc/ipc_kmsg.h>
        !            64: #include <ipc/ipc_entry.h>
        !            65: #include <ipc/ipc_object.h>
        !            66: #include <ipc/ipc_mqueue.h>
        !            67: #include <ipc/ipc_space.h>
        !            68: #include <ipc/ipc_port.h>
        !            69: #include <ipc/ipc_pset.h>
        !            70: #include <ipc/ipc_thread.h>
        !            71: 
        !            72: 
        !            73: /*
        !            74:  *     Routine:        mach_msg_send_from_kernel
        !            75:  *     Purpose:
        !            76:  *             Send a message from the kernel.
        !            77:  *
        !            78:  *             This is used by the client side of KernelUser interfaces
        !            79:  *             to implement SimpleRoutines.  Currently, this includes
        !            80:  *             device_reply and memory_object messages.
        !            81:  *     Conditions:
        !            82:  *             Nothing locked.
        !            83:  *     Returns:
        !            84:  *             MACH_MSG_SUCCESS        Sent the message.
        !            85:  *             MACH_SEND_INVALID_DATA  Bad destination port.
        !            86:  */
        !            87: 
        !            88: mach_msg_return_t
        !            89: mach_msg_send_from_kernel(msg, send_size)
        !            90:        mach_msg_header_t *msg;
        !            91:        mach_msg_size_t send_size;
        !            92: {
        !            93:        ipc_kmsg_t kmsg;
        !            94:        mach_msg_return_t mr;
        !            95: 
        !            96:        if (!MACH_PORT_VALID(msg->msgh_remote_port))
        !            97:                return MACH_SEND_INVALID_DEST;
        !            98: 
        !            99:        mr = ipc_kmsg_get_from_kernel(msg, MACH_MSG_OPTION_NONE,
        !           100:                                      send_size, MAX_TRAILER_SIZE,
        !           101:                                      &kmsg);
        !           102:        if (mr != MACH_MSG_SUCCESS)
        !           103:                panic("mach_msg_send_from_kernel");
        !           104: 
        !           105:        ipc_kmsg_copyin_from_kernel(kmsg);
        !           106:        ipc_mqueue_send_always(kmsg);
        !           107: 
        !           108:        return MACH_MSG_SUCCESS;
        !           109: }
        !           110: 
        !           111: /*
        !           112:  *     Routine:        mach_msg_abort_rpc
        !           113:  *     Purpose:
        !           114:  *             Destroy the thread's ith_rpc_reply port.
        !           115:  *             This will interrupt a mach_msg_rpc_from_kernel
        !           116:  *             with a MACH_RCV_PORT_DIED return code.
        !           117:  *     Conditions:
        !           118:  *             Nothing locked.
        !           119:  */
        !           120: 
        !           121: void
        !           122: mach_msg_abort_rpc(thread)
        !           123:        ipc_thread_t thread;
        !           124: {
        !           125:        ipc_port_t reply = IP_NULL;
        !           126: 
        !           127:        ith_lock(thread);
        !           128:        if (thread->ith_self != IP_NULL) {
        !           129:                reply = thread->ith_rpc_reply;
        !           130:                thread->ith_rpc_reply = IP_NULL;
        !           131:        }
        !           132:        ith_unlock(thread);
        !           133: 
        !           134:        if (reply != IP_NULL)
        !           135:                ipc_port_dealloc_reply(reply);
        !           136: }
        !           137: 
        !           138: msg_return_t
        !           139: msg_send_from_kernel(msg, option, time_out)
        !           140:        msg_header_t *msg;
        !           141:        msg_option_t option;
        !           142:        msg_timeout_t time_out;
        !           143: {
        !           144:        msg_size_t send_size = msg->msg_size;
        !           145:        ipc_kmsg_t kmsg;
        !           146:        integer_t send_delta = send_size;
        !           147:        mach_msg_return_t mr;
        !           148: 
        !           149:        send_size = (send_size + 3) & ~3; /* round up */
        !           150:        send_delta -= send_size;
        !           151: 
        !           152:        mr = ipc_kmsg_get_from_kernel((mach_msg_header_t *) msg,
        !           153:                                        MACH_MSG_OPTION_NONE,
        !           154:                                        (mach_msg_size_t) send_size,
        !           155:                                        send_delta,
        !           156:                                        &kmsg);
        !           157:        if (mr != MACH_MSG_SUCCESS)
        !           158:                return msg_return_translate(mr);
        !           159: 
        !           160:        ipc_kmsg_copyin_compat_from_kernel(kmsg);
        !           161:        if (option & SEND_NOTIFY) {
        !           162:                panic("msg_send_from_kernel");
        !           163:        } else
        !           164:                mr = ipc_mqueue_send(kmsg,
        !           165:                                     ((option & SEND_TIMEOUT) ?
        !           166:                                      MACH_SEND_TIMEOUT :
        !           167:                                      MACH_MSG_OPTION_NONE) |
        !           168:                                      MACH_SEND_ALWAYS | MACH_SEND_SWITCH,
        !           169:                                     (mach_msg_timeout_t) time_out,
        !           170:                                     IMQ_NULL_CONTINUE);
        !           171: 
        !           172:        if (mr != MACH_MSG_SUCCESS)
        !           173:                ipc_kmsg_destroy(kmsg);
        !           174: 
        !           175:        return msg_return_translate(mr);
        !           176: }
        !           177: 
        !           178: msg_return_t
        !           179: msg_send(msg, option, time_out)
        !           180:        msg_header_t *msg;
        !           181:        msg_option_t option;
        !           182:        msg_timeout_t time_out;
        !           183: {
        !           184:        ipc_space_t space = current_space();
        !           185:        vm_map_t map = current_map();
        !           186:        msg_size_t send_size = msg->msg_size;
        !           187:        ipc_kmsg_t kmsg;
        !           188:        integer_t send_delta = send_size;
        !           189:        mach_msg_return_t mr;
        !           190: 
        !           191:        send_size = (send_size + 3) & ~3; /* round up */
        !           192:        send_delta -= send_size;
        !           193: 
        !           194:        if (send_size > MSG_SIZE_MAX)
        !           195:                return SEND_MSG_TOO_LARGE;
        !           196: 
        !           197:        mr = ipc_kmsg_get_from_kernel((mach_msg_header_t *) msg,
        !           198:                                        MACH_MSG_OPTION_NONE,
        !           199:                                        (mach_msg_size_t) send_size,
        !           200:                                        send_delta,
        !           201:                                        &kmsg);
        !           202:        if (mr != MACH_MSG_SUCCESS)
        !           203:                return msg_return_translate(mr);
        !           204: 
        !           205:        mr = ipc_kmsg_copyin_compat(kmsg, space, map);
        !           206:        if (mr != MACH_MSG_SUCCESS) {
        !           207:                ikm_free(kmsg);
        !           208:                return msg_return_translate(mr);
        !           209:        }
        !           210:        if (option & SEND_NOTIFY) {
        !           211:                panic("msg_send notify");
        !           212:        } else
        !           213:                do {
        !           214:                        if (option & SEND_SWITCH)
        !           215:                                mr = ipc_mqueue_send(kmsg,
        !           216:                                                ((option & SEND_TIMEOUT) ?
        !           217:                                                MACH_SEND_TIMEOUT :
        !           218:                                                MACH_MSG_OPTION_NONE) |
        !           219:                                                MACH_SEND_SWITCH,
        !           220:                                                (mach_msg_timeout_t) time_out,
        !           221:                                                IMQ_NULL_CONTINUE);
        !           222:                        else
        !           223:                                mr = ipc_mqueue_send(kmsg,
        !           224:                                                ((option & SEND_TIMEOUT) ?
        !           225:                                                MACH_SEND_TIMEOUT :
        !           226:                                                MACH_MSG_OPTION_NONE),
        !           227:                                                (mach_msg_timeout_t) time_out,
        !           228:                                                IMQ_NULL_CONTINUE);
        !           229:                        if (mr == MACH_SEND_INTERRUPTED) {
        !           230:                                while (thread_should_halt(current_thread()))
        !           231:                                        thread_halt_self_with_continuation(
        !           232:                                                        (void (*)(void)) 0);
        !           233: 
        !           234:                                if (option & SEND_INTERRUPT)
        !           235:                                        break;
        !           236:                        }
        !           237:                } while (mr == MACH_SEND_INTERRUPTED);
        !           238: 
        !           239:        if (mr != MACH_MSG_SUCCESS)
        !           240:                ipc_kmsg_destroy(kmsg);
        !           241: 
        !           242:        return msg_return_translate(mr);
        !           243: }
        !           244: 
        !           245: msg_return_t
        !           246: msg_receive(msg, option, time_out)
        !           247:        msg_header_t *msg;
        !           248:        msg_option_t option;
        !           249:        msg_timeout_t time_out;
        !           250: {
        !           251:        ipc_space_t space = current_space();
        !           252:        vm_map_t map = current_map();
        !           253:        port_name_t rcv_name = msg->msg_local_port;
        !           254:        msg_size_t rcv_size = msg->msg_size;
        !           255:        ipc_object_t object;
        !           256:        ipc_mqueue_t mqueue;
        !           257:        ipc_kmsg_t kmsg;
        !           258:        mach_port_seqno_t seqno;
        !           259:        mach_msg_return_t mr;
        !           260: 
        !           261:        do {
        !           262:                mr = ipc_mqueue_copyin(space, (mach_port_t) rcv_name,
        !           263:                                        &mqueue, &object);
        !           264:                if (mr != MACH_MSG_SUCCESS)
        !           265:                        return msg_return_translate(mr);
        !           266:                /* hold ref for object; mqueue is locked */
        !           267: 
        !           268:                mr = ipc_mqueue_receive(mqueue,
        !           269:                                        ((option & RCV_TIMEOUT) ?
        !           270:                                        MACH_RCV_TIMEOUT :
        !           271:                                        MACH_MSG_OPTION_NONE) |
        !           272:                                        MACH_RCV_OLD_FORMAT,
        !           273:                                        (option & RCV_LARGE) ?
        !           274:                                        (mach_msg_size_t) rcv_size :
        !           275:                                        MACH_MSG_SIZE_MAX,
        !           276:                                        (mach_msg_timeout_t) time_out,
        !           277:                                        FALSE, IMQ_NULL_CONTINUE,
        !           278:                                        &kmsg, &seqno, 0);
        !           279:                /* mqueue is unlocked */
        !           280:                ipc_object_release(object);
        !           281:                if (mr == MACH_RCV_INTERRUPTED) {
        !           282:                        while (thread_should_halt(current_thread()))
        !           283:                                thread_halt_self_with_continuation(
        !           284:                                                (void (*)(void)) 0);
        !           285:                        
        !           286:                        if (option & RCV_INTERRUPT)
        !           287:                                break;
        !           288:                }
        !           289:        } while (mr == MACH_RCV_INTERRUPTED);
        !           290:        if (mr != MACH_MSG_SUCCESS) {
        !           291:                if (mr == MACH_RCV_TOO_LARGE) {
        !           292:                        msg_size_t real_size =
        !           293:                                (msg_size_t) (mach_msg_size_t) kmsg;
        !           294: 
        !           295:                        assert(real_size > rcv_size);
        !           296:                        
        !           297:                        msg->msg_size = real_size;
        !           298:                }
        !           299: 
        !           300:                return msg_return_translate(mr);
        !           301:        }
        !           302:        
        !           303:        if (kmsg->ikm_header.msgh_size > (mach_msg_size_t) rcv_size) {
        !           304:                assert(!(option & RCV_LARGE));
        !           305:                
        !           306:                ipc_kmsg_destroy(kmsg);
        !           307:                return msg_return_translate(MACH_RCV_TOO_LARGE);
        !           308:        }
        !           309: 
        !           310:        assert(kmsg->ikm_header.msgh_size <= (mach_msg_size_t) rcv_size);
        !           311: 
        !           312:        mr = ipc_kmsg_copyout_compat(kmsg, space, map);
        !           313:        assert(mr == MACH_MSG_SUCCESS);
        !           314: 
        !           315:        kmsg->ikm_header.msgh_size += kmsg->ikm_delta;
        !           316:        ipc_kmsg_put_to_kernel((mach_msg_header_t *) msg, kmsg,
        !           317:                                kmsg->ikm_header.msgh_size);
        !           318:        return msg_return_translate(mr);
        !           319: }
        !           320: 
        !           321: msg_return_t
        !           322: msg_rpc(msg, option, rcv_size, send_timeout, rcv_timeout)
        !           323:        msg_header_t *msg;      /* in/out */
        !           324:        msg_option_t option;
        !           325:        msg_size_t rcv_size;
        !           326:        msg_timeout_t send_timeout;
        !           327:        msg_timeout_t rcv_timeout;
        !           328: {
        !           329:        ipc_space_t space = current_space();
        !           330:        vm_map_t map = current_map();
        !           331:        msg_size_t send_size = msg->msg_size;
        !           332:        ipc_port_t reply;
        !           333:        ipc_pset_t pset;
        !           334:        ipc_mqueue_t mqueue;
        !           335:        ipc_kmsg_t kmsg;
        !           336:        integer_t send_delta = send_size;
        !           337:        mach_port_seqno_t seqno;
        !           338:        mach_msg_return_t mr;
        !           339: 
        !           340:        /*
        !           341:         *      Instead of using msg_send and msg_receive,
        !           342:         *      we implement msg_rpc directly.  The difference
        !           343:         *      is how the reply port is handled.  Instead of using
        !           344:         *      ipc_mqueue_copyin, we save a reference for the reply
        !           345:         *      port carried in the sent message.  For example,
        !           346:         *      consider a rename kernel call which changes the name
        !           347:         *      of the call's own reply port.  This is the behaviour
        !           348:         *      of the Mach 2.5 msg_rpc_trap.
        !           349:         */
        !           350: 
        !           351:        send_size = (send_size + 3) & ~3; /* round up */
        !           352:        send_delta -= send_size;
        !           353: 
        !           354:        if (send_size > MSG_SIZE_MAX)
        !           355:                return SEND_MSG_TOO_LARGE;
        !           356: 
        !           357:        mr = ipc_kmsg_get_from_kernel((mach_msg_header_t *) msg,
        !           358:                                        MACH_MSG_OPTION_NONE,
        !           359:                                        (mach_msg_size_t) send_size,
        !           360:                                        send_delta,
        !           361:                                        &kmsg);
        !           362:        if (mr != MACH_MSG_SUCCESS)
        !           363:                return msg_return_translate(mr);
        !           364: 
        !           365:        mr = ipc_kmsg_copyin_compat(kmsg, space, map);
        !           366:        if (mr != MACH_MSG_SUCCESS) {
        !           367:                ikm_free(kmsg);
        !           368:                return msg_return_translate(mr);
        !           369:        }
        !           370:        
        !           371:        reply = (ipc_port_t)kmsg->ikm_header.msgh_local_port;
        !           372:        if (IP_VALID(reply)) {
        !           373:                ipc_port_t      dest = (ipc_port_t)
        !           374:                                        kmsg->ikm_header.msgh_remote_port;
        !           375:                
        !           376:                ipc_port_reference(reply);
        !           377:                assert(IP_VALID(dest));
        !           378:                
        !           379:                ip_lock(dest);
        !           380:                
        !           381:                if (dest->ip_receiver == ipc_space_kernel) {
        !           382:                        ipc_mqueue_t    mqueue;
        !           383: 
        !           384:                        assert(ip_active(dest));
        !           385:                        ip_unlock(dest);
        !           386:                        
        !           387:                        kmsg = ipc_kobject_server(kmsg);
        !           388:                        if (kmsg == IKM_NULL)
        !           389:                                goto receive_reply;
        !           390:                        
        !           391:                        ip_lock(reply);
        !           392:                        
        !           393:                        if ((!ip_active(reply)) ||
        !           394:                            (reply->ip_receiver != space) ||
        !           395:                            (reply->ip_pset != IPS_NULL) ||
        !           396:                            (rcv_size < (kmsg->ikm_header.msgh_size + 
        !           397:                                                        kmsg->ikm_delta)))
        !           398:                        {
        !           399:                                ip_unlock(reply);
        !           400:                                ipc_mqueue_send_always(kmsg);
        !           401:                                goto receive_reply;
        !           402:                        }
        !           403: 
        !           404:                        mqueue = &reply->ip_messages;
        !           405:                        imq_lock(mqueue);
        !           406:                        
        !           407:                        if ((ipc_thread_queue_first(&mqueue->imq_threads)
        !           408:                                != ITH_NULL) ||
        !           409:                            (ipc_kmsg_queue_first(&mqueue->imq_messages)
        !           410:                                != IKM_NULL))
        !           411:                        {
        !           412:                                imq_unlock(mqueue);
        !           413:                                ip_unlock(reply);
        !           414:                                ipc_mqueue_send_always(kmsg);
        !           415:                                goto receive_reply;
        !           416:                        }
        !           417: 
        !           418:                        assert(kmsg->ikm_marequest == IMAR_NULL);
        !           419:                        assert(ipc_thread_queue_first(&reply->ip_blocked)
        !           420:                                == ITH_NULL);
        !           421: 
        !           422:                        reply->ip_seqno++;
        !           423:                        imq_unlock(mqueue);
        !           424: 
        !           425:                        ip_release(reply);
        !           426:                        ip_unlock(reply);
        !           427:                        
        !           428:                        goto copyout_reply;
        !           429:                }
        !           430:                
        !           431:                ip_unlock(dest);
        !           432:        }
        !           433: 
        !           434:        if (option & SEND_NOTIFY) {
        !           435:                panic("msg_rpc notify");
        !           436:        } else
        !           437:                do {
        !           438:                        if (option & SEND_SWITCH)
        !           439:                                mr = ipc_mqueue_send(kmsg,
        !           440:                                                    ((option & SEND_TIMEOUT) ?
        !           441:                                                    MACH_SEND_TIMEOUT :
        !           442:                                                    MACH_MSG_OPTION_NONE) |
        !           443:                                                    MACH_SEND_SWITCH,
        !           444:                                                    (mach_msg_timeout_t)
        !           445:                                                            send_timeout,
        !           446:                                                    IMQ_NULL_CONTINUE);
        !           447:                        else
        !           448:                                mr = ipc_mqueue_send(kmsg,
        !           449:                                                    ((option & SEND_TIMEOUT) ?
        !           450:                                                    MACH_SEND_TIMEOUT :
        !           451:                                                    MACH_MSG_OPTION_NONE),
        !           452:                                                    (mach_msg_timeout_t)
        !           453:                                                            send_timeout,
        !           454:                                                    IMQ_NULL_CONTINUE);
        !           455:                        if (mr == MACH_SEND_INTERRUPTED) {
        !           456:                                while (thread_should_halt(current_thread()))
        !           457:                                        thread_halt_self_with_continuation(
        !           458:                                                        (void (*)(void)) 0);
        !           459: 
        !           460:                                if (option & SEND_INTERRUPT)
        !           461:                                        break;
        !           462:                        }
        !           463:                } while (mr == MACH_SEND_INTERRUPTED);
        !           464: 
        !           465:        if (mr != MACH_MSG_SUCCESS) {
        !           466:                ipc_kmsg_destroy(kmsg);
        !           467:                if (IP_VALID(reply))
        !           468:                        ipc_port_release(reply);
        !           469:                return msg_return_translate(mr);
        !           470:        }
        !           471: 
        !           472: receive_reply:
        !           473:        if (!IP_VALID(reply))
        !           474:                return RCV_INVALID_PORT;
        !           475:        
        !           476:        ip_lock(reply);
        !           477:        if (reply->ip_receiver != space) {
        !           478:                ip_release(reply);
        !           479:                ip_check_unlock(reply);
        !           480:                return RCV_INVALID_PORT;
        !           481:        }
        !           482: 
        !           483:        assert(ip_active(reply));
        !           484:        pset = reply->ip_pset;
        !           485: 
        !           486:        if (pset != IPS_NULL) {
        !           487:                ips_lock(pset);
        !           488:                if (ips_active(pset)) {
        !           489:                        ips_unlock(pset);
        !           490:                        ip_release(reply);
        !           491:                        ip_unlock(reply);
        !           492:                        return RCV_INVALID_PORT;
        !           493:                }
        !           494: 
        !           495:                ipc_pset_remove(pset, reply);
        !           496:                ips_check_unlock(pset);
        !           497:                assert(reply->ip_pset == IPS_NULL);
        !           498:        }
        !           499: 
        !           500:        mqueue = &reply->ip_messages;
        !           501:        imq_lock(mqueue);
        !           502:        ip_unlock(reply);
        !           503: 
        !           504:        mr = ipc_mqueue_receive(mqueue,
        !           505:                                ((option & RCV_TIMEOUT) ?
        !           506:                                MACH_RCV_TIMEOUT :
        !           507:                                MACH_MSG_OPTION_NONE) |
        !           508:                                MACH_RCV_OLD_FORMAT,
        !           509:                                (option & RCV_LARGE) ?
        !           510:                                (mach_msg_size_t) rcv_size :
        !           511:                                MACH_MSG_SIZE_MAX,
        !           512:                                (mach_msg_timeout_t) rcv_timeout,
        !           513:                                FALSE, IMQ_NULL_CONTINUE,
        !           514:                                &kmsg, &seqno, 0);
        !           515:        /* mqueue is unlocked */
        !           516:        ipc_port_release(reply);
        !           517:        if (mr != MACH_MSG_SUCCESS) {
        !           518:                if (mr == MACH_RCV_INTERRUPTED) {
        !           519:                        while (thread_should_halt(current_thread()))
        !           520:                                thread_halt_self_with_continuation(
        !           521:                                                (void (*)(void)) 0);
        !           522:                                
        !           523:                        msg->msg_size = rcv_size;       /* XXX */
        !           524:                        
        !           525:                        if (!(option & RCV_INTERRUPT))
        !           526:                                return msg_receive(msg, option, rcv_timeout);
        !           527:                } else if (mr == MACH_RCV_TOO_LARGE) {
        !           528:                        msg_size_t real_size =
        !           529:                                (msg_size_t) (mach_msg_size_t) kmsg;
        !           530: 
        !           531:                        assert(real_size > rcv_size);
        !           532:                        
        !           533:                        msg->msg_size = real_size;
        !           534:                }
        !           535: 
        !           536:                return msg_return_translate(mr);
        !           537:        }
        !           538:        
        !           539:        if (kmsg->ikm_header.msgh_size > (mach_msg_size_t) rcv_size) {
        !           540:                assert(!(option & RCV_LARGE));
        !           541:                
        !           542:                ipc_kmsg_destroy(kmsg);
        !           543:                return msg_return_translate(MACH_RCV_TOO_LARGE);
        !           544:        }
        !           545: 
        !           546: copyout_reply:
        !           547:        assert(kmsg->ikm_header.msgh_size <= (mach_msg_size_t) rcv_size);
        !           548: 
        !           549:        mr = ipc_kmsg_copyout_compat(kmsg, space, map);
        !           550:        assert(mr == MACH_MSG_SUCCESS);
        !           551: 
        !           552:        kmsg->ikm_header.msgh_size += kmsg->ikm_delta;
        !           553:        ipc_kmsg_put_to_kernel((mach_msg_header_t *) msg, kmsg,
        !           554:                                kmsg->ikm_header.msgh_size);
        !           555:        return msg_return_translate(mr);
        !           556: 
        !           557: }
        !           558: 
        !           559: /*
        !           560:  *     Routine:        mig_get_reply_port
        !           561:  *     Purpose:
        !           562:  *             Called by client side interfaces living in the kernel
        !           563:  *             to get a reply port.  This port is used for
        !           564:  *             mach_msg() calls which are kernel calls.
        !           565:  */
        !           566: 
        !           567: mach_port_t
        !           568: mig_get_reply_port()
        !           569: {
        !           570:        ipc_thread_t self = current_thread();
        !           571: 
        !           572:        if (self->ith_mig_reply == MACH_PORT_NULL)
        !           573:                self->ith_mig_reply = mach_reply_port();
        !           574: 
        !           575:        return self->ith_mig_reply;
        !           576: }
        !           577: 
        !           578: /*
        !           579:  *     Routine:        mig_dealloc_reply_port
        !           580:  *     Purpose:
        !           581:  *             Called by client side interfaces to get rid of a reply port.
        !           582:  *             Shouldn't ever be called inside the kernel, because
        !           583:  *             kernel calls shouldn't prompt Mig to call it.
        !           584:  */
        !           585: 
        !           586: void
        !           587: mig_dealloc_reply_port()
        !           588: {
        !           589:        panic("mig_dealloc_reply_port");
        !           590: }
        !           591: 
        !           592: /*
        !           593:  * mig_strncpy.c - by Joshua Block
        !           594:  *
        !           595:  * mig_strncp -- Bounded string copy.  Does what the library routine strncpy
        !           596:  * OUGHT to do:  Copies the (null terminated) string in src into dest, a 
        !           597:  * buffer of length len.  Assures that the copy is still null terminated
        !           598:  * and doesn't overflow the buffer, truncating the copy if necessary.
        !           599:  *
        !           600:  * Parameters:
        !           601:  * 
        !           602:  *     dest - Pointer to destination buffer.
        !           603:  * 
        !           604:  *     src - Pointer to source string.
        !           605:  * 
        !           606:  *     len - Length of destination buffer.
        !           607:  */
        !           608: vm_size_t mig_strncpy(
        !           609:        char            *dest,
        !           610:        const char      *src,
        !           611:        vm_size_t       len)
        !           612: {
        !           613:     vm_size_t i;
        !           614: 
        !           615:     if (len <= 0)
        !           616:        return 0;
        !           617: 
        !           618:     for (i=1; i<len; i++)
        !           619:        if (! (*dest++ = *src++))
        !           620:            return i;
        !           621: 
        !           622:     *dest = '\0';
        !           623:     return i;
        !           624: }
        !           625: 
        !           626: #if    0
        !           627: 
        !           628: #define        fast_send_right_lookup(name, port, abort)                       \
        !           629: MACRO_BEGIN                                                            \
        !           630:        register ipc_space_t space = current_space();                   \
        !           631:        register ipc_entry_t entry;                                     \
        !           632:        register mach_port_index_t index = MACH_PORT_INDEX(name);       \
        !           633:                                                                        \
        !           634:        is_read_lock(space);                                            \
        !           635:        assert(space->is_active);                                       \
        !           636:                                                                        \
        !           637:        if ((index >= space->is_table_size) ||                          \
        !           638:            (((entry = &space->is_table[index])->ie_bits &              \
        !           639:              (IE_BITS_GEN_MASK|MACH_PORT_TYPE_SEND)) !=                \
        !           640:             (MACH_PORT_GEN(name) | MACH_PORT_TYPE_SEND))) {            \
        !           641:                is_read_unlock(space);                                  \
        !           642:                abort;                                                  \
        !           643:        }                                                               \
        !           644:                                                                        \
        !           645:        port = (ipc_port_t) entry->ie_object;                           \
        !           646:        assert(port != IP_NULL);                                        \
        !           647:                                                                        \
        !           648:        ip_lock(port);                                                  \
        !           649:        /* can safely unlock space now that port is locked */           \
        !           650:        is_read_unlock(space);                                          \
        !           651: MACRO_END
        !           652: 
        !           653: thread_t
        !           654: port_name_to_thread(name)
        !           655:        mach_port_t name;
        !           656: {
        !           657:        register ipc_port_t port;
        !           658: 
        !           659:        fast_send_right_lookup(name, port, goto abort);
        !           660:        /* port is locked */
        !           661: 
        !           662:        if (ip_active(port) &&
        !           663:            (ip_kotype(port) == IKOT_THREAD)) {
        !           664:                register thread_t thread;
        !           665: 
        !           666:                thread = (thread_t) port->ip_kobject;
        !           667:                assert(thread != THREAD_NULL);
        !           668: 
        !           669:                /* thread referencing is a bit complicated,
        !           670:                   so don't bother to expand inline */
        !           671:                thread_reference(thread);
        !           672:                ip_unlock(port);
        !           673: 
        !           674:                return thread;
        !           675:        }
        !           676: 
        !           677:        ip_unlock(port);
        !           678:        return THREAD_NULL;
        !           679: 
        !           680:     abort: {
        !           681:        thread_t thread;
        !           682:        ipc_port_t kern_port;
        !           683:        kern_return_t kr;
        !           684: 
        !           685:        kr = ipc_object_copyin(current_space(), name,
        !           686:                               MACH_MSG_TYPE_COPY_SEND,
        !           687:                               (ipc_object_t *) &kern_port);
        !           688:        if (kr != KERN_SUCCESS)
        !           689:                return THREAD_NULL;
        !           690: 
        !           691:        thread = convert_port_to_thread(kern_port);
        !           692:        if (IP_VALID(kern_port))
        !           693:                ipc_port_release_send(kern_port);
        !           694: 
        !           695:        return thread;
        !           696:     }
        !           697: }
        !           698: 
        !           699: task_t
        !           700: port_name_to_task(name)
        !           701:        mach_port_t name;
        !           702: {
        !           703:        register ipc_port_t port;
        !           704: 
        !           705:        fast_send_right_lookup(name, port, goto abort);
        !           706:        /* port is locked */
        !           707: 
        !           708:        if (ip_active(port) &&
        !           709:            (ip_kotype(port) == IKOT_TASK)) {
        !           710:                register task_t task;
        !           711: 
        !           712:                task = (task_t) port->ip_kobject;
        !           713:                assert(task != TASK_NULL);
        !           714: 
        !           715:                task_lock(task);
        !           716:                /* can safely unlock port now that task is locked */
        !           717:                ip_unlock(port);
        !           718: 
        !           719:                task->ref_count++;
        !           720:                task_unlock(task);
        !           721: 
        !           722:                return task;
        !           723:        }
        !           724: 
        !           725:        ip_unlock(port);
        !           726:        return TASK_NULL;
        !           727: 
        !           728:     abort: {
        !           729:        task_t task;
        !           730:        ipc_port_t kern_port;
        !           731:        kern_return_t kr;
        !           732: 
        !           733:        kr = ipc_object_copyin(current_space(), name,
        !           734:                               MACH_MSG_TYPE_COPY_SEND,
        !           735:                               (ipc_object_t *) &kern_port);
        !           736:        if (kr != KERN_SUCCESS)
        !           737:                return TASK_NULL;
        !           738: 
        !           739:        task = convert_port_to_task(kern_port);
        !           740:        if (IP_VALID(kern_port))
        !           741:                ipc_port_release_send(kern_port);
        !           742: 
        !           743:        return task;
        !           744:     }
        !           745: }
        !           746: 
        !           747: vm_map_t
        !           748: port_name_to_map(name)
        !           749:        mach_port_t name;
        !           750: {
        !           751:        register ipc_port_t port;
        !           752: 
        !           753:        fast_send_right_lookup(name, port, goto abort);
        !           754:        /* port is locked */
        !           755: 
        !           756:        if (ip_active(port) &&
        !           757:            (ip_kotype(port) == IKOT_TASK)) {
        !           758:                register vm_map_t map;
        !           759: 
        !           760:                map = ((task_t) port->ip_kobject)->map;
        !           761:                assert(map != VM_MAP_NULL);
        !           762: 
        !           763:                simple_lock(&map->ref_lock);
        !           764:                /* can safely unlock port now that map is locked */
        !           765:                ip_unlock(port);
        !           766: 
        !           767:                map->ref_count++;
        !           768:                simple_unlock(&map->ref_lock);
        !           769: 
        !           770:                return map;
        !           771:        }
        !           772: 
        !           773:        ip_unlock(port);
        !           774:        return VM_MAP_NULL;
        !           775: 
        !           776:     abort: {
        !           777:        vm_map_t map;
        !           778:        ipc_port_t kern_port;
        !           779:        kern_return_t kr;
        !           780: 
        !           781:        kr = ipc_object_copyin(current_space(), name,
        !           782:                               MACH_MSG_TYPE_COPY_SEND,
        !           783:                               (ipc_object_t *) &kern_port);
        !           784:        if (kr != KERN_SUCCESS)
        !           785:                return VM_MAP_NULL;
        !           786: 
        !           787:        map = convert_port_to_map(kern_port);
        !           788:        if (IP_VALID(kern_port))
        !           789:                ipc_port_release_send(kern_port);
        !           790: 
        !           791:        return map;
        !           792:     }
        !           793: }
        !           794: 
        !           795: ipc_space_t
        !           796: port_name_to_space(name)
        !           797:        mach_port_t name;
        !           798: {
        !           799:        register ipc_port_t port;
        !           800: 
        !           801:        fast_send_right_lookup(name, port, goto abort);
        !           802:        /* port is locked */
        !           803: 
        !           804:        if (ip_active(port) &&
        !           805:            (ip_kotype(port) == IKOT_TASK)) {
        !           806:                register ipc_space_t space;
        !           807: 
        !           808:                space = ((task_t) port->ip_kobject)->itk_space;
        !           809:                assert(space != IS_NULL);
        !           810: 
        !           811:                simple_lock(&space->is_ref_lock_data);
        !           812:                /* can safely unlock port now that space is locked */
        !           813:                ip_unlock(port);
        !           814: 
        !           815:                space->is_references++;
        !           816:                simple_unlock(&space->is_ref_lock_data);
        !           817: 
        !           818:                return space;
        !           819:        }
        !           820: 
        !           821:        ip_unlock(port);
        !           822:        return IS_NULL;
        !           823: 
        !           824:     abort: {
        !           825:        ipc_space_t space;
        !           826:        ipc_port_t kern_port;
        !           827:        kern_return_t kr;
        !           828: 
        !           829:        kr = ipc_object_copyin(current_space(), name,
        !           830:                               MACH_MSG_TYPE_COPY_SEND,
        !           831:                               (ipc_object_t *) &kern_port);
        !           832:        if (kr != KERN_SUCCESS)
        !           833:                return IS_NULL;
        !           834: 
        !           835:        space = convert_port_to_space(kern_port);
        !           836:        if (IP_VALID(kern_port))
        !           837:                ipc_port_release_send(kern_port);
        !           838: 
        !           839:        return space;
        !           840:     }
        !           841: }
        !           842: 
        !           843: /*
        !           844:  * Hack to translate a thread port to a thread pointer for calling
        !           845:  * thread_get_state and thread_set_state.  This is only necessary
        !           846:  * because the IPC message for these two operations overflows the
        !           847:  * kernel stack.
        !           848:  *
        !           849:  * AARGH!
        !           850:  */
        !           851: 
        !           852: kern_return_t thread_get_state_KERNEL(thread_port, flavor,
        !           853:                        old_state, old_state_count)
        !           854:        mach_port_t     thread_port;    /* port right for thread */
        !           855:        int             flavor;
        !           856:        thread_state_t  old_state;      /* pointer to OUT array */
        !           857:        natural_t       *old_state_count;       /* IN/OUT */
        !           858: {
        !           859:        thread_t        thread;
        !           860:        kern_return_t   result;
        !           861: 
        !           862:        thread = port_name_to_thread(thread_port);
        !           863:        result = thread_get_state(thread, flavor, old_state, old_state_count);
        !           864:        thread_deallocate(thread);
        !           865: 
        !           866:        return result;
        !           867: }
        !           868: 
        !           869: kern_return_t thread_set_state_KERNEL(thread_port, flavor,
        !           870:                        new_state, new_state_count)
        !           871:        mach_port_t     thread_port;    /* port right for thread */
        !           872:        int             flavor;
        !           873:        thread_state_t  new_state;
        !           874:        natural_t       new_state_count;
        !           875: {
        !           876:        thread_t        thread;
        !           877:        kern_return_t   result;
        !           878: 
        !           879:        thread = port_name_to_thread(thread_port);
        !           880:        result = thread_set_state(thread, flavor, new_state, new_state_count);
        !           881:        thread_deallocate(thread);
        !           882: 
        !           883:        return result;
        !           884: }
        !           885: 
        !           886: /*
        !           887:  *     Things to keep in mind:
        !           888:  *
        !           889:  *     The idea here is to duplicate the semantics of the true kernel RPC.
        !           890:  *     The destination port/object should be checked first, before anything
        !           891:  *     that the user might notice (like ipc_object_copyin).  Return
        !           892:  *     MACH_SEND_INTERRUPTED if it isn't correct, so that the user stub
        !           893:  *     knows to fall back on an RPC.  For other return values, it won't
        !           894:  *     retry with an RPC.  The retry might get a different (incorrect) rc.
        !           895:  *     Return values are only set (and should only be set, with copyout)
        !           896:  *     on successfull calls.
        !           897:  */
        !           898: 
        !           899: kern_return_t syscall_vm_map(
        !           900:                target_map,
        !           901:                address, size, mask, anywhere,
        !           902:                memory_object, offset,
        !           903:                copy,
        !           904:                cur_protection, max_protection, inheritance)
        !           905:        mach_port_t     target_map;
        !           906:        vm_offset_t     *address;
        !           907:        vm_size_t       size;
        !           908:        vm_offset_t     mask;
        !           909:        boolean_t       anywhere;
        !           910:        mach_port_t     memory_object;
        !           911:        vm_offset_t     offset;
        !           912:        boolean_t       copy;
        !           913:        vm_prot_t       cur_protection;
        !           914:        vm_prot_t       max_protection;
        !           915:        vm_inherit_t    inheritance;
        !           916: {
        !           917:        vm_map_t                map;
        !           918:        ipc_port_t              port;
        !           919:        vm_offset_t             addr;
        !           920:        kern_return_t           result;
        !           921: 
        !           922:        map = port_name_to_map(target_map);
        !           923:        if (map == VM_MAP_NULL)
        !           924:                return MACH_SEND_INTERRUPTED;
        !           925: 
        !           926:        if (MACH_PORT_VALID(memory_object)) {
        !           927:                result = ipc_object_copyin(current_space(), memory_object,
        !           928:                                           MACH_MSG_TYPE_COPY_SEND,
        !           929:                                           (ipc_object_t *) &port);
        !           930:                if (result != KERN_SUCCESS) {
        !           931:                        vm_map_deallocate(map);
        !           932:                        return result;
        !           933:                }
        !           934:        } else
        !           935:                port = (ipc_port_t) memory_object;
        !           936: 
        !           937:        copyin((char *)address, (char *)&addr, sizeof(vm_offset_t));
        !           938:        result = vm_map(map, &addr, size, mask, anywhere,
        !           939:                        port, offset, copy,
        !           940:                        cur_protection, max_protection, inheritance);
        !           941:        if (result == KERN_SUCCESS)
        !           942:                copyout((char *)&addr, (char *)address, sizeof(vm_offset_t));
        !           943:        if (IP_VALID(port))
        !           944:                ipc_port_release_send(port);
        !           945:        vm_map_deallocate(map);
        !           946: 
        !           947:        return result;
        !           948: }
        !           949: 
        !           950: kern_return_t syscall_vm_allocate(target_map, address, size, anywhere)
        !           951:        mach_port_t             target_map;
        !           952:        vm_offset_t             *address;
        !           953:        vm_size_t               size;
        !           954:        boolean_t               anywhere;
        !           955: {
        !           956:        vm_map_t                map;
        !           957:        vm_offset_t             addr;
        !           958:        kern_return_t           result;
        !           959: 
        !           960:        map = port_name_to_map(target_map);
        !           961:        if (map == VM_MAP_NULL)
        !           962:                return MACH_SEND_INTERRUPTED;
        !           963: 
        !           964:        copyin((char *)address, (char *)&addr, sizeof(vm_offset_t));
        !           965:        result = vm_allocate(map, &addr, size, anywhere);
        !           966:        if (result == KERN_SUCCESS)
        !           967:                copyout((char *)&addr, (char *)address, sizeof(vm_offset_t));
        !           968:        vm_map_deallocate(map);
        !           969: 
        !           970:        return result;
        !           971: }
        !           972: 
        !           973: kern_return_t syscall_vm_deallocate(target_map, start, size)
        !           974:        mach_port_t             target_map;
        !           975:        vm_offset_t             start;
        !           976:        vm_size_t               size;
        !           977: {
        !           978:        vm_map_t                map;
        !           979:        kern_return_t           result;
        !           980: 
        !           981:        map = port_name_to_map(target_map);
        !           982:        if (map == VM_MAP_NULL)
        !           983:                return MACH_SEND_INTERRUPTED;
        !           984: 
        !           985:        result = vm_deallocate(map, start, size);
        !           986:        vm_map_deallocate(map);
        !           987: 
        !           988:        return result;
        !           989: }
        !           990: 
        !           991: kern_return_t syscall_task_create(parent_task, inherit_memory, child_task)
        !           992:        mach_port_t     parent_task;
        !           993:        boolean_t       inherit_memory;
        !           994:        mach_port_t     *child_task;            /* OUT */
        !           995: {
        !           996:        task_t          t, c;
        !           997:        ipc_port_t      port;
        !           998:        mach_port_t     name;
        !           999:        kern_return_t   result;
        !          1000: 
        !          1001:        t = port_name_to_task(parent_task);
        !          1002:        if (t == TASK_NULL)
        !          1003:                return MACH_SEND_INTERRUPTED;
        !          1004: 
        !          1005:        result = task_create(t, inherit_memory, &c);
        !          1006:        if (result == KERN_SUCCESS) {
        !          1007:                port = (ipc_port_t) convert_task_to_port(c);
        !          1008:                /* always returns a name, even for non-success return codes */
        !          1009:                (void) ipc_kmsg_copyout_object(current_space(),
        !          1010:                                               (ipc_object_t) port,
        !          1011:                                               MACH_MSG_TYPE_PORT_SEND, &name);
        !          1012:                copyout((char *)&name, (char *)child_task,
        !          1013:                        sizeof(mach_port_t));
        !          1014:        }
        !          1015:        task_deallocate(t);
        !          1016: 
        !          1017:        return result;
        !          1018: }
        !          1019: 
        !          1020: kern_return_t syscall_task_terminate(task)
        !          1021:        mach_port_t     task;
        !          1022: {
        !          1023:        task_t          t;
        !          1024:        kern_return_t   result;
        !          1025: 
        !          1026:        t = port_name_to_task(task);
        !          1027:        if (t == TASK_NULL)
        !          1028:                return MACH_SEND_INTERRUPTED;
        !          1029: 
        !          1030:        result = task_terminate(t);
        !          1031:        task_deallocate(t);
        !          1032: 
        !          1033:        return result;
        !          1034: }
        !          1035: 
        !          1036: kern_return_t syscall_task_suspend(task)
        !          1037:        mach_port_t     task;
        !          1038: {
        !          1039:        task_t          t;
        !          1040:        kern_return_t   result;
        !          1041: 
        !          1042:        t = port_name_to_task(task);
        !          1043:        if (t == TASK_NULL)
        !          1044:                return MACH_SEND_INTERRUPTED;
        !          1045: 
        !          1046:        result = task_suspend(t);
        !          1047:        task_deallocate(t);
        !          1048: 
        !          1049:        return result;
        !          1050: }
        !          1051: 
        !          1052: kern_return_t syscall_task_set_special_port(task, which_port, port_name)
        !          1053:        mach_port_t     task;
        !          1054:        int             which_port;
        !          1055:        mach_port_t     port_name;
        !          1056: {
        !          1057:        task_t          t;
        !          1058:        ipc_port_t      port;
        !          1059:        kern_return_t   result;
        !          1060: 
        !          1061:        t = port_name_to_task(task);
        !          1062:        if (t == TASK_NULL)
        !          1063:                return MACH_SEND_INTERRUPTED;
        !          1064: 
        !          1065:        if (MACH_PORT_VALID(port_name)) {
        !          1066:                result = ipc_object_copyin(current_space(), port_name,
        !          1067:                                           MACH_MSG_TYPE_COPY_SEND,
        !          1068:                                           (ipc_object_t *) &port);
        !          1069:                if (result != KERN_SUCCESS) {
        !          1070:                        task_deallocate(t);
        !          1071:                        return result;
        !          1072:                }
        !          1073:        } else
        !          1074:                port = (ipc_port_t) port_name;
        !          1075: 
        !          1076:        result = task_set_special_port(t, which_port, port);
        !          1077:        if ((result != KERN_SUCCESS) && IP_VALID(port))
        !          1078:                ipc_port_release_send(port);
        !          1079:        task_deallocate(t);
        !          1080: 
        !          1081:        return result;
        !          1082: }
        !          1083: 
        !          1084: kern_return_t
        !          1085: syscall_mach_port_allocate(task, right, namep)
        !          1086:        mach_port_t task;
        !          1087:        mach_port_right_t right;
        !          1088:        mach_port_t *namep;
        !          1089: {
        !          1090:        ipc_space_t space;
        !          1091:        mach_port_t name;
        !          1092:        kern_return_t kr;
        !          1093: 
        !          1094:        space = port_name_to_space(task);
        !          1095:        if (space == IS_NULL)
        !          1096:                return MACH_SEND_INTERRUPTED;
        !          1097: 
        !          1098:        kr = mach_port_allocate(space, right, &name);
        !          1099:        if (kr == KERN_SUCCESS)
        !          1100:                copyout((char *)&name, (char *)namep, sizeof(mach_port_t));
        !          1101:        is_release(space);
        !          1102: 
        !          1103:        return kr;
        !          1104: }
        !          1105: 
        !          1106: kern_return_t
        !          1107: syscall_mach_port_allocate_name(task, right, name)
        !          1108:        mach_port_t task;
        !          1109:        mach_port_right_t right;
        !          1110:        mach_port_t name;
        !          1111: {
        !          1112:        ipc_space_t space;
        !          1113:        kern_return_t kr;
        !          1114: 
        !          1115:        space = port_name_to_space(task);
        !          1116:        if (space == IS_NULL)
        !          1117:                return MACH_SEND_INTERRUPTED;
        !          1118: 
        !          1119:        kr = mach_port_allocate_name(space, right, name);
        !          1120:        is_release(space);
        !          1121: 
        !          1122:        return kr;
        !          1123: }
        !          1124: 
        !          1125: kern_return_t
        !          1126: syscall_mach_port_deallocate(task, name)
        !          1127:        mach_port_t task;
        !          1128:        mach_port_t name;
        !          1129: {
        !          1130:        ipc_space_t space;
        !          1131:        kern_return_t kr;
        !          1132: 
        !          1133:        space = port_name_to_space(task);
        !          1134:        if (space == IS_NULL)
        !          1135:                return MACH_SEND_INTERRUPTED;
        !          1136: 
        !          1137:        kr = mach_port_deallocate(space, name);
        !          1138:        is_release(space);
        !          1139: 
        !          1140:        return kr;
        !          1141: }
        !          1142: 
        !          1143: kern_return_t
        !          1144: syscall_mach_port_insert_right(task, name, right, rightType)
        !          1145:        mach_port_t task;
        !          1146:        mach_port_t name;
        !          1147:        mach_port_t right;
        !          1148:        mach_msg_type_name_t rightType;
        !          1149: {
        !          1150:        ipc_space_t space;
        !          1151:        ipc_object_t object;
        !          1152:        mach_msg_type_name_t newtype;
        !          1153:        kern_return_t kr;
        !          1154: 
        !          1155:        space = port_name_to_space(task);
        !          1156:        if (space == IS_NULL)
        !          1157:                return MACH_SEND_INTERRUPTED;
        !          1158: 
        !          1159:        if (!MACH_MSG_TYPE_PORT_ANY(rightType)) {
        !          1160:                is_release(space);
        !          1161:                return KERN_INVALID_VALUE;
        !          1162:        }
        !          1163: 
        !          1164:        if (MACH_PORT_VALID(right)) {
        !          1165:                kr = ipc_object_copyin(current_space(), right, rightType,
        !          1166:                                       &object);
        !          1167:                if (kr != KERN_SUCCESS) {
        !          1168:                        is_release(space);
        !          1169:                        return kr;
        !          1170:                }
        !          1171:        } else
        !          1172:                object = (ipc_object_t) right;
        !          1173:        newtype = ipc_object_copyin_type(rightType);
        !          1174: 
        !          1175:        kr = mach_port_insert_right(space, name, object, newtype);
        !          1176:        if ((kr != KERN_SUCCESS) && IO_VALID(object))
        !          1177:                ipc_object_destroy(object, newtype);
        !          1178:        is_release(space);
        !          1179: 
        !          1180:        return kr;
        !          1181: }
        !          1182: 
        !          1183: kern_return_t syscall_thread_depress_abort(thread)
        !          1184:        mach_port_t     thread;
        !          1185: {
        !          1186:        thread_t        t;
        !          1187:        kern_return_t   result;
        !          1188: 
        !          1189:        t = port_name_to_thread(thread);
        !          1190:        if (t == THREAD_NULL)
        !          1191:                return MACH_SEND_INTERRUPTED;
        !          1192: 
        !          1193:        result = thread_depress_abort(t);
        !          1194:        thread_deallocate(t);
        !          1195: 
        !          1196:        return result;
        !          1197: }
        !          1198: 
        !          1199: #endif

unix.superglobalmegacorp.com

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