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/ipc/ipc_space.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,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_space.c,v $
   29  * Revision 2.12  93/01/14  17:33:08  danner
   30  *      64bit cleanup.
   31  *      [92/11/30            af]
   32  * 
   33  * Revision 2.11  92/08/03  17:35:34  jfriedl
   34  *      removed silly prototypes
   35  *      [92/08/02            jfriedl]
   36  * 
   37  * Revision 2.10  92/05/21  17:11:42  jfriedl
   38  *      tried prototypes.
   39  *      [92/05/20            jfriedl]
   40  * 
   41  * Revision 2.9  92/03/10  16:26:21  jsb
   42  *      NORMA_IPC: declare ipc_space_remote.
   43  *      [91/12/24  14:00:40  jsb]
   44  * 
   45  * Revision 2.8  91/10/09  16:10:26  af
   46  *      Revision 2.7.2.1  91/09/16  10:15:57  rpd
   47  *      Added <ipc/ipc_hash.h>.
   48  *      [91/09/02            rpd]
   49  * 
   50  * Revision 2.7.2.1  91/09/16  10:15:57  rpd
   51  *      Added <ipc/ipc_hash.h>.
   52  *      [91/09/02            rpd]
   53  * 
   54  * Revision 2.7  91/05/14  16:36:44  mrt
   55  *      Correcting copyright
   56  * 
   57  * Revision 2.6  91/03/16  14:48:37  rpd
   58  *      Added is_growing.
   59  *      [91/03/07  16:38:42  rpd]
   60  * 
   61  * Revision 2.5  91/02/05  17:23:43  mrt
   62  *      Changed to new Mach copyright
   63  *      [91/02/01  15:51:18  mrt]
   64  * 
   65  * Revision 2.4  91/01/08  15:14:48  rpd
   66  *      Removed MACH_IPC_GENNOS.
   67  *      [90/11/08            rpd]
   68  * 
   69  * Revision 2.3  90/11/05  14:30:20  rpd
   70  *      Use new ip_reference and ip_release.
   71  *      [90/10/29            rpd]
   72  * 
   73  * Revision 2.2  90/06/02  14:51:39  rpd
   74  *      Created for new IPC.
   75  *      [90/03/26  21:03:12  rpd]
   76  * 
   77  */
   78 /*
   79  *      File:   ipc/ipc_space.c
   80  *      Author: Rich Draves
   81  *      Date:   1989
   82  *
   83  *      Functions to manipulate IPC capability spaces.
   84  */
   85 
   86 #include <mach_ipc_compat.h>
   87 #include <norma_ipc.h>
   88 
   89 #include <mach/boolean.h>
   90 #include <mach/kern_return.h>
   91 #include <mach/port.h>
   92 #include <kern/assert.h>
   93 #include <kern/sched_prim.h>
   94 #include <kern/zalloc.h>
   95 #include <ipc/port.h>
   96 #include <ipc/ipc_entry.h>
   97 #include <ipc/ipc_splay.h>
   98 #include <ipc/ipc_hash.h>
   99 #include <ipc/ipc_table.h>
  100 #include <ipc/ipc_port.h>
  101 #include <ipc/ipc_space.h>
  102 #include <ipc/ipc_right.h>
  103 
  104 
  105 
  106 zone_t ipc_space_zone;
  107 ipc_space_t ipc_space_kernel;
  108 ipc_space_t ipc_space_reply;
  109 #if     NORMA_IPC
  110 ipc_space_t ipc_space_remote;
  111 #endif  NORMA_IPC
  112 
  113 /*
  114  *      Routine:        ipc_space_reference
  115  *      Routine:        ipc_space_release
  116  *      Purpose:
  117  *              Function versions of the IPC space macros.
  118  *              The "is_" cover macros can be defined to use the
  119  *              macros or the functions, as desired.
  120  */
  121 
  122 void
  123 ipc_space_reference(space)
  124         ipc_space_t space;
  125 {
  126         ipc_space_reference_macro(space);
  127 }
  128 
  129 void
  130 ipc_space_release(space)
  131         ipc_space_t space;
  132 {
  133         ipc_space_release_macro(space);
  134 }
  135 
  136 /*
  137  *      Routine:        ipc_space_create
  138  *      Purpose:
  139  *              Creates a new IPC space.
  140  *
  141  *              The new space has two references, one for the caller
  142  *              and one because it is active.
  143  *      Conditions:
  144  *              Nothing locked.  Allocates memory.
  145  *      Returns:
  146  *              KERN_SUCCESS            Created a space.
  147  *              KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
  148  */
  149 
  150 kern_return_t
  151 ipc_space_create(initial, spacep)
  152         ipc_table_size_t initial;
  153         ipc_space_t *spacep;
  154 {
  155         ipc_space_t space;
  156         ipc_entry_t table;
  157         ipc_entry_num_t new_size;
  158         mach_port_index_t index;
  159 
  160         space = is_alloc();
  161         if (space == IS_NULL)
  162                 return KERN_RESOURCE_SHORTAGE;
  163 
  164         table = it_entries_alloc(initial);
  165         if (table == IE_NULL) {
  166                 is_free(space);
  167                 return KERN_RESOURCE_SHORTAGE;
  168         }
  169 
  170         new_size = initial->its_size;
  171         bzero((char *) table, new_size * sizeof(struct ipc_entry));
  172 
  173         /*
  174          *      Initialize the free list in the table.
  175          *      Add the entries in reverse order, and
  176          *      set the generation number to -1, so that
  177          *      initial allocations produce "natural" names.
  178          */
  179 
  180         for (index = 0; index < new_size; index++) {
  181                 ipc_entry_t entry = &table[index];
  182 
  183                 entry->ie_bits = IE_BITS_GEN_MASK;
  184                 entry->ie_next = index+1;
  185         }
  186         table[new_size-1].ie_next = 0;
  187 
  188         is_ref_lock_init(space);
  189         space->is_references = 2;
  190 
  191         is_lock_init(space);
  192         space->is_active = TRUE;
  193         space->is_growing = FALSE;
  194         space->is_table = table;
  195         space->is_table_size = new_size;
  196         space->is_table_next = initial+1;
  197 
  198         ipc_splay_tree_init(&space->is_tree);
  199         space->is_tree_total = 0;
  200         space->is_tree_small = 0;
  201         space->is_tree_hash = 0;
  202 
  203 #if     MACH_IPC_COMPAT
  204     {
  205         mach_port_t name;
  206         ipc_port_t port;
  207         kern_return_t kr;
  208 
  209         /*
  210          *      ipc_port_alloc_compat probably won't look at is_notify,
  211          *      but make sure all fields have sane values anyway.
  212          */
  213 
  214         space->is_notify = IP_NULL;
  215 
  216         kr = ipc_port_alloc_compat(space, &name, &port);
  217         if (kr != KERN_SUCCESS) {
  218                 ipc_space_destroy(space);
  219                 is_release(space);
  220                 return kr;
  221         }
  222 
  223         ip_reference(port);
  224         port->ip_srights++;
  225         ip_unlock(port);
  226         space->is_notify = port;
  227     }
  228 #endif  MACH_IPC_COMPAT
  229 
  230         *spacep = space;
  231         return KERN_SUCCESS;
  232 }
  233 
  234 /*
  235  *      Routine:        ipc_space_create_special
  236  *      Purpose:
  237  *              Create a special space.  A special space
  238  *              doesn't hold rights in the normal way.
  239  *              Instead it is place-holder for holding
  240  *              disembodied (naked) receive rights.
  241  *              See ipc_port_alloc_special/ipc_port_dealloc_special.
  242  *      Conditions:
  243  *              Nothing locked.
  244  *      Returns:
  245  *              KERN_SUCCESS            Created a space.
  246  *              KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
  247  */
  248 
  249 kern_return_t
  250 ipc_space_create_special(spacep)
  251         ipc_space_t *spacep;
  252 {
  253         ipc_space_t space;
  254 
  255         space = is_alloc();
  256         if (space == IS_NULL)
  257                 return KERN_RESOURCE_SHORTAGE;
  258 
  259         is_ref_lock_init(space);
  260         space->is_references = 1;
  261 
  262         is_lock_init(space);
  263         space->is_active = FALSE;
  264 
  265         *spacep = space;
  266         return KERN_SUCCESS;
  267 }
  268 
  269 /*
  270  *      Routine:        ipc_space_destroy
  271  *      Purpose:
  272  *              Marks the space as dead and cleans up the entries.
  273  *              Does nothing if the space is already dead.
  274  *      Conditions:
  275  *              Nothing locked.
  276  */
  277 
  278 void
  279 ipc_space_destroy(space)
  280         ipc_space_t space;
  281 {
  282         ipc_tree_entry_t tentry;
  283         ipc_entry_t table;
  284         ipc_entry_num_t size;
  285         mach_port_index_t index;
  286         boolean_t active;
  287 
  288         assert(space != IS_NULL);
  289 
  290         is_write_lock(space);
  291         active = space->is_active;
  292         space->is_active = FALSE;
  293         is_write_unlock(space);
  294 
  295         if (!active)
  296                 return;
  297 
  298         /*
  299          *      If somebody is trying to grow the table,
  300          *      we must wait until they finish and figure
  301          *      out the space died.
  302          */
  303 
  304         is_read_lock(space);
  305         while (space->is_growing) {
  306                 assert_wait((event_t) space, FALSE);
  307                 is_read_unlock(space);
  308                 thread_block((void (*)()) 0);
  309                 is_read_lock(space);
  310         }
  311         is_read_unlock(space);
  312 
  313         /*
  314          *      Now we can futz with it without having it locked.
  315          */
  316 
  317         table = space->is_table;
  318         size = space->is_table_size;
  319 
  320         for (index = 0; index < size; index++) {
  321                 ipc_entry_t entry = &table[index];
  322                 mach_port_type_t type = IE_BITS_TYPE(entry->ie_bits);
  323 
  324                 if (type != MACH_PORT_TYPE_NONE) {
  325                         mach_port_t name =
  326                                 MACH_PORT_MAKEB(index, entry->ie_bits);
  327 
  328                         ipc_right_clean(space, name, entry);
  329                 }
  330         }
  331 
  332         it_entries_free(space->is_table_next-1, table);
  333 
  334         for (tentry = ipc_splay_traverse_start(&space->is_tree);
  335              tentry != ITE_NULL;
  336              tentry = ipc_splay_traverse_next(&space->is_tree, TRUE)) {
  337                 mach_port_type_t type = IE_BITS_TYPE(tentry->ite_bits);
  338                 mach_port_t name = tentry->ite_name;
  339 
  340                 assert(type != MACH_PORT_TYPE_NONE);
  341 
  342                 /* use object before ipc_right_clean releases ref */
  343 
  344                 if (type == MACH_PORT_TYPE_SEND)
  345                         ipc_hash_global_delete(space, tentry->ite_object,
  346                                                name, tentry);
  347 
  348                 ipc_right_clean(space, name, &tentry->ite_entry);
  349         }
  350         ipc_splay_traverse_finish(&space->is_tree);
  351 
  352 #if     MACH_IPC_COMPAT
  353         if (IP_VALID(space->is_notify))
  354                 ipc_port_release_send(space->is_notify);
  355 #endif  MACH_IPC_COMPAT
  356 
  357         /*
  358          *      Because the space is now dead,
  359          *      we must release the "active" reference for it.
  360          *      Our caller still has his reference.
  361          */
  362 
  363         is_release(space);
  364 }

Cache object: f976ee1413988ee063562d5a70f671f1


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