ipc_space.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989 Carnegie Mellon University.
  4. * Copyright (c) 1993,1994 The University of Utah and
  5. * the Computer Systems Laboratory (CSL).
  6. * All rights reserved.
  7. *
  8. * Permission to use, copy, modify and distribute this software and its
  9. * documentation is hereby granted, provided that both the copyright
  10. * notice and this permission notice appear in all copies of the
  11. * software, derivative works or modified versions, and any portions
  12. * thereof, and that both notices appear in supporting documentation.
  13. *
  14. * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
  15. * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
  16. * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
  17. * THIS SOFTWARE.
  18. *
  19. * Carnegie Mellon requests users of this software to return to
  20. *
  21. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  22. * School of Computer Science
  23. * Carnegie Mellon University
  24. * Pittsburgh PA 15213-3890
  25. *
  26. * any improvements or extensions that they make and grant Carnegie Mellon
  27. * the rights to redistribute these changes.
  28. */
  29. /*
  30. */
  31. /*
  32. * File: ipc/ipc_space.c
  33. * Author: Rich Draves
  34. * Date: 1989
  35. *
  36. * Functions to manipulate IPC capability spaces.
  37. */
  38. #pragma GCC diagnostic error "-Wundef"
  39. #include <glue/gnulinux.h>
  40. #include <string.h>
  41. #include <mach/boolean.h>
  42. #include <mach/kern_return.h>
  43. #include <mach/port.h>
  44. #include <kern/assert.h>
  45. #include <kern/sched_prim.h>
  46. #include <kern/slab.h>
  47. #include <ipc/port.h>
  48. #include <ipc/ipc_entry.h>
  49. #include <ipc/ipc_splay.h>
  50. #include <ipc/ipc_hash.h>
  51. #include <ipc/ipc_table.h>
  52. #include <ipc/ipc_port.h>
  53. #include <ipc/ipc_space.h>
  54. #include <ipc/ipc_right.h>
  55. struct gnu_kmem_cache ipc_space_cache;
  56. ipc_space_t ipc_space_kernel;
  57. ipc_space_t ipc_space_reply;
  58. /*
  59. * Routine: ipc_space_reference
  60. * Routine: ipc_space_release
  61. * Purpose:
  62. * Function versions of the IPC space macros.
  63. * The "is_" cover macros can be defined to use the
  64. * macros or the functions, as desired.
  65. */
  66. void
  67. ipc_space_reference(
  68. ipc_space_t space)
  69. {
  70. ipc_space_reference_macro(space);
  71. }
  72. void
  73. ipc_space_release(
  74. ipc_space_t space)
  75. {
  76. ipc_space_release_macro(space);
  77. }
  78. /*
  79. * Routine: ipc_space_create
  80. * Purpose:
  81. * Creates a new IPC space.
  82. *
  83. * The new space has two references, one for the caller
  84. * and one because it is active.
  85. * Conditions:
  86. * Nothing locked. Allocates memory.
  87. * Returns:
  88. * KERN_SUCCESS Created a space.
  89. * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
  90. */
  91. kern_return_t
  92. ipc_space_create(
  93. ipc_table_size_t initial,
  94. ipc_space_t *spacep)
  95. {
  96. ipc_space_t space;
  97. ipc_entry_t table;
  98. ipc_entry_num_t new_size;
  99. mach_port_index_t index;
  100. space = is_alloc();
  101. if (space == IS_NULL)
  102. return KERN_RESOURCE_SHORTAGE;
  103. table = it_entries_alloc(initial);
  104. if (table == IE_NULL) {
  105. is_free(space);
  106. return KERN_RESOURCE_SHORTAGE;
  107. }
  108. new_size = initial->its_size;
  109. memset((void *) table, 0, new_size * sizeof(struct ipc_entry));
  110. /*
  111. * Initialize the free list in the table.
  112. * Add the entries in reverse order, and
  113. * set the generation number to -1, so that
  114. * initial allocations produce "natural" names.
  115. */
  116. for (index = 0; index < new_size; index++) {
  117. ipc_entry_t entry = &table[index];
  118. entry->ie_bits = IE_BITS_GEN_MASK;
  119. entry->ie_next = index+1;
  120. }
  121. table[new_size-1].ie_next = 0;
  122. is_ref_lock_init(space);
  123. space->is_references = 2;
  124. is_lock_init(space);
  125. space->is_active = TRUE;
  126. space->is_growing = FALSE;
  127. space->is_table = table;
  128. space->is_table_size = new_size;
  129. space->is_table_next = initial+1;
  130. ipc_splay_tree_init(&space->is_tree);
  131. space->is_tree_total = 0;
  132. space->is_tree_small = 0;
  133. space->is_tree_hash = 0;
  134. *spacep = space;
  135. return KERN_SUCCESS;
  136. }
  137. /*
  138. * Routine: ipc_space_create_special
  139. * Purpose:
  140. * Create a special space. A special space
  141. * doesn't hold rights in the normal way.
  142. * Instead it is place-holder for holding
  143. * disembodied (naked) receive rights.
  144. * See ipc_port_alloc_special/ipc_port_dealloc_special.
  145. * Conditions:
  146. * Nothing locked.
  147. * Returns:
  148. * KERN_SUCCESS Created a space.
  149. * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
  150. */
  151. kern_return_t
  152. ipc_space_create_special(
  153. ipc_space_t *spacep)
  154. {
  155. ipc_space_t space;
  156. space = is_alloc();
  157. if (space == IS_NULL)
  158. return KERN_RESOURCE_SHORTAGE;
  159. is_ref_lock_init(space);
  160. space->is_references = 1;
  161. is_lock_init(space);
  162. space->is_active = FALSE;
  163. *spacep = space;
  164. return KERN_SUCCESS;
  165. }
  166. /*
  167. * Routine: ipc_space_destroy
  168. * Purpose:
  169. * Marks the space as dead and cleans up the entries.
  170. * Does nothing if the space is already dead.
  171. * Conditions:
  172. * Nothing locked.
  173. */
  174. void
  175. ipc_space_destroy(
  176. ipc_space_t space)
  177. {
  178. ipc_tree_entry_t tentry;
  179. ipc_entry_t table;
  180. ipc_entry_num_t size;
  181. mach_port_index_t index;
  182. boolean_t active;
  183. assert(space != IS_NULL);
  184. is_write_lock(space);
  185. active = space->is_active;
  186. space->is_active = FALSE;
  187. is_write_unlock(space);
  188. if (!active)
  189. return;
  190. /*
  191. * If somebody is trying to grow the table,
  192. * we must wait until they finish and figure
  193. * out the space died.
  194. */
  195. is_read_lock(space);
  196. while (space->is_growing) {
  197. assert_wait((event_t) space, FALSE);
  198. is_read_unlock(space);
  199. thread_block((void (*)(void)) 0);
  200. is_read_lock(space);
  201. }
  202. is_read_unlock(space);
  203. /*
  204. * Now we can futz with it without having it locked.
  205. */
  206. table = space->is_table;
  207. size = space->is_table_size;
  208. for (index = 0; index < size; index++) {
  209. ipc_entry_t entry = &table[index];
  210. mach_port_type_t type = IE_BITS_TYPE(entry->ie_bits);
  211. if (type != MACH_PORT_TYPE_NONE) {
  212. mach_port_t name =
  213. MACH_PORT_MAKEB(index, entry->ie_bits);
  214. ipc_right_clean(space, name, entry);
  215. }
  216. }
  217. it_entries_free(space->is_table_next-1, table);
  218. for (tentry = ipc_splay_traverse_start(&space->is_tree);
  219. tentry != ITE_NULL;
  220. tentry = ipc_splay_traverse_next(&space->is_tree, TRUE)) {
  221. mach_port_type_t type = IE_BITS_TYPE(tentry->ite_bits);
  222. mach_port_t name = tentry->ite_name;
  223. assert(type != MACH_PORT_TYPE_NONE);
  224. /* use object before ipc_right_clean releases ref */
  225. if (type == MACH_PORT_TYPE_SEND)
  226. ipc_hash_global_delete(space, tentry->ite_object,
  227. name, tentry);
  228. ipc_right_clean(space, name, &tentry->ite_entry);
  229. }
  230. ipc_splay_traverse_finish(&space->is_tree);
  231. /*
  232. * Because the space is now dead,
  233. * we must release the "active" reference for it.
  234. * Our caller still has his reference.
  235. */
  236. is_release(space);
  237. }