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_list.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,1992 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_list.c,v $
   29  * Revision 2.3  93/05/15  19:35:22  mrt
   30  *      machparam.h -> machspl.h
   31  * 
   32  * Revision 2.2  92/03/10  16:27:38  jsb
   33  *      Merged in norma branch changes as of NORMA_MK7.
   34  *      [92/03/09  12:49:22  jsb]
   35  * 
   36  * Revision 2.1.1.7.1.5  92/02/22  10:44:15  jsb
   37  *      Temporary workaround: changed "not tabled" panic to a printf.
   38  * 
   39  * Revision 2.1.1.7.1.4  92/02/21  11:24:24  jsb
   40  *      Added new routine norma_port_remove_try.
   41  *      [92/02/20  17:15:49  jsb]
   42  * 
   43  *      Added db_show_{uid,all_uids}_verbose.
   44  *      [92/02/20  10:33:47  jsb]
   45  * 
   46  * Revision 2.1.1.7.1.3  92/01/21  21:51:19  jsb
   47  *      Now uses hash table. Now uses netipc lock instead of spls.
   48  *      Removed seqno debugging hack. Added norma_port_iterate and
   49  *      reimplemented db_show_uid (nee norma_list_all_ports) with it.
   50  *      Added support for show all {proxies, principals}. Use kdbprintf
   51  *      instead of printf for these routines for pagination.
   52  *      [92/01/16  22:46:09  jsb]
   53  * 
   54  * Revision 2.1.1.7.1.2  92/01/03  16:37:27  jsb
   55  *      Use ipc_port_release instead of ip_release to allow port deallocation.
   56  *      [91/12/31  21:42:40  jsb]
   57  * 
   58  *      Added norma_port_tabled function.
   59  *      [91/12/31  17:17:02  jsb]
   60  * 
   61  *      In norma_port_remove, refuse to remove a proxy that started out as a
   62  *      principal, since our forwarding algorithms require it to stay around.
   63  *      [91/12/31  12:19:08  jsb]
   64  * 
   65  *      Hacked norma_new_uid to incorporate incarnation in generated uids.
   66  *      Threw in a stub for norma_ipc_cleanup_incarnation.
   67  *      [91/12/29  16:08:32  jsb]
   68  * 
   69  *      Lots of ugly but useful debugging support.
   70  *      [91/12/28  18:45:37  jsb]
   71  * 
   72  *      Made norma_list_all_ports print port addresses as well as uids.
   73  *      [91/12/25  16:57:46  jsb]
   74  * 
   75  *      First checkin. Split from norma/ipc_transit.c.
   76  *      [91/12/24  14:26:58  jsb]
   77  * 
   78  * Revision 2.1.1.7.1.1  92/01/03  08:54:06  jsb
   79  *      First NORMA branch checkin.
   80  * 
   81  * 
   82  */
   83 /*
   84  *      File:   norma/ipc_list.c
   85  *      Author: Joseph S. Barrera III
   86  *      Date:   1991
   87  *
   88  *      Maintains list of norma ports.
   89  */
   90 
   91 #include <machine/machspl.h>
   92 #include <ipc/ipc_port.h>
   93 #include <norma/ipc_node.h>
   94 
   95 extern void netipc_thread_lock();
   96 extern void netipc_thread_unlock();
   97 
   98 /*
   99  * Definitions for norma special ports.
  100  */
  101 unsigned long           lid_counter = 0;
  102 extern unsigned long    node_incarnation;
  103 extern ipc_port_t       host_special_port[MAX_SPECIAL_ID];
  104 
  105 /*
  106  * Allocate a uid for a newly exported port.
  107  */
  108 unsigned long
  109 norma_new_uid_locked()
  110 {
  111         if (lid_counter == 0) {
  112                 /*
  113                  * XXX
  114                  * This is a hack to work the incarnation into the lid
  115                  * so that we don't recreate the same uids. I still need
  116                  * to figure out how to do norma_ipc_cleanup_incarnation
  117                  * for real.
  118                  */
  119                 lid_counter = MAX_SPECIAL_ID +
  120                     (node_incarnation % 16) * ((IP_NORMA_MAX_LID + 1) / 16);
  121                 printf1("*** first uid=%x\n",
  122                         IP_NORMA_UID(node_self(), lid_counter));
  123         } else if (lid_counter == IP_NORMA_MAX_LID) {
  124                 panic("norma_new_uid: ran out of local ids\n");
  125         }
  126         return IP_NORMA_UID(node_self(), lid_counter++);
  127 }
  128 
  129 norma_ipc_cleanup_incarnation(remote)
  130         unsigned long remote;
  131 {
  132         /*
  133          * XXX
  134          * What exactly do we clean up???
  135          */
  136 }
  137 
  138 #define HASH_SIZE       16              /* must be power of two */
  139 #define HASH_MASK       (HASH_SIZE - 1)
  140 #define UID_HASH(uid)   ((IP_NORMA_NODE(uid) + IP_NORMA_LID(uid)) & HASH_MASK)
  141 
  142 ipc_port_t      norma_port_table[HASH_SIZE];
  143 
  144 int c_norma_port_lookup = 0;
  145 int c_norma_port_insert = 0;
  146 int c_norma_port_remove = 0;
  147 
  148 /*
  149  * We currently use a fairly conservative locking strategy, in which we
  150  * always grab the netipc_lock before inserts, removals, and lookups.
  151  * We could do better once we move port removal out of norma_ipc_receive_dest,
  152  * at which point only port lookups would be done at interrupt level.
  153  * At this point, we could use a simple lock for lookups and only
  154  * use netipc_lock (in combination with the simple lock) for inserts and
  155  * removals. Currently this doesn't buy you much because send-once rights
  156  * are continually being inserted and removed; if we added a bit of laziness
  157  * to send-once right handling, then presumably lookups would dominate
  158  * inserts and removals.
  159  */
  160 
  161 boolean_t
  162 norma_port_tabled(port)
  163         ipc_port_t port;
  164 {
  165         return (port->ip_norma_next != port);
  166 }
  167 
  168 ipc_port_t
  169 norma_port_lookup_locked(uid)
  170         register unsigned long uid;
  171 {
  172         register ipc_port_t p;
  173 
  174         c_norma_port_lookup++;
  175         if (uid == 0) {
  176                 return IP_NULL;
  177         }
  178         for (p = norma_port_table[UID_HASH(uid)]; p; p = p->ip_norma_next) {
  179                 if (p->ip_norma_uid == uid) {
  180                         return p;
  181                 }
  182         }
  183         return IP_NULL;
  184 }
  185 
  186 void
  187 norma_port_insert_locked(port)
  188         register ipc_port_t port;
  189 {
  190         register ipc_port_t *bucket;
  191         register unsigned long uid;
  192 
  193         c_norma_port_insert++;
  194         if (norma_port_tabled(port)) {
  195                 panic("norma_port_insert: tabled!\n");
  196                 return;
  197         }
  198         uid = port->ip_norma_uid;
  199         assert(uid != 0);
  200         bucket = &norma_port_table[UID_HASH(uid)];
  201         port->ip_norma_next = *bucket;
  202         *bucket = port;
  203         ip_reference(port);
  204 }
  205 
  206 void
  207 norma_port_remove_locked(port)
  208         register ipc_port_t port;
  209 {
  210         register unsigned long uid;
  211         register ipc_port_t p, *pp;
  212 
  213         c_norma_port_remove++;
  214         if (! norma_port_tabled(port)) {
  215                 /* XXX should be a panic */
  216                 printf("norma_port_remote: not tabled!\n");
  217                 return;
  218         }
  219         uid = port->ip_norma_uid;
  220         assert(uid != 0);
  221 
  222         /*
  223          * This is kind of gross.
  224          * We cannot remove a proxy that started out as a principal;
  225          * it must stay around to do forwarding.
  226          */
  227         if (port->ip_norma_is_proxy && IP_NORMA_NODE(uid) == node_self()) {
  228                 printf1("norma_port_remove: not removing port %x\n", port);
  229                 return;
  230         }
  231 
  232         /*
  233          * We can go ahead now.
  234          */
  235         pp = &norma_port_table[UID_HASH(uid)];
  236         for (p = *pp; p; pp = &p->ip_norma_next, p = *pp) {
  237                 if (p == port) {
  238                         *pp = port->ip_norma_next;
  239                         port->ip_norma_next = port;
  240                         printf1("norma_port_remove(0x%x:%x): refs %d\n",
  241                                 port, uid, port->ip_references - 1);
  242                         ipc_port_release(port);
  243                         return;
  244                 }
  245         }
  246         panic("norma_port_remove(0x%x:%x): not found\n", port, uid);
  247 }
  248 
  249 ipc_port_t
  250 norma_port_lookup(uid)
  251         register unsigned long uid;
  252 {
  253         register ipc_port_t port;
  254 
  255         assert(! netipc_locked());
  256         netipc_thread_lock();
  257         port = norma_port_lookup_locked(uid);
  258         netipc_thread_unlock();
  259         return port;
  260 }
  261 
  262 void
  263 norma_port_insert(port)
  264         register ipc_port_t port;
  265 {
  266         assert(! netipc_locked());
  267         netipc_thread_lock();
  268         norma_port_insert_locked(port);
  269         netipc_thread_unlock();
  270 }
  271 
  272 void
  273 norma_port_remove(port)
  274         register ipc_port_t port;
  275 {
  276         assert(! netipc_locked());
  277         netipc_thread_lock();
  278         norma_port_remove_locked(port);
  279         netipc_thread_unlock();
  280 }
  281 
  282 void
  283 norma_port_remove_try(port)
  284         register ipc_port_t port;
  285 {
  286         if (port->ip_srights == 0 && port->ip_sorights == 0) {
  287                 printf1("norma_port_remove_try: releasing 0x%x:%x\n",
  288                         port, port->ip_norma_uid);
  289                 assert(! netipc_locked());
  290                 netipc_thread_lock();
  291                 norma_port_remove_locked(port);
  292                 netipc_thread_unlock();
  293         }
  294 }
  295 
  296 unsigned long
  297 norma_new_uid()
  298 {
  299         register unsigned long uid;
  300 
  301         assert(! netipc_locked());
  302         netipc_thread_lock();
  303         uid = norma_new_uid_locked();
  304         netipc_thread_unlock();
  305         return uid;
  306 }
  307 
  308 norma_port_table_statistics()
  309 {
  310         int i, total, average, len, longest;
  311         int l1, l2, l3;
  312         ipc_port_t p;
  313 
  314         total = 0;
  315         for (i = 0; i < HASH_SIZE; i++) {
  316                 for (p = norma_port_table[i]; p; p = p->ip_norma_next) {
  317                         total++;
  318                 }
  319         }
  320         average = total / HASH_SIZE;
  321         if (average == 0) {
  322                 average = 1;
  323         }
  324         longest = l1 = l2 = l3 = 0;
  325         for (i = 0; i < HASH_SIZE; i++) {
  326                 len = 0;
  327                 for (p = norma_port_table[i]; p; p = p->ip_norma_next) {
  328                         len++;
  329                 }
  330                 if (longest < len) {
  331                         longest = len;
  332                 }
  333                 if (len > average) {
  334                         l1++;
  335                         if (len > 2 * average) {
  336                                 l2++;
  337                                 if (len > 3 * average) {
  338                                         l3++;
  339                                 }
  340                         }
  341                 }
  342         }
  343         kdbprintf("%d ports, %d buckets, average %d per bucket\n",
  344                   total, HASH_SIZE, total / HASH_SIZE);
  345         kdbprintf("%d chains longer than %d, %d > %d, %d > %d; longest = %d\n",
  346                   l1, average, l2, 2 * average, l3, 3 * average, longest);
  347 }
  348 
  349 norma_port_iterate(function, args)
  350         void (*function)();
  351         void *args;
  352 {
  353         int i;
  354         ipc_port_t p;
  355 
  356         for (i = 0; i < HASH_SIZE; i++) {
  357                 for (p = norma_port_table[i]; p; p = p->ip_norma_next) {
  358                         (*function)(p, args);
  359                 }
  360         }
  361         (*function)(IP_NULL, args);
  362 }
  363 
  364 #include <ddb/db_sym.h>
  365 
  366 void
  367 db_show_uid(port, args)
  368         ipc_port_t port;
  369         void *args;
  370 {
  371         int *countp = (int *) args;
  372 
  373         if (port == IP_NULL) {
  374                 printf("\n");
  375                 return;
  376         }
  377         if (++*countp == 4) {
  378                 kdbprintf("%x:%x\n", port, port->ip_norma_uid);
  379                 *countp = 0;
  380         } else {
  381                 kdbprintf("%x:%x ", port, port->ip_norma_uid);
  382         }
  383 }
  384 
  385 void
  386 db_show_uid_verbose(port, args)
  387         ipc_port_t port;
  388         void *args;
  389 {
  390         if (port == IP_NULL) {
  391                 return;
  392         }
  393         kdbprintf("%x:%x %6d ",
  394                   port, port->ip_norma_uid, port->ip_norma_spare2);
  395         db_printsym(port->ip_norma_spare1, DB_STGY_PROC);
  396         kdbprintf("\n");
  397 }
  398 
  399 void
  400 db_show_proxy(port, args)
  401         ipc_port_t port;
  402         void *args;
  403 {
  404         if (port == IP_NULL || port->ip_norma_is_proxy) {
  405                 db_show_uid(port, args);
  406         }
  407 }
  408 
  409 void
  410 db_show_principal(port, args)
  411         ipc_port_t port;
  412         void *args;
  413 {
  414         if (port == IP_NULL || ! port->ip_norma_is_proxy) {
  415                 db_show_uid(port, args);
  416         }
  417 }
  418 
  419 db_show_all_uids()
  420 {
  421         int count = 0;
  422 
  423         norma_port_table_statistics();
  424         norma_port_iterate(db_show_uid, (void *) &count);
  425 }
  426 
  427 db_show_all_uids_verbose()
  428 {
  429         norma_port_table_statistics();
  430         norma_port_iterate(db_show_uid_verbose, (void *) 0);
  431 }
  432 
  433 db_show_all_proxies()
  434 {
  435         int count = 0;
  436 
  437         norma_port_iterate(db_show_proxy, (void *) &count);
  438 }
  439 
  440 db_show_all_principals()
  441 {
  442         int count = 0;
  443 
  444         norma_port_iterate(db_show_principal, (void *) &count);
  445 }

Cache object: 18e4720383fbe8df4efb9b331e295453


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