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_special.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 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_special.c,v $
   29  * Revision 2.4  92/03/10  16:28:17  jsb
   30  *      Merged in norma branch changes as of NORMA_MK7.
   31  *      [92/03/09  12:50:20  jsb]
   32  * 
   33  * Revision 2.3.2.4  92/02/18  19:16:34  jeffreyh
   34  *      Use IP_NORMA_IS_PROXY macro instead of checking for norma_uid
   35  *      in norma_port_location_hint.  The latter gives the wrong
   36  *      answer if the port has been exported and we're not node 0.
   37  *      [92/02/14            dlb]
   38  * 
   39  * Revision 2.3.2.3  92/01/21  21:52:33  jsb
   40  *      More de-linting.
   41  *      [92/01/17  11:41:55  jsb]
   42  * 
   43  *      De-linted.
   44  *      [92/01/16  22:14:38  jsb]
   45  * 
   46  * Revision 2.3.2.2  92/01/09  18:45:51  jsb
   47  *      Removed placeholder logic.
   48  *      Added remote_{special,device,host,host_priv} routines.
   49  *      [92/01/04  18:35:52  jsb]
   50  * 
   51  * Revision 2.3.2.1  92/01/03  16:37:58  jsb
   52  *      Corrected log. Removed norma_token_startup call. Fixed type clash.
   53  *      [91/12/24  14:26:15  jsb]
   54  * 
   55  * Revision 2.2  91/11/14  16:48:12  rpd
   56  *      Moved from norma/ipc_xxx.c.
   57  * 
   58  * Revision 2.5  91/08/28  11:16:15  jsb
   59  *      Renamed clport things to norma things.
   60  *      Eliminated NORMA_ETHER special case node/lid uid division.
   61  *      [91/08/15  09:14:06  jsb]
   62  * 
   63  *      Renamed ipc_clport_foo things to norma_ipc_foo.
   64  *      Added host_port_at_node().
   65  *      [91/08/14  19:21:16  jsb]
   66  * 
   67  * Revision 2.4  91/08/03  18:19:34  jsb
   68  *      Conditionalized printfs.
   69  *      [91/08/01  22:55:17  jsb]
   70  * 
   71  *      Eliminated dynamically allocated clport structures; this information
   72  *      is now stored in ports directly. This simplifies issues of allocation
   73  *      at interrupt time.
   74  * 
   75  *      Added definitions for IP_CLPORT_{NODE,LID} appropriate for using the
   76  *      low two bytes of an internet address as a node number.
   77  * 
   78  *      Revised norma_special_port mechanism to better handle port death
   79  *      and port replacement. Eliminated redundant special port calls.
   80  *      Cleaned up associated startup code.
   81  *      [91/07/25  19:09:16  jsb]
   82  * 
   83  * Revision 2.3  91/07/01  08:25:52  jsb
   84  *      Some locking changes.
   85  *      [91/06/29  15:10:46  jsb]
   86  * 
   87  * Revision 2.2  91/06/17  15:48:05  jsb
   88  *      Moved here from ipc/ipc_clport.c.
   89  *      [91/06/17  11:07:25  jsb]
   90  * 
   91  * Revision 2.7  91/06/06  17:05:35  jsb
   92  *      Added norma_get_special_port, norma_set_special_port.
   93  *      [91/05/25  10:28:14  jsb]
   94  * 
   95  *      Much code moved to other norma/ files.
   96  *      [91/05/13  17:16:24  jsb]
   97  * 
   98  */
   99 /*
  100  *      File:   norma/ipc_special.c
  101  *      Author: Joseph S. Barrera III
  102  *      Date:   1990
  103  *
  104  *      Functions to support norma special ports.
  105  */
  106 
  107 #include <norma_vm.h>
  108 #include <norma_ether.h>
  109 
  110 #include <vm/vm_kern.h>
  111 #include <mach/vm_param.h>
  112 #include <mach/port.h>
  113 #include <mach/message.h>
  114 #include <mach/norma_special_ports.h>
  115 #include <kern/assert.h>
  116 #include <kern/host.h>
  117 #include <kern/sched_prim.h>
  118 #include <kern/ipc_sched.h>
  119 #include <kern/ipc_kobject.h>
  120 #include <kern/zalloc.h>
  121 #include <device/device_port.h>
  122 #include <ipc/ipc_mqueue.h>
  123 #include <ipc/ipc_thread.h>
  124 #include <ipc/ipc_kmsg.h>
  125 #include <ipc/ipc_port.h>
  126 #include <ipc/ipc_pset.h>
  127 #include <ipc/ipc_space.h>
  128 #include <ipc/ipc_marequest.h>
  129 #include <norma/ipc_node.h>
  130 
  131 extern void netipc_thread();
  132 extern ipc_port_t norma_port_lookup();
  133 extern void netipc_thread_lock();
  134 extern void netipc_thread_unlock();
  135 extern void norma_port_insert();
  136 
  137 ipc_port_t host_special_port_array[MAX_SPECIAL_ID];
  138 #define host_special_port(id) (host_special_port_array[id])
  139 
  140 /*
  141  * The first three special ports are kernel owned.
  142  * They are DEVICE, HOST, and HOST_PRIV.
  143  * The kernel has receive rights to these ports.
  144  * Users are not allowed to change these ports.
  145  * No-more senders notifications are not requested for these ports.
  146  */
  147 
  148 norma_ipc_init()
  149 {
  150         /*
  151          * Register master device, host, and host_priv ports.
  152          */
  153         assert(master_device_port != IP_NULL);
  154         master_device_port->ip_norma_is_special = TRUE;
  155         host_special_port(NORMA_DEVICE_PORT) = master_device_port;
  156 
  157         assert(realhost.host_self != IP_NULL);
  158         realhost.host_self->ip_norma_is_special = TRUE;
  159         host_special_port(NORMA_HOST_PORT) = realhost.host_self;
  160 
  161         assert(realhost.host_priv_self != IP_NULL);
  162         realhost.host_priv_self->ip_norma_is_special = TRUE;
  163         host_special_port(NORMA_HOST_PRIV_PORT) = realhost.host_priv_self;
  164 
  165         /*
  166          * Initialize network subsystem
  167          */
  168         netipc_init();
  169 
  170         /*
  171          * Start up netipc thread, kserver module, and token module.
  172          * XXX netipc_init should do the former...
  173          */
  174         (void) kernel_thread(kernel_task, netipc_thread, (char *) 0);
  175         norma_kserver_startup();
  176 }
  177 
  178 /*
  179  * XXX should probably eliminate this -- it's a hack used by the xmm system
  180  */
  181 ipc_port_node(port)
  182         ipc_port_t port;
  183 {
  184         if (!port) return node_self();
  185         if (!port->ip_norma_uid) return node_self();
  186         return IP_NORMA_NODE(port->ip_norma_uid);
  187 }
  188 
  189 kern_return_t
  190 norma_port_location_hint(task, port, node)
  191         task_t task;
  192         ipc_port_t port;
  193         int *node;
  194 {
  195         if (port == IP_NULL) {
  196                 return KERN_INVALID_ARGUMENT;
  197         }
  198         if (IP_NORMA_IS_PROXY(port)) {
  199                 *node = port->ip_norma_dest_node;
  200         } else {
  201                 *node = node_self();
  202         }
  203         return KERN_SUCCESS;
  204 }
  205 
  206 kern_return_t
  207 norma_set_special_port(host, id, port)
  208         host_t host;
  209         unsigned long id;
  210         ipc_port_t port;
  211 {
  212         ipc_port_t old;
  213 
  214         if (host == HOST_NULL) {
  215                 return KERN_INVALID_HOST;
  216         }
  217         if (id <= 0 || id > MAX_SPECIAL_ID) {
  218                 return KERN_INVALID_VALUE;
  219         }
  220         if (id <= MAX_SPECIAL_KERNEL_ID) {
  221                 /* these never change */
  222                 return KERN_INVALID_VALUE;
  223         }
  224         netipc_thread_lock();
  225         old = host_special_port(id);
  226         host_special_port(id) = port;
  227         port->ip_norma_is_special = TRUE;
  228         if (IP_VALID(old)) {
  229                 fret("special id #%d replaced\n", id);
  230                 ipc_port_release_send(old);
  231         }
  232         netipc_thread_unlock();
  233         return KERN_SUCCESS;
  234 }
  235 
  236 /*
  237  * Internally called when port is being destroyed.
  238  * XXX
  239  * Is it also called when proxy is destroyed???
  240  */
  241 norma_unset_special_port(port)
  242         ipc_port_t port;
  243 {
  244         unsigned long id;
  245 
  246         for (id = 1; id <= MAX_SPECIAL_ID; id++) {
  247                 if (host_special_port(id) == port) {
  248                         assert(id >= MAX_SPECIAL_KERNEL_ID);
  249                         fret("special id #%d died\n", id);
  250                         host_special_port(id) = IP_NULL;
  251                         ipc_port_release_send(port);
  252                 }
  253         }
  254         port->ip_norma_is_special = FALSE;
  255 }
  256 
  257 ipc_port_t
  258 local_special(id)
  259         unsigned long id;
  260 {
  261         assert(IP_NORMA_SPECIAL(id));
  262         assert(id > 0 && id <= MAX_SPECIAL_KERNEL_ID);
  263         return ipc_port_make_send(host_special_port(id));
  264 }
  265 
  266 ipc_port_t
  267 remote_special(node, id)
  268         unsigned long node;
  269         unsigned long id;
  270 {
  271         ipc_port_t port;
  272         unsigned long uid = IP_NORMA_UID(node, id);
  273 
  274         assert(node != node_self());
  275         assert(id > 0 && id <= MAX_SPECIAL_KERNEL_ID);
  276         port = norma_port_lookup(uid);
  277         if (port == IP_NULL) {
  278                 port = ipc_port_alloc_special(ipc_space_remote);
  279                 if (port == IP_NULL) {
  280                         panic("remote_special: ipc_port_alloc_special");
  281                 }
  282                 port->ip_nsrequest = ip_nsproxym(port);
  283                 port->ip_srights = 1;
  284                 port->ip_norma_uid = uid;
  285                 port->ip_norma_dest_node = node;
  286                 port->ip_norma_is_proxy = TRUE;
  287                 norma_port_insert(port);
  288         } else {
  289                 port->ip_srights++;
  290         }
  291         port->ip_norma_stransit = -0x70000000;  /* XXX */
  292         return port;
  293 }
  294 
  295 ipc_port_t
  296 remote_device(node)
  297         unsigned long node;
  298 {
  299         return remote_special(node, (unsigned long) NORMA_DEVICE_PORT);
  300 }
  301 
  302 ipc_port_t
  303 remote_host(node)
  304         unsigned long node;
  305 {
  306         return remote_special(node, (unsigned long) NORMA_HOST_PORT);
  307 }
  308 
  309 ipc_port_t
  310 remote_host_priv(node)
  311         unsigned long node;
  312 {
  313         return remote_special(node, (unsigned long) NORMA_HOST_PRIV_PORT);
  314 }
  315 
  316 /*
  317  * XXX
  318  * The blocking behavior of this call is now somewhat funny.
  319  * A remote call will block until the remote node comes up.
  320  * However, in either local or remote case, a null port may be returned;
  321  * that is, we do not block for a valid port to show up.
  322  */
  323 kern_return_t
  324 norma_get_special_port(host, node, id, portp)
  325         host_t host;
  326         unsigned long node;
  327         unsigned long id;
  328         ipc_port_t *portp;
  329 {
  330         if (host == HOST_NULL) {
  331                 return KERN_INVALID_HOST;
  332         }
  333         if (id <= 0 || id > MAX_SPECIAL_ID) {
  334                 return KERN_INVALID_ARGUMENT;
  335         }
  336         if (id <= MAX_SPECIAL_KERNEL_ID) {
  337                 if (node == node_self()) {
  338                         *portp = local_special(id);
  339                 } else {
  340                         *portp = remote_special(node, id);
  341                 }
  342         } else {
  343                 if (node == node_self()) {
  344                         *portp = ipc_port_copy_send(host_special_port(id));
  345                 } else {
  346                         return r_norma_get_special_port(remote_host_priv(node),
  347                                                         node, id, portp);
  348                 }
  349         }
  350         return KERN_SUCCESS;
  351 }

Cache object: 9ae3feebbb4574f135db426a9f8a2f99


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