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/norma/ipc_clean.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 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_clean.c,v $
   29  * Revision 2.2  92/03/10  16:27:19  jsb
   30  *      Merged in norma branch changes as of NORMA_MK7.
   31  *      [92/03/09  12:48:39  jsb]
   32  * 
   33  * Revision 2.1.2.3  92/02/21  11:24:11  jsb
   34  *      Moved ipc_kmsg_uncopyout_to_network here from ipc/ipc_kmsg.c.
   35  *      Separated norma_ipc_uncopyout_all_kmsgs out from
   36  *      norma_ipc_dead_destination (renamed from norma_ipc_destroy_proxy).
   37  *      [92/02/21  10:38:49  jsb]
   38  * 
   39  *      Eliminated norma_ipc_unsend_*_dest, since norma_ipc_send_*_dest
   40  *      is no longer called until and unless message is successfully
   41  *      received. Added check to ensure that destroyed proxy has queued
   42  *      messages. Added call to norma_port_remove before call to
   43  *      ipc_port_destroy. Removed zeroing of ip_seqno.
   44  *      [92/02/18  08:44:28  jsb]
   45  * 
   46  * Revision 2.1.2.2  92/01/21  21:51:00  jsb
   47  *      De-linted.
   48  *      [92/01/16  21:31:56  jsb]
   49  * 
   50  * Revision 2.1.2.1  92/01/03  08:57:08  jsb
   51  *      First NORMA branch checkin.
   52  * 
   53  * Revision 2.1.1.3  91/12/31  21:36:40  jsb
   54  *      Changed ndproxy macros to nsproxy.
   55  * 
   56  * Revision 2.1.1.2  91/12/31  12:11:04  jsb
   57  *      Changed remote_port handling in norma_ipc_destroy_proxy to account
   58  *      for remote consumption of send-once right (if any) in first kmsg.
   59  *      Added ipc_kmsg_uncopyout_to_network, which is given remote_port which
   60  *      it in turn hands to norma_ipc_unsend{_migrating,}_dest, which now
   61  *      use this port instead of trying to look it up based on uid.
   62  *      Changes for IP_NORMA_REQUEST macros being renamed to ip_ndproxy{,m,p}.
   63  * 
   64  * Revision 2.1.1.1  91/12/29  21:42:51  jsb
   65  *      First checkin.
   66  * 
   67  */ 
   68 /*
   69  *      File:   norma/ipc_clean.c
   70  *      Author: Joseph S. Barrera III
   71  *      Date:   1991
   72  *
   73  *      Routines to clean messages sent to the network.
   74  */
   75 
   76 #include <ipc/ipc_port.h>
   77 #include <ipc/ipc_kmsg.h>
   78 
   79 extern ipc_port_t norma_port_lookup();
   80 extern ipc_port_t norma_ipc_receive_soright();
   81 extern ipc_port_t norma_ipc_receive_sright();
   82 
   83 extern ipc_port_t norma_ipc_unsend_port();
   84 extern ipc_port_t norma_ipc_unsend_soright();
   85 extern ipc_port_t norma_ipc_unsend_sright();
   86 extern ipc_port_t norma_ipc_unsend_rright();
   87 extern void norma_ipc_unsend_dest();
   88 extern void norma_ipc_unsend_migrating_dest();
   89 
   90 /*
   91  * These unsend routines should undo the effects of the send routines above.
   92  */
   93 
   94 ipc_port_t
   95 norma_ipc_unsend_port(uid, type_name)
   96         unsigned long uid;
   97         mach_msg_type_name_t type_name;
   98 {
   99         if (type_name == MACH_MSG_TYPE_PORT_SEND_ONCE) {
  100                 return norma_ipc_unsend_soright(uid);
  101         } else if (type_name == MACH_MSG_TYPE_PORT_SEND) {
  102                 return norma_ipc_unsend_sright(uid);
  103         } else if (type_name == MACH_MSG_TYPE_PORT_RECEIVE) {
  104                 return norma_ipc_unsend_rright(uid);
  105         } else {
  106                 panic("norma_ipc_unsend_port: bad type %d\n", type_name);
  107                 /* NOTREACHED */
  108         }
  109 }
  110 
  111 ipc_port_t
  112 norma_ipc_unsend_soright(uid)
  113         unsigned long uid;
  114 {
  115         return norma_ipc_receive_soright(uid);
  116 }
  117 
  118 ipc_port_t
  119 norma_ipc_unsend_sright(uid)
  120         unsigned long uid;
  121 {
  122         return norma_ipc_receive_sright(uid);
  123 }
  124 
  125 ipc_port_t
  126 norma_ipc_unsend_rright(uid)
  127         unsigned long uid;
  128 {
  129         ipc_port_t port;
  130 
  131         port = norma_port_lookup(uid);
  132         if (port == IP_NULL) {
  133                 return IP_NULL;
  134         }
  135         if (! ip_active(port)) {
  136                 return IP_DEAD;
  137         }
  138         assert(! port->ip_norma_is_proxy);
  139         ip_reference(port);
  140         return port;
  141 }
  142 
  143 void
  144 ipc_kmsg_uncopyout_header_to_network(msgh, dest)
  145         mach_msg_header_t *msgh;
  146         ipc_port_t dest;
  147 {
  148         /*
  149          * Uncopy local port
  150          */
  151         if (msgh->msgh_local_port) {
  152                 register mach_msg_type_name_t type;
  153 
  154                 type = MACH_MSGH_BITS_LOCAL(msgh->msgh_bits);
  155                 type = ipc_object_copyin_type(type);
  156                 msgh->msgh_local_port = (mach_port_t)
  157                     norma_ipc_unsend_port((unsigned long)msgh->msgh_local_port,
  158                                           type);
  159         }
  160 
  161         /*
  162          * Uncopy remote port
  163          */
  164         assert(msgh->msgh_remote_port == (mach_port_t) dest->ip_norma_uid);
  165         msgh->msgh_remote_port = (mach_port_t) dest;
  166 }
  167 
  168 void
  169 ipc_kmsg_uncopyout_to_network(kmsg)
  170         ipc_kmsg_t kmsg;
  171 {
  172         vm_offset_t saddr, eaddr;
  173 
  174         if ((kmsg->ikm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0) {
  175                 return;
  176         }
  177 
  178         kmsg->ikm_header.msgh_bits &= ~ (MACH_MSGH_BITS_COMPLEX_DATA |
  179                                          MACH_MSGH_BITS_COMPLEX_PORTS |
  180                                          MACH_MSGH_BITS_MIGRATED);
  181 
  182         saddr = (vm_offset_t) (&kmsg->ikm_header + 1);
  183         eaddr = (vm_offset_t) &kmsg->ikm_header + kmsg->ikm_header.msgh_size;
  184 
  185         while (saddr < eaddr) {
  186                 mach_msg_type_long_t *type;
  187                 mach_msg_type_name_t name;
  188                 mach_msg_type_size_t size;
  189                 mach_msg_type_number_t number;
  190                 boolean_t is_inline, longform, is_port;
  191                 vm_offset_t data;
  192                 vm_size_t length;
  193 
  194                 type = (mach_msg_type_long_t *) saddr;
  195                 is_inline = type->msgtl_header.msgt_inline;
  196                 longform = type->msgtl_header.msgt_longform;
  197                 /* type->msgtl_header.msgt_deallocate not used */
  198                 if (longform) {
  199                         name = type->msgtl_name;
  200                         size = type->msgtl_size;
  201                         number = type->msgtl_number;
  202                         saddr += sizeof(mach_msg_type_long_t);
  203                 } else {
  204                         name = type->msgtl_header.msgt_name;
  205                         size = type->msgtl_header.msgt_size;
  206                         number = type->msgtl_header.msgt_number;
  207                         saddr += sizeof(mach_msg_type_t);
  208                 }
  209 
  210                 /* calculate length of data in bytes, rounding up */
  211 
  212                 length = ((number * size) + 7) >> 3;
  213 
  214                 is_port = MACH_MSG_TYPE_PORT_ANY(name);
  215 
  216                 if (is_inline) {
  217                         /* inline data sizes round up to int boundaries */
  218 
  219                         data = saddr;
  220                         saddr += (length + 3) &~ 3;
  221                 } else if (is_port) {
  222                         /*
  223                          * Not a copy object, just a kernel address.
  224                          */
  225                         data = * (vm_offset_t *) saddr;
  226                         saddr += sizeof(vm_offset_t);
  227                 } else {
  228                         /*
  229                          * This is a copy object.
  230                          * It is okay to leave copy objects in page-list form.
  231                          * The netipc module is responsible for leaving them
  232                          * in a sane state.
  233                          */
  234                         saddr += sizeof(vm_offset_t);
  235                 }
  236 
  237                 if (is_port) {
  238                         ipc_port_t *ports = (ipc_port_t *) data;
  239                         mach_msg_type_number_t i;
  240 
  241                         /*
  242                          * Convert uids into ports and undo refcount action.
  243                          */
  244                         for (i = 0; i < number; i++) {
  245                                 ports[i] =
  246                                     norma_ipc_unsend_port((unsigned long)
  247                                                           ports[i], name);
  248                         }
  249                 }
  250         }
  251 }
  252 
  253 /*
  254  * Convert all kmsgs queued on port from network to internal format.
  255  */
  256 void
  257 norma_ipc_uncopyout_all_kmsgs(port)
  258         ipc_port_t port;
  259 {
  260         register ipc_kmsg_t kmsg;
  261         register ipc_kmsg_queue_t kmsgs;
  262 
  263         kmsgs = &port->ip_messages.imq_messages;
  264         kmsg = ipc_kmsg_queue_first(kmsgs);
  265         if (kmsg != IKM_NULL) do {
  266                 printf1("uncopyout ksmg=0x%x msgh_id=%d; was s=%d so=%d\n",
  267                         kmsg, kmsg->ikm_header.msgh_id,
  268                         port->ip_srights, port->ip_sorights);
  269 
  270                 /*
  271                  * Uncopy header
  272                  */
  273                 ipc_kmsg_uncopyout_header_to_network(&kmsg->ikm_header, port);
  274 
  275                 /*
  276                  * Uncopy body
  277                  */
  278                 ipc_kmsg_uncopyout_to_network(kmsg);
  279 
  280                 /*
  281                  * Move to next kmsg
  282                  */
  283                 kmsg = kmsg->ikm_next;
  284         } while (kmsg != ipc_kmsg_queue_first(kmsgs));
  285 }
  286 
  287 /*
  288  * Called when a send to a remote port returns a notification that
  289  * the port is dead.
  290  */
  291 norma_ipc_dead_destination(port)
  292         ipc_port_t port;
  293 {
  294         ipc_kmsg_t kmsg;
  295         mach_port_rights_t sorights;
  296 
  297         printf1("norma_ipc_dead_destination: 0x%x:%x refs %d\n",
  298                 port, port->ip_norma_uid, port->ip_references);
  299 
  300         assert(port->ip_norma_is_proxy);
  301         assert(port->ip_references > 0);
  302 
  303         /*
  304          * Convert all kmsgs from network to internal format.
  305          * XXX
  306          * We need to lock to prevent anyone else from
  307          * queueing ports from this point.
  308          */
  309         norma_ipc_uncopyout_all_kmsgs(port);
  310 
  311         /*
  312          * The remote kernel counts us as having consumed one send-once
  313          * right, if our destination right was a send-once right.
  314          * This reduces how often we need to call norma_ipc_yield_rights.
  315          */
  316         kmsg = ipc_kmsg_queue_first(&port->ip_messages.imq_messages);
  317         assert(kmsg != IKM_NULL);
  318         if (MACH_MSGH_BITS_REMOTE(kmsg->ikm_header.msgh_bits) ==
  319             MACH_MSG_TYPE_PORT_SEND_ONCE) {
  320                 sorights = port->ip_sorights - 1;
  321         } else {
  322                 sorights = port->ip_sorights;
  323         }
  324 
  325         printf1("*** That's really s=%d so=%d\n", port->ip_srights, sorights);
  326 
  327         if (port->ip_srights > 0 || sorights > 0) {
  328                 printf("dead_destination(0x%x) s=%d so=%d st=%d (leak)\n",
  329                        port,
  330                        port->ip_srights,
  331                        port->ip_sorights,
  332                        - port->ip_norma_stransit);
  333 #if 0
  334                 /* XXX */
  335                 norma_ipc_yield_rights(0, -port->ip_stransit, sorights);
  336 #endif
  337         }
  338 
  339         /*
  340          * Remove port from proxy list before destroying it.
  341          */
  342         norma_port_remove(port);
  343 
  344         /*
  345          * Fiddle with fields to make ipc_port_destroy happy, then call it.
  346          */
  347         assert(ip_nsproxyp(port->ip_nsrequest));
  348         port->ip_nsrequest = IP_NULL;
  349         printf1("dead_destination: 0x%x:%x: about to destroy port\n",
  350                 port, port->ip_norma_uid);
  351         ipc_port_destroy(port);
  352         printf1("dead_destination: 0x%x:%x: destroyed port\n",
  353                 port, port->ip_norma_uid);
  354 }

Cache object: 62fc81347bf95ba110e69625032d2466


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