The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/ipc_mig.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        ipc_mig.c,v $
   29  * Revision 2.23  93/11/17  17:11:36  dbg
   30  *      Moved syscall_timer_sleep to kern/mach_timer.c
   31  *      [93/07/21            dbg]
   32  * 
   33  *      Add traps for timers and real-time threads.
   34  *      [93/07/13            dbg]
   35  * 
   36  *      Use thread_lock instead of ith_lock.
   37  *      [93/07/12            dbg]
   38  * 
   39  *      Added ANSI function prototypes.  Removed unneeded routines:
   40  *      thread_{get,set}_state_KERNEL.  Conditionalized mach_msg,
   41  *      mig_get_reply_port, mig_dealloc_reply_port on NORMA_TASK
   42  *      || NORMA_VM.
   43  *      [93/03/30            dbg]
   44  * 
   45  * Revision 2.22  93/08/10  15:11:34  mrt
   46  *      Fixed the case where device write traps are called with reply ports.
   47  *      [93/07/29            cmaeda]
   48  * 
   49  *      Device traps and scatter/gather IO (actually just gather IO) --
   50  *      Added port_name_to_device, syscall_device_write_request,
   51  *      and syscall_device_writev_request.
   52  *      (Original version of this code from rfr, many moons ago.)
   53  *      [93/04/14            cmaeda]
   54  * 
   55  * Revision 2.21  93/03/26  17:54:47  mrt
   56  *      Merge botch got rid of the above.
   57  *      [93/03/23            af]
   58  * 
   59  * Revision 2.20  93/01/14  17:34:34  danner
   60  *      64bit cleanup.
   61  *      [92/12/01            af]
   62  * 
   63  * Revision 2.19  92/08/03  17:37:30  jfriedl
   64  *      removed silly prototypes
   65  *      [92/08/02            jfriedl]
   66  * 
   67  * Revision 2.18  92/05/21  17:13:55  jfriedl
   68  *      Removed unsed var 'addr' from syscall_vm_deallocate.
   69  *      [92/05/16            jfriedl]
   70  * 
   71  * Revision 2.17  92/03/10  16:26:34  jsb
   72  *      Corrected log.
   73  *      [91/12/24  14:42:53  jsb]
   74  * 
   75  * Revision 2.16  92/02/19  16:06:28  elf
   76  *      Added syscall_thread_depress_abort.
   77  *      [92/01/20            rwd]
   78  * 
   79  * Revision 2.15  91/11/14  16:56:39  rpd
   80  *      Replaced call to ipc_kmsg_copyout_dest with ipc_kmsg_copyout_to_kernel
   81  *      in mach_msg_rpc_from_kernel, to preserve rights and memory.
   82  *      [91/11/00            jsb]
   83  * 
   84  * Revision 2.14  91/08/28  11:14:34  jsb
   85  *      Fixed syscall_mach_port_insert_right and syscall_task_set_special_port
   86  *      to handle non-valid port names correctly.
   87  *      [91/08/15            rpd]
   88  * 
   89  *      Changed MACH_RCV_TOO_LARGE and MACH_RCV_INVALID_NOTIFY to work
   90  *      like MACH_RCV_HEADER_ERROR, using ipc_kmsg_copyout_dest.
   91  *      [91/08/12            rpd]
   92  * 
   93  *      Added seqno argument to ipc_mqueue_receive.
   94  *      [91/08/10            rpd]
   95  *      Conditionalize mach_msg_rpc_from_kernel on NORMA_VM, not NORMA_TASK.
   96  *      [91/08/14  18:34:30  jsb]
   97  * 
   98  * Revision 2.13  91/08/03  18:18:53  jsb
   99  *      Corrected comment for mach_msg_send_from_kernel.
  100  *      [91/07/04  10:08:23  jsb]
  101  * 
  102  * Revision 2.12  91/07/30  15:45:43  rvb
  103  *      Fixed syscall_vm_map to handle non-valid memory objects correctly.
  104  *      [91/07/12            rpd]
  105  * 
  106  * Revision 2.11  91/06/17  15:47:05  jsb
  107  *      Renamed NORMA conditionals.
  108  *      [91/06/17  10:50:07  jsb]
  109  * 
  110  * Revision 2.10  91/06/06  17:07:09  jsb
  111  *      NORMA_TASK: We still need mach_msg_rpc_from_kernel.
  112  *      [91/05/14  09:13:45  jsb]
  113  * 
  114  * Revision 2.9  91/05/20  22:22:16  rpd
  115  *      Cleaned up the semantics of the syscall forms of kernel RPCs.
  116  *      [91/05/20            rpd]
  117  * 
  118  * Revision 2.8  91/05/14  16:42:22  mrt
  119  *      Correcting copyright
  120  * 
  121  * Revision 2.7  91/02/05  17:26:46  mrt
  122  *      Changed to new Mach copyright
  123  *      [91/02/01  16:13:09  mrt]
  124  * 
  125  * Revision 2.6  91/01/08  15:15:44  rpd
  126  *      Don't need mach_msg_rpc_from_kernel.
  127  *      [90/12/26            rpd]
  128  *      Updated ipc_mqueue_receive calls.
  129  *      [90/11/21            rpd]
  130  *      Removed MACH_IPC_GENNOS.
  131  *      [90/11/09            rpd]
  132  * 
  133  * Revision 2.5  90/11/05  14:30:59  rpd
  134  *      Changed ip_reference to ipc_port_reference.
  135  *      Changed ip_release to ipc_port_release.
  136  *      Removed ipc_object_release_macro.
  137  *      Use new ip_reference and ip_release.
  138  *      [90/10/29            rpd]
  139  * 
  140  * Revision 2.4  90/09/09  14:32:13  rpd
  141  *      Added mach_port_allocate_name.
  142  *      [90/09/03            rwd]
  143  * 
  144  * Revision 2.3  90/06/19  22:58:57  rpd
  145  *      Optimized port_name_to_task, port_name_to_thread, etc.
  146  *      [90/06/03            rpd]
  147  * 
  148  *      Added mach_port_allocate, mach_port_deallocate, mach_port_insert_right.
  149  *      [90/06/02            rpd]
  150  * 
  151  * Revision 2.2  90/06/02  14:54:16  rpd
  152  *      Moved trap versions of kernel calls here
  153  *      from vm/vm_user.c, kern/task.c.
  154  *      Converted them to new IPC.
  155  *      [90/05/31            rpd]
  156  * 
  157  *      Created for new IPC.
  158  *      [90/03/26  23:47:15  rpd]
  159  * 
  160  */
  161 
  162 #include <mach_rt.h>
  163 #include <norma_ipc.h>
  164 #include <norma_task.h>
  165 #include <norma_vm.h>
  166 
  167 #include <mach/boolean.h>
  168 #include <mach/port.h>
  169 #include <mach/message.h>
  170 #include <mach/thread_status.h>
  171 #include <kern/ast.h>
  172 #include <kern/ipc_tt.h>
  173 #include <kern/memory.h>
  174 #include <kern/syscall_subr.h>
  175 #include <kern/thread.h>
  176 #include <kern/task.h>
  177 #include <kern/rt_thread.h>
  178 #include <kern/ipc_kobject.h>
  179 #include <vm/vm_map.h>
  180 #include <vm/vm_user.h>
  181 #include <ipc/port.h>
  182 #include <ipc/ipc_kmsg.h>
  183 #include <ipc/ipc_entry.h>
  184 #include <ipc/ipc_object.h>
  185 #include <ipc/ipc_mqueue.h>
  186 #include <ipc/ipc_space.h>
  187 #include <ipc/ipc_port.h>
  188 #include <ipc/ipc_pset.h>
  189 #include <ipc/ipc_thread.h>
  190 #include <device/device_types.h>
  191 
  192 
  193 /*
  194  *      Routine:        mach_msg_send_from_kernel
  195  *      Purpose:
  196  *              Send a message from the kernel.
  197  *
  198  *              This is used by the client side of KernelUser interfaces
  199  *              to implement SimpleRoutines.  Currently, this includes
  200  *              device_reply and memory_object messages.
  201  *      Conditions:
  202  *              Nothing locked.
  203  *      Returns:
  204  *              MACH_MSG_SUCCESS        Sent the message.
  205  *              MACH_SEND_INVALID_DATA  Bad destination port.
  206  */
  207 
  208 mach_msg_return_t
  209 mach_msg_send_from_kernel(
  210         mach_msg_header_t *msg,
  211         mach_msg_size_t send_size)
  212 {
  213         ipc_kmsg_t kmsg;
  214         mach_msg_return_t mr;
  215 
  216         if (!MACH_PORT_VALID(msg->msgh_remote_port))
  217                 return MACH_SEND_INVALID_DEST;
  218 
  219         mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
  220         if (mr != MACH_MSG_SUCCESS)
  221                 panic("mach_msg_send_from_kernel");
  222 
  223         ipc_kmsg_copyin_from_kernel(kmsg);
  224         ipc_mqueue_send_always(kmsg);
  225 
  226         return MACH_MSG_SUCCESS;
  227 }
  228 
  229 #if     NORMA_VM
  230 /*
  231  *      Routine:        mach_msg_rpc_from_kernel
  232  *      Purpose:
  233  *              Send a message from the kernel and receive a reply.
  234  *              Uses ith_rpc_reply for the reply port.
  235  *
  236  *              This is used by the client side of KernelUser interfaces
  237  *              to implement Routines.  Currently, this is only
  238  *              used by norma code.
  239  *      Conditions:
  240  *              Nothing locked.
  241  *      Returns:
  242  *              MACH_MSG_SUCCESS        Sent the message.
  243  *              MACH_RCV_PORT_DIED      The reply port was deallocated.
  244  */
  245 
  246 mach_msg_return_t
  247 mach_msg_rpc_from_kernel(
  248         mach_msg_header_t *msg,
  249         mach_msg_size_t send_size,
  250         mach_msg_size_t rcv_size)
  251 {
  252         ipc_thread_t self = current_thread();
  253         ipc_port_t reply;
  254         ipc_kmsg_t kmsg;
  255         mach_port_seqno_t seqno;
  256         mach_msg_return_t mr;
  257 
  258         assert(MACH_PORT_VALID(msg->msgh_remote_port));
  259         assert(msg->msgh_local_port == MACH_PORT_NULL);
  260 
  261         mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
  262         if (mr != MACH_MSG_SUCCESS)
  263                 panic("mach_msg_rpc_from_kernel");
  264 
  265         ipc_kmsg_copyin_from_kernel(kmsg);
  266 
  267         thread_lock(self);
  268         assert(self->active);
  269 
  270         reply = self->ith_rpc_reply;
  271         if (reply == IP_NULL) {
  272                 thread_unlock(self);
  273                 reply = ipc_port_alloc_reply();
  274                 thread_lock(self);
  275                 if ((reply == IP_NULL) ||
  276                     (self->ith_rpc_reply != IP_NULL))
  277                         panic("mach_msg_rpc_from_kernel");
  278                 self->ith_rpc_reply = reply;
  279         }
  280 
  281         /* insert send-once right for the reply port */
  282         kmsg->ikm_header.msgh_local_port =
  283                 (mach_port_t) ipc_port_make_sonce(reply);
  284 
  285         ipc_port_reference(reply);
  286         thread_unlock(self);
  287 
  288         ipc_mqueue_send_always(kmsg);
  289 
  290         for (;;) {
  291                 ipc_mqueue_t mqueue;
  292 
  293                 ip_lock(reply);
  294                 if (!ip_active(reply)) {
  295                         ip_unlock(reply);
  296                         ipc_port_release(reply);
  297                         return MACH_RCV_PORT_DIED;
  298                 }
  299 
  300                 assert(reply->ip_pset == IPS_NULL);
  301                 mqueue = &reply->ip_messages;
  302                 imq_lock(mqueue);
  303                 ip_unlock(reply);
  304 
  305                 mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
  306                                         MACH_MSG_SIZE_MAX,
  307                                         MACH_MSG_TIMEOUT_NONE,
  308                                         FALSE, CONTINUE_NULL,
  309                                         &kmsg, &seqno);
  310                 /* mqueue is unlocked */
  311                 if (mr == MACH_MSG_SUCCESS)
  312                         break;
  313 
  314                 assert((mr == MACH_RCV_INTERRUPTED) ||
  315                        (mr == MACH_RCV_PORT_DIED));
  316 
  317                 if (self->ast & AST_HALT) {
  318                         thread_halt_self(CONTINUE_NULL);
  319                 }
  320                 if (self->ast & AST_TERMINATE) {
  321                         /* don't terminate while holding a reference */
  322                         ipc_port_release(reply);
  323                         thread_terminate_self();
  324                 }
  325         }
  326         ipc_port_release(reply);
  327 
  328         kmsg->ikm_header.msgh_seqno = seqno;
  329 
  330         if (rcv_size < kmsg->ikm_header.msgh_size) {
  331                 ipc_kmsg_copyout_dest(kmsg, ipc_space_reply);
  332                 ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
  333                 return MACH_RCV_TOO_LARGE;
  334         }
  335 
  336         /*
  337          *      We want to preserve rights and memory in reply!
  338          *      We don't have to put them anywhere; just leave them
  339          *      as they are.
  340          */
  341 
  342         ipc_kmsg_copyout_to_kernel(kmsg, ipc_space_reply);
  343         ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
  344         return MACH_MSG_SUCCESS;
  345 }
  346 #endif  /* NORMA_VM */
  347 
  348 /*
  349  *      Routine:        mach_msg_abort_rpc
  350  *      Purpose:
  351  *              Destroy the thread's ith_rpc_reply port.
  352  *              This will interrupt a mach_msg_rpc_from_kernel
  353  *              with a MACH_RCV_PORT_DIED return code.
  354  *      Conditions:
  355  *              Nothing locked.
  356  */
  357 
  358 void
  359 mach_msg_abort_rpc(
  360         ipc_thread_t thread)
  361 {
  362         ipc_port_t reply = IP_NULL;
  363 
  364         thread_lock(thread);
  365         if (thread->active) {
  366                 reply = thread->ith_rpc_reply;
  367                 thread->ith_rpc_reply = IP_NULL;
  368         }
  369         thread_unlock(thread);
  370 
  371         if (reply != IP_NULL)
  372                 ipc_port_dealloc_reply(reply);
  373 }
  374 
  375 #if     NORMA_TASK || NORMA_VM
  376 /*
  377  *      Routine:        mach_msg
  378  *      Purpose:
  379  *              Like mach_msg_trap except that message buffers
  380  *              live in kernel space.  Doesn't handle any options.
  381  *
  382  *              This is used by in-kernel server threads to make
  383  *              kernel calls, to receive request messages, and
  384  *              to send reply messages.  Currently, this is
  385  *              only used by NORMA code.
  386  *      Conditions:
  387  *              Nothing locked.
  388  *      Returns:
  389  */
  390 
  391 mach_msg_return_t
  392 mach_msg(
  393         mach_msg_header_t *msg,
  394         mach_msg_option_t option,
  395         mach_msg_size_t send_size,
  396         mach_msg_size_t rcv_size,
  397         mach_port_t rcv_name,
  398         mach_msg_timeout_t time_out,
  399         mach_port_t notify)
  400 {
  401         ipc_space_t space = current_space();
  402         vm_map_t map = current_map();
  403         ipc_kmsg_t kmsg;
  404         mach_port_seqno_t seqno;
  405         mach_msg_return_t mr;
  406 
  407         if (option & MACH_SEND_MSG) {
  408                 mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
  409                 if (mr != MACH_MSG_SUCCESS)
  410                         panic("mach_msg");
  411 
  412                 mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
  413                 if (mr != MACH_MSG_SUCCESS) {
  414                         ikm_free(kmsg);
  415                         return mr;
  416                 }
  417 
  418                 do
  419                         mr = ipc_mqueue_send(kmsg, MACH_MSG_OPTION_NONE,
  420                                              MACH_MSG_TIMEOUT_NONE);
  421                 while (mr == MACH_SEND_INTERRUPTED);
  422                 assert(mr == MACH_MSG_SUCCESS);
  423         }
  424 
  425         if (option & MACH_RCV_MSG) {
  426                 do {
  427                         ipc_object_t object;
  428                         ipc_mqueue_t mqueue;
  429 
  430                         mr = ipc_mqueue_copyin(space, rcv_name,
  431                                                &mqueue, &object);
  432                         if (mr != MACH_MSG_SUCCESS)
  433                                 return mr;
  434                         /* hold ref for object; mqueue is locked */
  435 
  436                         mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
  437                                                 MACH_MSG_SIZE_MAX,
  438                                                 MACH_MSG_TIMEOUT_NONE,
  439                                                 FALSE, CONTINUE_NULL,
  440                                                 &kmsg, &seqno);
  441                         /* mqueue is unlocked */
  442                         ipc_object_release(object);
  443                 } while (mr == MACH_RCV_INTERRUPTED);
  444                 if (mr != MACH_MSG_SUCCESS)
  445                         return mr;
  446 
  447                 kmsg->ikm_header.msgh_seqno = seqno;
  448 
  449                 if (rcv_size < kmsg->ikm_header.msgh_size) {
  450                         ipc_kmsg_copyout_dest(kmsg, space);
  451                         ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
  452                         return MACH_RCV_TOO_LARGE;
  453                 }
  454 
  455                 mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
  456                 if (mr != MACH_MSG_SUCCESS) {
  457                         if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
  458                                 ipc_kmsg_put_to_kernel(msg, kmsg,
  459                                                 kmsg->ikm_header.msgh_size);
  460                         } else {
  461                                 ipc_kmsg_copyout_dest(kmsg, space);
  462                                 ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
  463                         }
  464 
  465                         return mr;
  466                 }
  467 
  468                 ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
  469         }
  470 
  471         return MACH_MSG_SUCCESS;
  472 }
  473 
  474 /*
  475  *      Routine:        mig_get_reply_port
  476  *      Purpose:
  477  *              Called by client side interfaces living in the kernel
  478  *              to get a reply port.  This port is used for
  479  *              mach_msg() calls which are kernel calls.
  480  */
  481 
  482 mach_port_t
  483 mig_get_reply_port(void)
  484 {
  485         ipc_thread_t self = current_thread();
  486 
  487         if (self->ith_mig_reply == MACH_PORT_NULL)
  488                 self->ith_mig_reply = mach_reply_port();
  489 
  490         return self->ith_mig_reply;
  491 }
  492 
  493 /*
  494  *      Routine:        mig_dealloc_reply_port
  495  *      Purpose:
  496  *              Called by client side interfaces to get rid of a reply port.
  497  *              Shouldn't ever be called inside the kernel, because
  498  *              kernel calls shouldn't prompt Mig to call it.
  499  */
  500 
  501 void
  502 mig_dealloc_reply_port(mach_port_t port)
  503 {
  504         panic("mig_dealloc_reply_port");
  505 }
  506 #endif  /* NORMA_TASK || NORMA_VM */
  507 
  508 /*
  509  * mig_strncpy.c - by Joshua Block
  510  *
  511  * mig_strncp -- Bounded string copy.  Does what the library routine strncpy
  512  * OUGHT to do:  Copies the (null terminated) string in src into dest, a 
  513  * buffer of length len.  Assures that the copy is still null terminated
  514  * and doesn't overflow the buffer, truncating the copy if necessary.
  515  *
  516  * Parameters:
  517  * 
  518  *     dest - Pointer to destination buffer.
  519  * 
  520  *     src - Pointer to source string.
  521  * 
  522  *     len - Length of destination buffer.
  523  */
  524 void mig_strncpy(
  525         char *dest,
  526         char *src,
  527         int len)
  528 {
  529     int i;
  530 
  531     if (len <= 0)
  532         return;
  533 
  534     for (i=1; i<len; i++)
  535         if (! (*dest++ = *src++))
  536             return;
  537 
  538     *dest = '\0';
  539     return;
  540 }
  541 
  542 #define fast_send_right_lookup(name, port, abort)                       \
  543 MACRO_BEGIN                                                             \
  544         register ipc_space_t space = current_space();                   \
  545         register ipc_entry_t entry;                                     \
  546         register mach_port_index_t index = MACH_PORT_INDEX(name);       \
  547                                                                         \
  548         is_read_lock(space);                                            \
  549         assert(space->is_active);                                       \
  550                                                                         \
  551         if ((index >= space->is_table_size) ||                          \
  552             (((entry = &space->is_table[index])->ie_bits &              \
  553               (IE_BITS_GEN_MASK|MACH_PORT_TYPE_SEND)) !=                \
  554              (MACH_PORT_GEN(name) | MACH_PORT_TYPE_SEND))) {            \
  555                 is_read_unlock(space);                                  \
  556                 abort;                                                  \
  557         }                                                               \
  558                                                                         \
  559         port = (ipc_port_t) entry->ie_object;                           \
  560         assert(port != IP_NULL);                                        \
  561                                                                         \
  562         ip_lock(port);                                                  \
  563         /* can safely unlock space now that port is locked */           \
  564         is_read_unlock(space);                                          \
  565 MACRO_END
  566 
  567 device_t
  568 port_name_to_device(
  569         mach_port_t name)
  570 {
  571         register ipc_port_t port;
  572         register device_t device;
  573  
  574         fast_send_right_lookup(name, port, goto abort);
  575         /* port is locked */
  576  
  577         /*
  578          * Now map the port object to a device object.
  579          * This is an inline version of dev_port_lookup().
  580          */
  581         if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
  582                 device = (device_t) port->ip_kobject;
  583                 device_reference(device);
  584                 ip_unlock(port);
  585                 return device;                  
  586         }
  587  
  588         ip_unlock(port);
  589         return DEVICE_NULL;
  590  
  591        /*
  592         * The slow case.  The port wasn't easily accessible.
  593         */
  594     abort: {
  595             ipc_port_t kern_port;
  596             kern_return_t kr;
  597            
  598             kr = ipc_object_copyin(current_space(), name,
  599                                    MACH_MSG_TYPE_COPY_SEND,
  600                                    (ipc_object_t *) &kern_port);
  601             if (kr != KERN_SUCCESS)
  602                     return DEVICE_NULL;
  603  
  604             device = dev_port_lookup(kern_port);
  605             if (IP_VALID(kern_port))
  606                     ipc_port_release_send(kern_port);
  607             return device;
  608     }
  609 }
  610 
  611 thread_t
  612 port_name_to_thread(
  613         mach_port_t name)
  614 {
  615         register ipc_port_t port;
  616 
  617         fast_send_right_lookup(name, port, goto abort);
  618         /* port is locked */
  619 
  620         if (ip_active(port) &&
  621             (ip_kotype(port) == IKOT_THREAD)) {
  622                 register thread_t thread;
  623 
  624                 thread = (thread_t) port->ip_kobject;
  625                 assert(thread != THREAD_NULL);
  626 
  627                 /* thread referencing is a bit complicated,
  628                    so don't bother to expand inline */
  629                 thread_reference(thread);
  630                 ip_unlock(port);
  631 
  632                 return thread;
  633         }
  634 
  635         ip_unlock(port);
  636         return THREAD_NULL;
  637 
  638     abort: {
  639         thread_t thread;
  640         ipc_port_t kern_port;
  641         kern_return_t kr;
  642 
  643         kr = ipc_object_copyin(current_space(), name,
  644                                MACH_MSG_TYPE_COPY_SEND,
  645                                (ipc_object_t *) &kern_port);
  646         if (kr != KERN_SUCCESS)
  647                 return THREAD_NULL;
  648 
  649         thread = convert_port_to_thread(kern_port);
  650         if (IP_VALID(kern_port))
  651                 ipc_port_release_send(kern_port);
  652 
  653         return thread;
  654     }
  655 }
  656 
  657 task_t
  658 port_name_to_task(
  659         mach_port_t name)
  660 {
  661         register ipc_port_t port;
  662 
  663         fast_send_right_lookup(name, port, goto abort);
  664         /* port is locked */
  665 
  666         if (ip_active(port) &&
  667             (ip_kotype(port) == IKOT_TASK)) {
  668                 register task_t task;
  669 
  670                 task = (task_t) port->ip_kobject;
  671                 assert(task != TASK_NULL);
  672 
  673                 task_lock(task);
  674                 /* can safely unlock port now that task is locked */
  675                 ip_unlock(port);
  676 
  677                 task->ref_count++;
  678                 task_unlock(task);
  679 
  680                 return task;
  681         }
  682 
  683         ip_unlock(port);
  684         return TASK_NULL;
  685 
  686     abort: {
  687         task_t task;
  688         ipc_port_t kern_port;
  689         kern_return_t kr;
  690 
  691         kr = ipc_object_copyin(current_space(), name,
  692                                MACH_MSG_TYPE_COPY_SEND,
  693                                (ipc_object_t *) &kern_port);
  694         if (kr != KERN_SUCCESS)
  695                 return TASK_NULL;
  696 
  697         task = convert_port_to_task(kern_port);
  698         if (IP_VALID(kern_port))
  699                 ipc_port_release_send(kern_port);
  700 
  701         return task;
  702     }
  703 }
  704 
  705 vm_map_t
  706 port_name_to_map(
  707         mach_port_t name)
  708 {
  709         register ipc_port_t port;
  710 
  711         fast_send_right_lookup(name, port, goto abort);
  712         /* port is locked */
  713 
  714         if (ip_active(port) &&
  715             (ip_kotype(port) == IKOT_TASK)) {
  716                 register vm_map_t map;
  717 
  718                 map = ((task_t) port->ip_kobject)->map;
  719                 assert(map != VM_MAP_NULL);
  720 
  721                 simple_lock(&map->ref_lock);
  722                 /* can safely unlock port now that map is locked */
  723                 ip_unlock(port);
  724 
  725                 map->ref_count++;
  726                 simple_unlock(&map->ref_lock);
  727 
  728                 return map;
  729         }
  730 
  731         ip_unlock(port);
  732         return VM_MAP_NULL;
  733 
  734     abort: {
  735         vm_map_t map;
  736         ipc_port_t kern_port;
  737         kern_return_t kr;
  738 
  739         kr = ipc_object_copyin(current_space(), name,
  740                                MACH_MSG_TYPE_COPY_SEND,
  741                                (ipc_object_t *) &kern_port);
  742         if (kr != KERN_SUCCESS)
  743                 return VM_MAP_NULL;
  744 
  745         map = convert_port_to_map(kern_port);
  746         if (IP_VALID(kern_port))
  747                 ipc_port_release_send(kern_port);
  748 
  749         return map;
  750     }
  751 }
  752 
  753 ipc_space_t
  754 port_name_to_space(
  755         mach_port_t name)
  756 {
  757         register ipc_port_t port;
  758 
  759         fast_send_right_lookup(name, port, goto abort);
  760         /* port is locked */
  761 
  762         if (ip_active(port) &&
  763             (ip_kotype(port) == IKOT_TASK)) {
  764                 register ipc_space_t space;
  765 
  766                 space = ((task_t) port->ip_kobject)->itk_space;
  767                 assert(space != IS_NULL);
  768 
  769                 simple_lock(&space->is_ref_lock_data);
  770                 /* can safely unlock port now that space is locked */
  771                 ip_unlock(port);
  772 
  773                 space->is_references++;
  774                 simple_unlock(&space->is_ref_lock_data);
  775 
  776                 return space;
  777         }
  778 
  779         ip_unlock(port);
  780         return IS_NULL;
  781 
  782     abort: {
  783         ipc_space_t space;
  784         ipc_port_t kern_port;
  785         kern_return_t kr;
  786 
  787         kr = ipc_object_copyin(current_space(), name,
  788                                MACH_MSG_TYPE_COPY_SEND,
  789                                (ipc_object_t *) &kern_port);
  790         if (kr != KERN_SUCCESS)
  791                 return IS_NULL;
  792 
  793         space = convert_port_to_space(kern_port);
  794         if (IP_VALID(kern_port))
  795                 ipc_port_release_send(kern_port);
  796 
  797         return space;
  798     }
  799 }
  800 
  801 mach_timer_t
  802 port_name_to_timer(
  803         mach_port_t     name)
  804 {
  805         register ipc_port_t port;
  806 
  807         fast_send_right_lookup(name, port, goto abort);
  808         /* port is locked */
  809 
  810         if (ip_active(port) &&
  811             (ip_kotype(port) == IKOT_TIMER)) {
  812                 register mach_timer_t timer;
  813 
  814                 timer = (mach_timer_t) port->ip_kobject;
  815                 assert(timer != TIMER_NULL);
  816 
  817                 timer_ref_lock(timer);
  818                 timer->tm_ref_count++;
  819                 timer_ref_unlock(timer);
  820 
  821                 ip_unlock(port);
  822 
  823                 return timer;
  824         }
  825 
  826         ip_unlock(port);
  827         return TIMER_NULL;
  828 
  829     abort: {
  830         mach_timer_t timer;
  831         ipc_port_t kern_port;
  832         kern_return_t kr;
  833 
  834         kr = ipc_object_copyin(current_space(), name,
  835                                MACH_MSG_TYPE_COPY_SEND,
  836                                (ipc_object_t *) &kern_port);
  837         if (kr != KERN_SUCCESS)
  838                 return TIMER_NULL;
  839 
  840         timer = convert_port_to_timer(kern_port);
  841         if (IP_VALID(kern_port))
  842                 ipc_port_release_send(kern_port);
  843 
  844         return timer;
  845     }
  846 }
  847 
  848 /*
  849  *      Things to keep in mind:
  850  *
  851  *      The idea here is to duplicate the semantics of the true kernel RPC.
  852  *      The destination port/object should be checked first, before anything
  853  *      that the user might notice (like ipc_object_copyin).  Return
  854  *      MACH_SEND_INTERRUPTED if it isn't correct, so that the user stub
  855  *      knows to fall back on an RPC.  For other return values, it won't
  856  *      retry with an RPC.  The retry might get a different (incorrect) rc.
  857  *      Return values are only set (and should only be set, with copyout)
  858  *      on successfull calls.
  859  */
  860 
  861 kern_return_t syscall_vm_map(
  862         mach_port_t     target_map,
  863         vm_offset_t     *address,
  864         vm_size_t       size,
  865         vm_offset_t     mask,
  866         boolean_t       anywhere,
  867         mach_port_t     memory_object,
  868         vm_offset_t     offset,
  869         boolean_t       copy,
  870         vm_prot_t       cur_protection,
  871         vm_prot_t       max_protection,
  872         vm_inherit_t    inheritance)
  873 {
  874         vm_map_t                map;
  875         ipc_port_t              port;
  876         vm_offset_t             addr;
  877         kern_return_t           result;
  878 
  879         map = port_name_to_map(target_map);
  880         if (map == VM_MAP_NULL)
  881                 return MACH_SEND_INTERRUPTED;
  882 
  883         if (MACH_PORT_VALID(memory_object)) {
  884                 result = ipc_object_copyin(current_space(), memory_object,
  885                                            MACH_MSG_TYPE_COPY_SEND,
  886                                            (ipc_object_t *) &port);
  887                 if (result != KERN_SUCCESS) {
  888                         vm_map_deallocate(map);
  889                         return result;
  890                 }
  891         } else
  892                 port = (ipc_port_t) memory_object;
  893 
  894         copyin((char *)address, (char *)&addr, sizeof(vm_offset_t));
  895         result = vm_map(map, &addr, size, mask, anywhere,
  896                         port, offset, copy,
  897                         cur_protection, max_protection, inheritance);
  898         if (result == KERN_SUCCESS)
  899                 copyout((char *)&addr, (char *)address, sizeof(vm_offset_t));
  900         if (IP_VALID(port))
  901                 ipc_port_release_send(port);
  902         vm_map_deallocate(map);
  903 
  904         return result;
  905 }
  906 
  907 kern_return_t syscall_vm_allocate(
  908         mach_port_t             target_map,
  909         vm_offset_t             *address,
  910         vm_size_t               size,
  911         boolean_t               anywhere)
  912 {
  913         vm_map_t                map;
  914         vm_offset_t             addr;
  915         kern_return_t           result;
  916 
  917         map = port_name_to_map(target_map);
  918         if (map == VM_MAP_NULL)
  919                 return MACH_SEND_INTERRUPTED;
  920 
  921         copyin((char *)address, (char *)&addr, sizeof(vm_offset_t));
  922         result = vm_allocate(map, &addr, size, anywhere);
  923         if (result == KERN_SUCCESS)
  924                 copyout((char *)&addr, (char *)address, sizeof(vm_offset_t));
  925         vm_map_deallocate(map);
  926 
  927         return result;
  928 }
  929 
  930 kern_return_t syscall_vm_deallocate(
  931         mach_port_t             target_map,
  932         vm_offset_t             start,
  933         vm_size_t               size)
  934 {
  935         vm_map_t                map;
  936         kern_return_t           result;
  937 
  938         map = port_name_to_map(target_map);
  939         if (map == VM_MAP_NULL)
  940                 return MACH_SEND_INTERRUPTED;
  941 
  942         result = vm_deallocate(map, start, size);
  943         vm_map_deallocate(map);
  944 
  945         return result;
  946 }
  947 
  948 kern_return_t syscall_task_create(
  949         mach_port_t     parent_task,
  950         boolean_t       inherit_memory,
  951         mach_port_t     *child_task)            /* OUT */
  952 {
  953         task_t          t, c;
  954         ipc_port_t      port;
  955         mach_port_t     name;
  956         kern_return_t   result;
  957 
  958         t = port_name_to_task(parent_task);
  959         if (t == TASK_NULL)
  960                 return MACH_SEND_INTERRUPTED;
  961 
  962         result = task_create(t, inherit_memory, &c);
  963         if (result == KERN_SUCCESS) {
  964                 port = (ipc_port_t) convert_task_to_port(c);
  965                 /* always returns a name, even for non-success return codes */
  966                 (void) ipc_kmsg_copyout_object(current_space(),
  967                                                (ipc_object_t) port,
  968                                                MACH_MSG_TYPE_PORT_SEND, &name);
  969                 copyout((char *)&name, (char *)child_task,
  970                         sizeof(mach_port_t));
  971         }
  972         task_deallocate(t);
  973 
  974         return result;
  975 }
  976 
  977 kern_return_t syscall_task_terminate(
  978         mach_port_t     task)
  979 {
  980         task_t          t;
  981         kern_return_t   result;
  982 
  983         t = port_name_to_task(task);
  984         if (t == TASK_NULL)
  985                 return MACH_SEND_INTERRUPTED;
  986 
  987         result = task_terminate(t);
  988         task_deallocate(t);
  989 
  990         return result;
  991 }
  992 
  993 kern_return_t syscall_task_suspend(
  994         mach_port_t     task)
  995 {
  996         task_t          t;
  997         kern_return_t   result;
  998 
  999         t = port_name_to_task(task);
 1000         if (t == TASK_NULL)
 1001                 return MACH_SEND_INTERRUPTED;
 1002 
 1003         result = task_suspend(t);
 1004         task_deallocate(t);
 1005 
 1006         return result;
 1007 }
 1008 
 1009 kern_return_t syscall_task_set_special_port(
 1010         mach_port_t     task,
 1011         int             which_port,
 1012         mach_port_t     port_name)
 1013 {
 1014         task_t          t;
 1015         ipc_port_t      port;
 1016         kern_return_t   result;
 1017 
 1018         t = port_name_to_task(task);
 1019         if (t == TASK_NULL)
 1020                 return MACH_SEND_INTERRUPTED;
 1021 
 1022         if (MACH_PORT_VALID(port_name)) {
 1023                 result = ipc_object_copyin(current_space(), port_name,
 1024                                            MACH_MSG_TYPE_COPY_SEND,
 1025                                            (ipc_object_t *) &port);
 1026                 if (result != KERN_SUCCESS) {
 1027                         task_deallocate(t);
 1028                         return result;
 1029                 }
 1030         } else
 1031                 port = (ipc_port_t) port_name;
 1032 
 1033         result = task_set_special_port(t, which_port, port);
 1034         if ((result != KERN_SUCCESS) && IP_VALID(port))
 1035                 ipc_port_release_send(port);
 1036         task_deallocate(t);
 1037 
 1038         return result;
 1039 }
 1040 
 1041 kern_return_t
 1042 syscall_mach_port_allocate(
 1043         mach_port_t task,
 1044         mach_port_right_t right,
 1045         mach_port_t *namep)
 1046 {
 1047         ipc_space_t space;
 1048         mach_port_t name;
 1049         kern_return_t kr;
 1050 
 1051         space = port_name_to_space(task);
 1052         if (space == IS_NULL)
 1053                 return MACH_SEND_INTERRUPTED;
 1054 
 1055         kr = mach_port_allocate(space, right, &name);
 1056         if (kr == KERN_SUCCESS)
 1057                 copyout((char *)&name, (char *)namep, sizeof(mach_port_t));
 1058         is_release(space);
 1059 
 1060         return kr;
 1061 }
 1062 
 1063 kern_return_t
 1064 syscall_mach_port_allocate_name(
 1065         mach_port_t task,
 1066         mach_port_right_t right,
 1067         mach_port_t name)
 1068 {
 1069         ipc_space_t space;
 1070         kern_return_t kr;
 1071 
 1072         space = port_name_to_space(task);
 1073         if (space == IS_NULL)
 1074                 return MACH_SEND_INTERRUPTED;
 1075 
 1076         kr = mach_port_allocate_name(space, right, name);
 1077         is_release(space);
 1078 
 1079         return kr;
 1080 }
 1081 
 1082 kern_return_t
 1083 syscall_mach_port_deallocate(
 1084         mach_port_t task,
 1085         mach_port_t name)
 1086 {
 1087         ipc_space_t space;
 1088         kern_return_t kr;
 1089 
 1090         space = port_name_to_space(task);
 1091         if (space == IS_NULL)
 1092                 return MACH_SEND_INTERRUPTED;
 1093 
 1094         kr = mach_port_deallocate(space, name);
 1095         is_release(space);
 1096 
 1097         return kr;
 1098 }
 1099 
 1100 kern_return_t
 1101 syscall_mach_port_insert_right(
 1102         mach_port_t task,
 1103         mach_port_t name,
 1104         mach_port_t right,
 1105         mach_msg_type_name_t rightType)
 1106 {
 1107         ipc_space_t space;
 1108         ipc_object_t object;
 1109         mach_msg_type_name_t newtype;
 1110         kern_return_t kr;
 1111 
 1112         space = port_name_to_space(task);
 1113         if (space == IS_NULL)
 1114                 return MACH_SEND_INTERRUPTED;
 1115 
 1116         if (!MACH_MSG_TYPE_PORT_ANY(rightType)) {
 1117                 is_release(space);
 1118                 return KERN_INVALID_VALUE;
 1119         }
 1120 
 1121         if (MACH_PORT_VALID(right)) {
 1122                 kr = ipc_object_copyin(current_space(), right, rightType,
 1123                                        &object);
 1124                 if (kr != KERN_SUCCESS) {
 1125                         is_release(space);
 1126                         return kr;
 1127                 }
 1128         } else
 1129                 object = (ipc_object_t) right;
 1130         newtype = ipc_object_copyin_type(rightType);
 1131 
 1132         kr = mach_port_insert_right(space, name, object, newtype);
 1133         if ((kr != KERN_SUCCESS) && IO_VALID(object))
 1134                 ipc_object_destroy(object, newtype);
 1135         is_release(space);
 1136 
 1137         return kr;
 1138 }
 1139 
 1140 kern_return_t syscall_thread_depress_abort(
 1141         mach_port_t     thread)
 1142 {
 1143         thread_t        t;
 1144         kern_return_t   result;
 1145 
 1146         t = port_name_to_thread(thread);
 1147         if (t == THREAD_NULL)
 1148                 return MACH_SEND_INTERRUPTED;
 1149 
 1150         result = thread_depress_abort(t);
 1151         thread_deallocate(t);
 1152 
 1153         return result;
 1154 }
 1155 
 1156 kern_return_t syscall_timer_arm(
 1157         mach_port_t     timer,
 1158         time_spec_t     expire_time,
 1159         time_spec_t     interval_time,
 1160         mach_port_t     expire_port,
 1161         mach_port_t     thread,
 1162         int             flags)
 1163 {
 1164         mach_timer_t    tm;
 1165         ipc_port_t      ex_port;
 1166         thread_t        th;
 1167         kern_return_t   result;
 1168 
 1169         tm = port_name_to_timer(timer);
 1170         if (tm == TIMER_NULL)
 1171                 return MACH_SEND_INTERRUPTED;
 1172 
 1173         if (MACH_PORT_VALID(thread)) {
 1174                 th = port_name_to_thread(thread);
 1175                 if (th == THREAD_NULL) {
 1176                         mach_timer_deallocate(tm);
 1177                         return KERN_INVALID_ARGUMENT;
 1178                 }
 1179         }
 1180         else {
 1181                 th = THREAD_NULL;
 1182         }
 1183         if (MACH_PORT_VALID(expire_port)) {
 1184                 result = ipc_object_copyin(current_space(), expire_port,
 1185                                            MACH_MSG_TYPE_COPY_SEND,
 1186                                            (ipc_object_t *) &ex_port);
 1187                 if (result != KERN_SUCCESS) {
 1188                         thread_deallocate(th);
 1189                         mach_timer_deallocate(tm);
 1190                         return result;
 1191                 }
 1192         }
 1193         else
 1194                 ex_port = (ipc_port_t) expire_port;
 1195 
 1196         result = timer_arm(tm, expire_time, interval_time,
 1197                         ex_port, th, flags);
 1198 
 1199         if (result != KERN_SUCCESS && IP_VALID(ex_port))
 1200                 ipc_port_release_send(ex_port);
 1201         thread_deallocate(th);
 1202         mach_timer_deallocate(tm);
 1203 
 1204         return result;
 1205 }
 1206 
 1207 kern_return_t syscall_timer_cancel(
 1208         mach_port_t     timer,
 1209         int             flags)
 1210 {
 1211         mach_timer_t    tm;
 1212         kern_return_t   result;
 1213 
 1214         tm = port_name_to_timer(timer);
 1215         if (tm == TIMER_NULL)
 1216                 return MACH_SEND_INTERRUPTED;
 1217 
 1218         result = timer_cancel(tm, flags);
 1219 
 1220         mach_timer_deallocate(tm);
 1221 
 1222         return result;
 1223 }
 1224 
 1225 kern_return_t syscall_periodic_thread_restart(
 1226         mach_port_t     thread)
 1227 {
 1228         thread_t        t;
 1229         kern_return_t   result;
 1230 
 1231         t = port_name_to_thread(thread);
 1232         if (t == THREAD_NULL)
 1233                 return MACH_SEND_INTERRUPTED;
 1234 
 1235         result = periodic_thread_restart(t);
 1236         thread_deallocate(t);
 1237 
 1238         return result;
 1239 }
 1240 
 1241 
 1242 /*
 1243  * Device traps -- these are way experimental.
 1244  */
 1245 
 1246 extern io_return_t ds_device_write_trap();
 1247 extern io_return_t ds_device_writev_trap();
 1248 
 1249 io_return_t
 1250 syscall_device_write_request(mach_port_t        device_name,
 1251                              mach_port_t        reply_name,
 1252                              dev_mode_t         mode,
 1253                              recnum_t           recnum,
 1254                              vm_offset_t        data,
 1255                              vm_size_t          data_count)
 1256 {
 1257         device_t        dev;
 1258         ipc_port_t      reply_port;
 1259         io_return_t     res;
 1260 
 1261         /*
 1262          * First try to translate the device name.
 1263          *
 1264          * If this fails, return KERN_INVALID_CAPABILITY.
 1265          * Caller knows that this most likely means that
 1266          * device is not local to node and IPC should be used.
 1267          *
 1268          * If kernel doesn't do device traps, kern_invalid()
 1269          * will be called instead of this function which will
 1270          * return KERN_INVALID_ARGUMENT.
 1271          */
 1272         dev = port_name_to_device(device_name);
 1273         if (dev == DEVICE_NULL)
 1274                 return KERN_INVALID_CAPABILITY;
 1275 
 1276         /*
 1277          * Translate reply port.
 1278          */
 1279         if (reply_name == MACH_PORT_NULL)
 1280                 reply_port = IP_NULL;
 1281         else {
 1282                 /* Homey don't play that. */
 1283                 device_deallocate(dev);
 1284                 return KERN_INVALID_RIGHT;
 1285         }
 1286 
 1287         /* note: doesn't take reply_port arg yet. */
 1288         res = ds_device_write_trap(dev, /*reply_port,*/
 1289                                    mode, recnum,
 1290                                    data, data_count);
 1291 
 1292         /*
 1293          * Give up reference from port_name_to_device.
 1294          */
 1295         device_deallocate(dev);
 1296         return res;
 1297 }
 1298 
 1299 io_return_t
 1300 syscall_device_writev_request(mach_port_t       device_name,
 1301                               mach_port_t       reply_name,
 1302                               dev_mode_t        mode,
 1303                               recnum_t          recnum,
 1304                               io_buf_vec_t      *iovec,
 1305                               vm_size_t         iocount)
 1306 {
 1307         device_t        dev;
 1308         ipc_port_t      reply_port;
 1309         io_return_t     res;
 1310 
 1311         /*
 1312          * First try to translate the device name.
 1313          *
 1314          * If this fails, return KERN_INVALID_CAPABILITY.
 1315          * Caller knows that this most likely means that
 1316          * device is not local to node and IPC should be used.
 1317          *
 1318          * If kernel doesn't do device traps, kern_invalid()
 1319          * will be called instead of this function which will
 1320          * return KERN_INVALID_ARGUMENT.
 1321          */
 1322         dev = port_name_to_device(device_name);
 1323         if (dev == DEVICE_NULL)
 1324                 return KERN_INVALID_CAPABILITY;
 1325 
 1326         /*
 1327          * Translate reply port.
 1328          */
 1329         if (reply_name == MACH_PORT_NULL)
 1330                 reply_port = IP_NULL;
 1331         else {
 1332                 /* Homey don't play that. */
 1333                 device_deallocate(dev);
 1334                 return KERN_INVALID_RIGHT;
 1335         }
 1336 
 1337         /* note: doesn't take reply_port arg yet. */
 1338         res = ds_device_writev_trap(dev, /*reply_port,*/
 1339                                     mode, recnum,
 1340                                     iovec, iocount);
 1341 
 1342         /*
 1343          * Give up reference from port_name_to_device.
 1344          */
 1345         device_deallocate(dev);
 1346         return res;
 1347 }
 1348 
 1349 

Cache object: ed814ce3fb818b65d533345b8f295632


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.