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

Cache object: a2e555efaf531222965b847d0bed2911


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