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_kobject.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) 1991,1990,1989 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_kobject.c,v $
   29  * Revision 2.15  93/01/24  13:19:00  danner
   30  *      Introduce Mach4 interface.  Initially for pc sampling.
   31  *      [93/01/11            rvb]
   32  * 
   33  * Revision 2.14  92/08/03  17:37:23  jfriedl
   34  *      removed silly prototypes
   35  *      [92/08/02            jfriedl]
   36  * 
   37  * Revision 2.13  92/05/21  17:13:47  jfriedl
   38  *      Made correct for when assert is off.
   39  *      [92/05/16            jfriedl]
   40  * 
   41  * Revision 2.12  92/03/10  16:26:28  jsb
   42  *      Add IKOT_PAGER_TERMINATING case to ipc_kobject_destroy.
   43  *      [92/02/25            dlb]
   44  *      Added ipc_kobject_notify for kernel-requested notifications.
   45  *      Added code to correctly release send-once kobject destinations.
   46  *      [92/01/21  18:20:19  jsb]
   47  * 
   48  * Revision 2.11  92/01/03  20:14:32  dbg
   49  *      Call <subsystem>_routine_name to find IPC stub to execute.
   50  *      Build reply message header by hand. (XXX)
   51  *      Simplify cleanup of request message when reply is success.
   52  *      [91/12/18            dbg]
   53  * 
   54  * Revision 2.10  91/12/13  13:42:24  jsb
   55  *      Added support for norma/norma_internal.defs.
   56  * 
   57  * Revision 2.9  91/08/01  14:36:18  dbg
   58  *      Call machine-dependent interface routine, under
   59  *      MACH_MACHINE_ROUTINES.
   60  *      [91/08/01            dbg]
   61  * 
   62  * Revision 2.8  91/06/17  15:47:02  jsb
   63  *      Renamed NORMA conditionals. Added NORMA_VM support.
   64  *      [91/06/17  13:46:55  jsb]
   65  * 
   66  * Revision 2.7  91/06/06  17:07:05  jsb
   67  *      Added NORMA_TASK support.
   68  *      [91/05/14  09:05:48  jsb]
   69  * 
   70  * Revision 2.6  91/05/18  14:31:42  rpd
   71  *      Added check_simple_locks.
   72  *      [91/04/01            rpd]
   73  * 
   74  * Revision 2.5  91/05/14  16:42:00  mrt
   75  *      Correcting copyright
   76  * 
   77  * Revision 2.4  91/03/16  14:50:02  rpd
   78  *      Replaced ith_saved with ikm_cache.
   79  *      [91/02/16            rpd]
   80  * 
   81  * Revision 2.3  91/02/05  17:26:37  mrt
   82  *      Changed to new Mach copyright
   83  *      [91/02/01  16:12:51  mrt]
   84  * 
   85  * Revision 2.2  90/06/02  14:54:08  rpd
   86  *      Created for new IPC.
   87  *      [90/03/26  23:46:53  rpd]
   88  * 
   89  */
   90 /*
   91  *      File:   kern/ipc_kobject.c
   92  *      Author: Rich Draves
   93  *      Date:   1989
   94  *
   95  *      Functions for letting a port represent a kernel object.
   96  */
   97 
   98 #include <mach_debug.h>
   99 #include <mach_ipc_test.h>
  100 #include <mach_machine_routines.h>
  101 #include <norma_task.h>
  102 #include <norma_vm.h>
  103 
  104 #include <mach/port.h>
  105 #include <mach/kern_return.h>
  106 #include <mach/message.h>
  107 #include <mach/mig_errors.h>
  108 #include <mach/notify.h>
  109 #include <kern/ipc_kobject.h>
  110 #include <ipc/ipc_object.h>
  111 #include <ipc/ipc_kmsg.h>
  112 #include <ipc/ipc_port.h>
  113 #include <ipc/ipc_thread.h>
  114 
  115 #if     MACH_MACHINE_ROUTINES
  116 #include <machine/machine_routines.h>
  117 #endif
  118 
  119 
  120 /*
  121  *      Routine:        ipc_kobject_server
  122  *      Purpose:
  123  *              Handle a message sent to the kernel.
  124  *              Generates a reply message.
  125  *      Conditions:
  126  *              Nothing locked.
  127  */
  128 
  129 ipc_kmsg_t
  130 ipc_kobject_server(request)
  131         ipc_kmsg_t request;
  132 {
  133         mach_msg_size_t reply_size = ikm_less_overhead(8192);
  134         ipc_kmsg_t reply;
  135         kern_return_t kr;
  136         mig_routine_t routine;
  137         ipc_port_t *destp;
  138 
  139         reply = ikm_alloc(reply_size);
  140         if (reply == IKM_NULL) {
  141                 printf("ipc_kobject_server: dropping request\n");
  142                 ipc_kmsg_destroy(request);
  143                 return IKM_NULL;
  144         }
  145         ikm_init(reply, reply_size);
  146 
  147         /*
  148          * Initialize reply message.
  149          */
  150         {
  151 #define InP     ((mach_msg_header_t *) &request->ikm_header)
  152 #define OutP    ((mig_reply_header_t *) &reply->ikm_header)
  153 
  154             static mach_msg_type_t RetCodeType = {
  155                 /* msgt_name = */               MACH_MSG_TYPE_INTEGER_32,
  156                 /* msgt_size = */               32,
  157                 /* msgt_number = */             1,
  158                 /* msgt_inline = */             TRUE,
  159                 /* msgt_longform = */           FALSE,
  160                 /* msgt_unused = */             0
  161             };
  162             OutP->Head.msgh_bits =
  163                 MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
  164             OutP->Head.msgh_size = sizeof(mig_reply_header_t);
  165             OutP->Head.msgh_remote_port = InP->msgh_local_port;
  166             OutP->Head.msgh_local_port  = MACH_PORT_NULL;
  167             OutP->Head.msgh_seqno = 0;
  168             OutP->Head.msgh_id = InP->msgh_id + 100;
  169 
  170             OutP->RetCodeType = RetCodeType;
  171 
  172 #undef  InP
  173 #undef  OutP
  174         }
  175 
  176         /*
  177          * Find the server routine to call, and call it
  178          * to perform the kernel function
  179          */
  180     {
  181         extern mig_routine_t    mach_server_routine(),
  182                                 mach_port_server_routine(),
  183                                 mach_host_server_routine(),
  184                                 device_server_routine(),
  185                                 device_pager_server_routine(),
  186                                 mach4_server_routine();
  187 #if     MACH_DEBUG
  188         extern mig_routine_t    mach_debug_server_routine();
  189 #endif
  190 #if     NORMA_TASK
  191         extern mig_routine_t    mach_norma_server_routine();
  192         extern mig_routine_t    norma_internal_server_routine();
  193 #endif
  194 #if     NORMA_VM
  195         extern mig_routine_t    proxy_server_routine();
  196 #endif
  197 
  198 #if     MACH_MACHINE_ROUTINES
  199         extern mig_routine_t    MACHINE_SERVER_ROUTINE();
  200 #endif
  201 
  202         check_simple_locks();
  203         if ((routine = mach_server_routine(&request->ikm_header)) != 0
  204          || (routine = mach_port_server_routine(&request->ikm_header)) != 0
  205          || (routine = mach_host_server_routine(&request->ikm_header)) != 0
  206          || (routine = device_server_routine(&request->ikm_header)) != 0
  207          || (routine = device_pager_server_routine(&request->ikm_header)) != 0
  208 #if     MACH_DEBUG
  209          || (routine = mach_debug_server_routine(&request->ikm_header)) != 0
  210 #endif  MACH_DEBUG
  211 #if     NORMA_TASK
  212          || (routine = mach_norma_server_routine(&request->ikm_header)) != 0
  213          || (routine = norma_internal_server_routine(&request->ikm_header)) != 0
  214 #endif  NORMA_TASK
  215 #if     NORMA_VM
  216          || (routine = proxy_server_routine(&request->ikm_header)) != 0
  217 #endif  NORMA_VM
  218          || (routine = mach4_server_routine(&request->ikm_header)) != 0
  219 #if     MACH_MACHINE_ROUTINES
  220          || (routine = MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0
  221 #endif  MACH_MACHINE_ROUTINES
  222         ) {
  223             (*routine)(&request->ikm_header, &reply->ikm_header);
  224         }
  225         else if (!ipc_kobject_notify(&request->ikm_header,&reply->ikm_header)){
  226                 ((mig_reply_header_t *) &reply->ikm_header)->RetCode
  227                     = MIG_BAD_ID;
  228 #if     MACH_IPC_TEST
  229                 printf("ipc_kobject_server: bogus kernel message, id=%d\n",
  230                        request->ikm_header.msgh_id);
  231 #endif  MACH_IPC_TEST
  232         }
  233     }
  234         check_simple_locks();
  235 
  236         /*
  237          *      Destroy destination. The following code differs from
  238          *      ipc_object_destroy in that we release the send-once
  239          *      right instead of generating a send-once notification
  240          *      (which would bring us here again, creating a loop).
  241          *      It also differs in that we only expect send or
  242          *      send-once rights, never receive rights.
  243          *
  244          *      We set msgh_remote_port to IP_NULL so that the kmsg
  245          *      destroy routines don't try to destroy the port twice.
  246          */
  247         destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port;
  248         switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) {
  249                 case MACH_MSG_TYPE_PORT_SEND:
  250                 ipc_port_release_send(*destp);
  251                 break;
  252                 
  253                 case MACH_MSG_TYPE_PORT_SEND_ONCE:
  254                 ipc_port_release_sonce(*destp);
  255                 break;
  256                 
  257                 default:
  258 #if MACH_ASSERT
  259                 assert(!"ipc_object_destroy: strange destination rights");
  260 #else
  261                 panic("ipc_object_destroy: strange destination rights");
  262 #endif
  263         }
  264         *destp = IP_NULL;
  265 
  266         kr = ((mig_reply_header_t *) &reply->ikm_header)->RetCode;
  267         if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
  268                 /*
  269                  *      The server function is responsible for the contents
  270                  *      of the message.  The reply port right is moved
  271                  *      to the reply message, and we have deallocated
  272                  *      the destination port right, so we just need
  273                  *      to free the kmsg.
  274                  */
  275 
  276                 /* like ipc_kmsg_put, but without the copyout */
  277 
  278                 ikm_check_initialized(request, request->ikm_size);
  279                 if ((request->ikm_size == IKM_SAVED_KMSG_SIZE) &&
  280                     (ikm_cache() == IKM_NULL))
  281                         ikm_cache() = request;
  282                 else
  283                         ikm_free(request);
  284         } else {
  285                 /*
  286                  *      The message contents of the request are intact.
  287                  *      Destroy everthing except the reply port right,
  288                  *      which is needed in the reply message.
  289                  */
  290 
  291                 request->ikm_header.msgh_local_port = MACH_PORT_NULL;
  292                 ipc_kmsg_destroy(request);
  293         }
  294 
  295         if (kr == MIG_NO_REPLY) {
  296                 /*
  297                  *      The server function will send a reply message
  298                  *      using the reply port right, which it has saved.
  299                  */
  300 
  301                 ikm_free(reply);
  302                 return IKM_NULL;
  303         } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) {
  304                 /*
  305                  *      Can't queue the reply message if the destination
  306                  *      (the reply port) isn't valid.
  307                  */
  308 
  309                 ipc_kmsg_destroy(reply);
  310                 return IKM_NULL;
  311         }
  312 
  313         return reply;
  314 }
  315 
  316 /*
  317  *      Routine:        ipc_kobject_set
  318  *      Purpose:
  319  *              Make a port represent a kernel object of the given type.
  320  *              The caller is responsible for handling refs for the
  321  *              kernel object, if necessary.
  322  *      Conditions:
  323  *              Nothing locked.  The port must be active.
  324  */
  325 
  326 void
  327 ipc_kobject_set(port, kobject, type)
  328         ipc_port_t port;
  329         ipc_kobject_t kobject;
  330         ipc_kobject_type_t type;
  331 {
  332         ip_lock(port);
  333         assert(ip_active(port));
  334         port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type;
  335         port->ip_kobject = kobject;
  336         ip_unlock(port);
  337 }
  338 
  339 /*
  340  *      Routine:        ipc_kobject_destroy
  341  *      Purpose:
  342  *              Release any kernel object resources associated
  343  *              with the port, which is being destroyed.
  344  *
  345  *              This should only be needed when resources are
  346  *              associated with a user's port.  In the normal case,
  347  *              when the kernel is the receiver, the code calling
  348  *              ipc_port_dealloc_kernel should clean up the resources.
  349  *      Conditions:
  350  *              The port is not locked, but it is dead.
  351  */
  352 
  353 void
  354 ipc_kobject_destroy(port)
  355         ipc_port_t port;
  356 {
  357         switch (ip_kotype(port)) {
  358             case IKOT_PAGER:
  359                 vm_object_destroy(port);
  360                 break;
  361 
  362             case IKOT_PAGER_TERMINATING:
  363                 vm_object_pager_wakeup(port);
  364                 break;
  365 
  366             default:
  367 #if     MACH_ASSERT
  368                 printf("ipc_kobject_destroy: port 0x%x, kobj 0x%x, type %d\n",
  369                        port, port->ip_kobject, ip_kotype(port));
  370 #endif  MACH_ASSERT
  371                 break;
  372         }
  373 }
  374 
  375 /*
  376  *      Routine:        ipc_kobject_notify
  377  *      Purpose:
  378  *              Deliver notifications to kobjects that care about them.
  379  */
  380 
  381 boolean_t
  382 ipc_kobject_notify(request_header, reply_header)
  383         mach_msg_header_t *request_header;
  384         mach_msg_header_t *reply_header;
  385 {
  386         ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port;
  387 
  388         ((mig_reply_header_t *) reply_header)->RetCode = MIG_NO_REPLY;
  389         switch (request_header->msgh_id) {
  390                 case MACH_NOTIFY_PORT_DELETED:
  391                 case MACH_NOTIFY_MSG_ACCEPTED:
  392                 case MACH_NOTIFY_PORT_DESTROYED:
  393                 case MACH_NOTIFY_NO_SENDERS:
  394                 case MACH_NOTIFY_SEND_ONCE:
  395                 case MACH_NOTIFY_DEAD_NAME:
  396                 break;
  397 
  398                 default:
  399                 return FALSE;
  400         }
  401         switch (ip_kotype(port)) {
  402 #if     NORMA_VM
  403                 case IKOT_XMM_OBJECT:
  404                 return xmm_object_notify(request_header);
  405 
  406                 case IKOT_XMM_PAGER:
  407                 return xmm_pager_notify(request_header);
  408 
  409                 case IKOT_XMM_KERNEL:
  410                 return xmm_kernel_notify(request_header);
  411 
  412                 case IKOT_XMM_REPLY:
  413                 return xmm_reply_notify(request_header);
  414 #endif  NORMA_VM
  415 
  416                 case IKOT_DEVICE:
  417                 return ds_notify(request_header);
  418 
  419                 default:
  420                 return FALSE;
  421         }
  422 }

Cache object: 7140ede940663e00244204f5621b64c3


[ 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.