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_marequest.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,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_marequest.c,v $
   29  * Revision 2.10  93/03/09  10:54:41  danner
   30  *      Added typecast in hashing macros to shutup GCC.
   31  *      [93/03/06            af]
   32  * 
   33  * Revision 2.9  92/08/03  17:34:37  jfriedl
   34  *      removed silly prototypes
   35  *      [92/08/02            jfriedl]
   36  * 
   37  * Revision 2.8  92/05/21  17:10:37  jfriedl
   38  *      tried prototypes.
   39  *      [92/05/20            jfriedl]
   40  * 
   41  * Revision 2.7  92/01/14  16:44:37  rpd
   42  *      Changed ipc_marequest_info for CountInOut.
   43  *      [92/01/14            rpd]
   44  * 
   45  * Revision 2.6  91/05/14  16:33:35  mrt
   46  *      Correcting copyright
   47  * 
   48  * Revision 2.5  91/02/05  17:22:13  mrt
   49  *      Changed to new Mach copyright
   50  *      [91/02/01  15:46:05  mrt]
   51  * 
   52  * Revision 2.4  91/01/08  15:14:11  rpd
   53  *      Changed ipc_info_bucket_t to hash_info_bucket_t.
   54  *      [91/01/02            rpd]
   55  * 
   56  *      Changed zchange calls to make the IPC zones non-collectable.
   57  *      [90/12/29            rpd]
   58  * 
   59  * Revision 2.3  90/12/20  16:38:53  jeffreyh
   60  *      Change zchange to match new number of arguments.
   61  *      Made zone collectable. 
   62  *      [90/12/11            jeffreyh]
   63  * 
   64  * Revision 2.2  90/06/02  14:50:30  rpd
   65  *      Created for new IPC.
   66  *      [90/03/26  20:56:33  rpd]
   67  * 
   68  */
   69 /*
   70  *      File:   ipc/ipc_marequest.c
   71  *      Author: Rich Draves
   72  *      Date:   1989
   73  *
   74  *      Functions to handle msg-accepted requests.
   75  */
   76 
   77 #include <mach_ipc_compat.h>
   78 
   79 #include <mach/message.h>
   80 #include <mach/port.h>
   81 #include <kern/lock.h>
   82 #include <kern/mach_param.h>
   83 #include <kern/kalloc.h>
   84 #include <kern/zalloc.h>
   85 #include <ipc/port.h>
   86 #include <ipc/ipc_space.h>
   87 #include <ipc/ipc_entry.h>
   88 #include <ipc/ipc_port.h>
   89 #include <ipc/ipc_right.h>
   90 #include <ipc/ipc_marequest.h>
   91 #include <ipc/ipc_notify.h>
   92 
   93 #include <mach_ipc_debug.h>
   94 #if     MACH_IPC_DEBUG
   95 #include <mach/kern_return.h>
   96 #include <mach_debug/hash_info.h>
   97 #include <vm/vm_map.h>
   98 #include <vm/vm_kern.h>
   99 #include <vm/vm_user.h>
  100 #endif
  101 
  102 
  103 zone_t ipc_marequest_zone;
  104 int ipc_marequest_max = IMAR_MAX;
  105 
  106 #define imar_alloc()            ((ipc_marequest_t) zalloc(ipc_marequest_zone))
  107 #define imar_free(imar)         zfree(ipc_marequest_zone, (vm_offset_t) (imar))
  108 
  109 typedef unsigned int ipc_marequest_index_t;
  110 
  111 ipc_marequest_index_t ipc_marequest_size;
  112 ipc_marequest_index_t ipc_marequest_mask;
  113 
  114 #define IMAR_HASH(space, name)                                          \
  115                 ((((ipc_marequest_index_t)((vm_offset_t)space) >> 4) +  \
  116                   MACH_PORT_INDEX(name) + MACH_PORT_NGEN(name)) &       \
  117                  ipc_marequest_mask)
  118 
  119 typedef struct ipc_marequest_bucket {
  120         decl_simple_lock_data(, imarb_lock_data)
  121         ipc_marequest_t imarb_head;
  122 } *ipc_marequest_bucket_t;
  123 
  124 #define IMARB_NULL      ((ipc_marequest_bucket_t) 0)
  125 
  126 #define imarb_lock_init(imarb)  simple_lock_init(&(imarb)->imarb_lock_data)
  127 #define imarb_lock(imarb)       simple_lock(&(imarb)->imarb_lock_data)
  128 #define imarb_unlock(imarb)     simple_unlock(&(imarb)->imarb_lock_data)
  129 
  130 ipc_marequest_bucket_t ipc_marequest_table;
  131 
  132 
  133 
  134 /*
  135  *      Routine:        ipc_marequest_init
  136  *      Purpose:
  137  *              Initialize the msg-accepted request module.
  138  */
  139 
  140 void
  141 ipc_marequest_init()
  142 {
  143         ipc_marequest_index_t i;
  144 
  145         /* if not configured, initialize ipc_marequest_size */
  146 
  147         if (ipc_marequest_size == 0) {
  148                 ipc_marequest_size = ipc_marequest_max >> 8;
  149                 if (ipc_marequest_size < 16)
  150                         ipc_marequest_size = 16;
  151         }
  152 
  153         /* make sure it is a power of two */
  154 
  155         ipc_marequest_mask = ipc_marequest_size - 1;
  156         if ((ipc_marequest_size & ipc_marequest_mask) != 0) {
  157                 unsigned int bit;
  158 
  159                 /* round up to closest power of two */
  160 
  161                 for (bit = 1;; bit <<= 1) {
  162                         ipc_marequest_mask |= bit;
  163                         ipc_marequest_size = ipc_marequest_mask + 1;
  164 
  165                         if ((ipc_marequest_size & ipc_marequest_mask) == 0)
  166                                 break;
  167                 }
  168         }
  169 
  170         /* allocate ipc_marequest_table */
  171 
  172         ipc_marequest_table = (ipc_marequest_bucket_t)
  173                 kalloc((vm_size_t) (ipc_marequest_size *
  174                                     sizeof(struct ipc_marequest_bucket)));
  175         assert(ipc_marequest_table != IMARB_NULL);
  176 
  177         /* and initialize it */
  178 
  179         for (i = 0; i < ipc_marequest_size; i++) {
  180                 ipc_marequest_bucket_t bucket;
  181 
  182                 bucket = &ipc_marequest_table[i];
  183                 imarb_lock_init(bucket);
  184                 bucket->imarb_head = IMAR_NULL;
  185         }
  186 
  187         ipc_marequest_zone =
  188                 zinit(sizeof(struct ipc_marequest),
  189                       ipc_marequest_max * sizeof(struct ipc_marequest),
  190                       sizeof(struct ipc_marequest),
  191                       FALSE, "ipc msg-accepted requests");
  192         /* make it exhaustible */
  193         zchange(ipc_marequest_zone, FALSE, FALSE, TRUE, FALSE);
  194 }
  195 
  196 /*
  197  *      Routine:        ipc_marequest_create
  198  *      Purpose:
  199  *              Create a msg-accepted request, because
  200  *              a sender is forcing a message with MACH_SEND_NOTIFY.
  201  *
  202  *              The "notify" argument should name a receive right
  203  *              that is used to create the send-once notify port.
  204  *
  205  *              [MACH_IPC_COMPAT] If "notify" is MACH_PORT_NULL,
  206  *              then an old-style msg-accepted request is created.
  207  *      Conditions:
  208  *              Nothing locked; refs held for space and port.
  209  *      Returns:
  210  *              MACH_MSG_SUCCESS        Msg-accepted request created.
  211  *              MACH_SEND_INVALID_NOTIFY        The space is dead.
  212  *              MACH_SEND_INVALID_NOTIFY        The notify port is bad.
  213  *              MACH_SEND_NOTIFY_IN_PROGRESS
  214  *                      This space has already forced a message to this port.
  215  *              MACH_SEND_NO_NOTIFY     Can't allocate a msg-accepted request.
  216  */
  217 
  218 mach_msg_return_t
  219 ipc_marequest_create(space, port, notify, marequestp)
  220         ipc_space_t space;
  221         ipc_port_t port;
  222         mach_port_t notify;
  223         ipc_marequest_t *marequestp;
  224 {
  225         mach_port_t name;
  226         ipc_entry_t entry;
  227         ipc_port_t soright;
  228         ipc_marequest_t marequest;
  229         ipc_marequest_bucket_t bucket;
  230 
  231 #if     !MACH_IPC_COMPAT
  232         assert(notify != MACH_PORT_NULL);
  233 #endif  !MACH_IPC_COMPAT
  234 
  235         marequest = imar_alloc();
  236         if (marequest == IMAR_NULL)
  237                 return MACH_SEND_NO_NOTIFY;
  238 
  239         /*
  240          *      Delay creating the send-once right until
  241          *      we know there will be no errors.  Otherwise,
  242          *      we would have to worry about disposing of it
  243          *      when it turned out it wasn't needed.
  244          */
  245 
  246         is_write_lock(space);
  247         if (!space->is_active) {
  248                 is_write_unlock(space);
  249                 imar_free(marequest);
  250                 return MACH_SEND_INVALID_NOTIFY;
  251         }
  252 
  253         if (ipc_right_reverse(space, (ipc_object_t) port, &name, &entry)) {
  254                 ipc_entry_bits_t bits;
  255 
  256                 /* port is locked and active */
  257                 ip_unlock(port);
  258                 bits = entry->ie_bits;
  259 
  260                 assert(port == (ipc_port_t) entry->ie_object);
  261                 assert(bits & MACH_PORT_TYPE_SEND_RECEIVE);
  262 
  263                 if (bits & IE_BITS_MAREQUEST) {
  264                         is_write_unlock(space);
  265                         imar_free(marequest);
  266                         return MACH_SEND_NOTIFY_IN_PROGRESS;
  267                 }
  268 
  269 #if     MACH_IPC_COMPAT
  270                 if (notify == MACH_PORT_NULL)
  271                         soright = IP_NULL;
  272                 else
  273 #endif  MACH_IPC_COMPAT
  274                 if ((soright = ipc_port_lookup_notify(space, notify))
  275                                                                 == IP_NULL) {
  276                         is_write_unlock(space);
  277                         imar_free(marequest);
  278                         return MACH_SEND_INVALID_NOTIFY;
  279                 }
  280 
  281                 entry->ie_bits = bits | IE_BITS_MAREQUEST;
  282 
  283                 is_reference(space);
  284                 marequest->imar_space = space;
  285                 marequest->imar_name = name;
  286                 marequest->imar_soright = soright;
  287 
  288                 bucket = &ipc_marequest_table[IMAR_HASH(space, name)];
  289                 imarb_lock(bucket);
  290 
  291                 marequest->imar_next = bucket->imarb_head;
  292                 bucket->imarb_head = marequest;
  293 
  294                 imarb_unlock(bucket);
  295         } else {
  296 #if     MACH_IPC_COMPAT
  297                 if (notify == MACH_PORT_NULL)
  298                         soright = IP_NULL;
  299                 else
  300 #endif  MACH_IPC_COMPAT
  301                 if ((soright = ipc_port_lookup_notify(space, notify))
  302                                                                 == IP_NULL) {
  303                         is_write_unlock(space);
  304                         imar_free(marequest);
  305                         return MACH_SEND_INVALID_NOTIFY;
  306                 }
  307 
  308                 is_reference(space);
  309                 marequest->imar_space = space;
  310                 marequest->imar_name = MACH_PORT_NULL;
  311                 marequest->imar_soright = soright;
  312         }
  313 
  314         is_write_unlock(space);
  315         *marequestp = marequest;
  316         return MACH_MSG_SUCCESS;
  317 }
  318 
  319 /*
  320  *      Routine:        ipc_marequest_cancel
  321  *      Purpose:
  322  *              Cancel a msg-accepted request, because
  323  *              the space's entry is being destroyed.
  324  *      Conditions:
  325  *              The space is write-locked and active.
  326  */
  327 
  328 void
  329 ipc_marequest_cancel(space, name)
  330         ipc_space_t space;
  331         mach_port_t name;
  332 {
  333         ipc_marequest_bucket_t bucket;
  334         ipc_marequest_t marequest, *last;
  335 
  336         assert(space->is_active);
  337 
  338         bucket = &ipc_marequest_table[IMAR_HASH(space, name)];
  339         imarb_lock(bucket);
  340 
  341         for (last = &bucket->imarb_head;
  342              (marequest = *last) != IMAR_NULL;
  343              last = &marequest->imar_next)
  344                 if ((marequest->imar_space == space) &&
  345                     (marequest->imar_name == name))
  346                         break;
  347 
  348         assert(marequest != IMAR_NULL);
  349         *last = marequest->imar_next;
  350         imarb_unlock(bucket);
  351 
  352         marequest->imar_name = MACH_PORT_NULL;
  353 }
  354 
  355 /*
  356  *      Routine:        ipc_marequest_rename
  357  *      Purpose:
  358  *              Rename a msg-accepted request, because the entry
  359  *              in the space is being renamed.
  360  *      Conditions:
  361  *              The space is write-locked and active.
  362  */
  363 
  364 void
  365 ipc_marequest_rename(space, old, new)
  366         ipc_space_t space;
  367         mach_port_t old, new;
  368 {
  369         ipc_marequest_bucket_t bucket;
  370         ipc_marequest_t marequest, *last;
  371 
  372         assert(space->is_active);
  373 
  374         bucket = &ipc_marequest_table[IMAR_HASH(space, old)];
  375         imarb_lock(bucket);
  376 
  377         for (last = &bucket->imarb_head;
  378              (marequest = *last) != IMAR_NULL;
  379              last = &marequest->imar_next)
  380                 if ((marequest->imar_space == space) &&
  381                     (marequest->imar_name == old))
  382                         break;
  383 
  384         assert(marequest != IMAR_NULL);
  385         *last = marequest->imar_next;
  386         imarb_unlock(bucket);
  387 
  388         marequest->imar_name = new;
  389 
  390         bucket = &ipc_marequest_table[IMAR_HASH(space, new)];
  391         imarb_lock(bucket);
  392 
  393         marequest->imar_next = bucket->imarb_head;
  394         bucket->imarb_head = marequest;
  395 
  396         imarb_unlock(bucket);
  397 }
  398 
  399 /*
  400  *      Routine:        ipc_marequest_destroy
  401  *      Purpose:
  402  *              Destroy a msg-accepted request, because
  403  *              the kernel message is being received/destroyed.
  404  *      Conditions:
  405  *              Nothing locked.
  406  */
  407 
  408 void
  409 ipc_marequest_destroy(marequest)
  410         ipc_marequest_t marequest;
  411 {
  412         ipc_space_t space = marequest->imar_space;
  413         mach_port_t name;
  414         ipc_port_t soright;
  415 #if     MACH_IPC_COMPAT
  416         ipc_port_t sright = IP_NULL;
  417 #endif  MACH_IPC_COMPAT
  418 
  419         is_write_lock(space);
  420 
  421         name = marequest->imar_name;
  422         soright = marequest->imar_soright;
  423 
  424         if (name != MACH_PORT_NULL) {
  425                 ipc_marequest_bucket_t bucket;
  426                 ipc_marequest_t this, *last;
  427 
  428                 bucket = &ipc_marequest_table[IMAR_HASH(space, name)];
  429                 imarb_lock(bucket);
  430 
  431                 for (last = &bucket->imarb_head;
  432                      (this = *last) != IMAR_NULL;
  433                      last = &this->imar_next)
  434                         if ((this->imar_space == space) &&
  435                             (this->imar_name == name))
  436                                 break;
  437 
  438                 assert(this == marequest);
  439                 *last = this->imar_next;
  440                 imarb_unlock(bucket);
  441 
  442                 if (space->is_active) {
  443                         ipc_entry_t entry;
  444 
  445                         entry = ipc_entry_lookup(space, name);
  446                         assert(entry != IE_NULL);
  447                         assert(entry->ie_bits & IE_BITS_MAREQUEST);
  448                         assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
  449 
  450                         entry->ie_bits &= ~IE_BITS_MAREQUEST;
  451 
  452 #if     MACH_IPC_COMPAT
  453                         if (soright == IP_NULL)
  454                                 sright = ipc_space_make_notify(space);
  455 #endif  MACH_IPC_COMPAT
  456                 } else
  457                         name = MACH_PORT_NULL;
  458         }
  459 
  460         is_write_unlock(space);
  461         is_release(space);
  462 
  463         imar_free(marequest);
  464 
  465 #if     MACH_IPC_COMPAT
  466         if (soright == IP_NULL) {
  467                 if (IP_VALID(sright)) {
  468                         assert(name != MACH_PORT_NULL);
  469                         ipc_notify_msg_accepted_compat(sright, name);
  470                 }
  471 
  472                 return;
  473         }
  474         assert(sright == IP_NULL);
  475 #endif  MACH_IPC_COMPAT
  476 
  477         assert(soright != IP_NULL);
  478         ipc_notify_msg_accepted(soright, name);
  479 }
  480 
  481 #if     MACH_IPC_DEBUG
  482 
  483 
  484 /*
  485  *      Routine:        ipc_marequest_info
  486  *      Purpose:
  487  *              Return information about the marequest hash table.
  488  *              Fills the buffer with as much information as possible
  489  *              and returns the desired size of the buffer.
  490  *      Conditions:
  491  *              Nothing locked.  The caller should provide
  492  *              possibly-pageable memory.
  493  */
  494 
  495 unsigned int
  496 ipc_marequest_info(maxp, info, count)
  497         unsigned int *maxp;
  498         hash_info_bucket_t *info;
  499         unsigned int count;
  500 {
  501         ipc_marequest_index_t i;
  502 
  503         if (ipc_marequest_size < count)
  504                 count = ipc_marequest_size;
  505 
  506         for (i = 0; i < count; i++) {
  507                 ipc_marequest_bucket_t bucket = &ipc_marequest_table[i];
  508                 unsigned int bucket_count = 0;
  509                 ipc_marequest_t marequest;
  510 
  511                 imarb_lock(bucket);
  512                 for (marequest = bucket->imarb_head;
  513                      marequest != IMAR_NULL;
  514                      marequest = marequest->imar_next)
  515                         bucket_count++;
  516                 imarb_unlock(bucket);
  517 
  518                 /* don't touch pageable memory while holding locks */
  519                 info[i].hib_count = bucket_count;
  520         }
  521 
  522         *maxp = ipc_marequest_max;
  523         return ipc_marequest_size;
  524 }
  525 
  526 #endif  MACH_IPC_DEBUG

Cache object: 4f9949691d92e3e0acf0a559640e7b39


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