2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
34 * Mach Operating System
35 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
36 * All Rights Reserved.
38 * Permission to use, copy, modify and distribute this software and its
39 * documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
46 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
48 * Carnegie Mellon requests users of this software to return to
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
61 * File: ipc/ipc_entry.c
65 * Primitive functions to manipulate translation entries.
69 #include <mach_debug.h>
71 #include <mach/kern_return.h>
72 #include <mach/port.h>
73 #include <kern/assert.h>
74 #include <kern/sched_prim.h>
75 #include <kern/zalloc.h>
76 #include <kern/misc_protos.h>
78 #include <kern/task.h>
81 #include <ipc/ipc_entry.h>
82 #include <ipc/ipc_space.h>
83 #include <ipc/ipc_splay.h>
84 #include <ipc/ipc_object.h>
85 #include <ipc/ipc_hash.h>
86 #include <ipc/ipc_table.h>
87 #include <ipc/ipc_port.h>
90 zone_t ipc_tree_entry_zone
;
95 * Forward declarations
97 boolean_t
ipc_entry_tree_collision(
99 mach_port_name_t name
);
102 * Routine: ipc_entry_tree_collision
104 * Checks if "name" collides with an allocated name
105 * in the space's tree. That is, returns TRUE
106 * if the splay tree contains a name with the same
109 * The space is locked (read or write) and active.
113 ipc_entry_tree_collision(
115 mach_port_name_t name
)
117 mach_port_index_t index
;
118 mach_port_name_t lower
, upper
;
120 assert(space
->is_active
);
123 * Check if we collide with the next smaller name
124 * or the next larger name.
127 ipc_splay_tree_bounds(&space
->is_tree
, name
, &lower
, &upper
);
129 index
= MACH_PORT_INDEX(name
);
130 return (((lower
!= (mach_port_name_t
)~0) &&
131 (MACH_PORT_INDEX(lower
) == index
)) ||
132 ((upper
!= 0) && (MACH_PORT_INDEX(upper
) == index
)));
136 * Routine: ipc_entry_lookup
138 * Searches for an entry, given its name.
140 * The space must be read or write locked throughout.
141 * The space must be active.
147 mach_port_name_t name
)
149 mach_port_index_t index
;
152 assert(space
->is_active
);
155 index
= MACH_PORT_INDEX(name
);
157 * If space is fast, we assume no splay tree and name within table
158 * bounds, but still check generation numbers (if enabled) and
159 * look for null entries.
161 if (is_fast_space(space
)) {
162 entry
= &space
->is_table
[index
];
163 if (IE_BITS_GEN(entry
->ie_bits
) != MACH_PORT_GEN(name
) ||
164 IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
168 if (index
< space
->is_table_size
) {
169 entry
= &space
->is_table
[index
];
170 if (IE_BITS_GEN(entry
->ie_bits
) != MACH_PORT_GEN(name
))
171 if (entry
->ie_bits
& IE_BITS_COLLISION
) {
172 assert(space
->is_tree_total
> 0);
176 else if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
178 } else if (space
->is_tree_total
== 0)
182 entry
= (ipc_entry_t
)
183 ipc_splay_tree_lookup(&space
->is_tree
, name
);
184 /* with sub-space introduction, an entry may appear in */
185 /* the splay tree and yet not show rights for this subspace */
186 if(entry
!= IE_NULL
) {
187 if(!(IE_BITS_TYPE(entry
->ie_bits
)))
192 assert((entry
== IE_NULL
) || IE_BITS_TYPE(entry
->ie_bits
));
197 * Routine: ipc_entry_get
199 * Tries to allocate an entry out of the space.
201 * The space is write-locked and active throughout.
202 * An object may be locked. Will not allocate memory.
204 * KERN_SUCCESS A free entry was found.
205 * KERN_NO_SPACE No entry allocated.
211 mach_port_name_t
*namep
,
215 mach_port_index_t first_free
;
216 ipc_entry_t free_entry
;
218 assert(space
->is_active
);
221 table
= space
->is_table
;
222 first_free
= table
->ie_next
;
225 return KERN_NO_SPACE
;
227 free_entry
= &table
[first_free
];
228 table
->ie_next
= free_entry
->ie_next
;
232 * Initialize the new entry. We need only
233 * increment the generation number and clear ie_request.
236 mach_port_name_t new_name
;
239 gen
= IE_BITS_NEW_GEN(free_entry
->ie_bits
);
240 free_entry
->ie_bits
= gen
;
241 free_entry
->ie_request
= 0;
244 * The new name can't be MACH_PORT_NULL because index
245 * is non-zero. It can't be MACH_PORT_DEAD because
246 * the table isn't allowed to grow big enough.
247 * (See comment in ipc/ipc_table.h.)
249 new_name
= MACH_PORT_MAKE(first_free
, gen
);
250 assert(MACH_PORT_VALID(new_name
));
254 assert(free_entry
->ie_object
== IO_NULL
);
256 *entryp
= free_entry
;
261 * Routine: ipc_entry_alloc
263 * Allocate an entry out of the space.
265 * The space is not locked before, but it is write-locked after
266 * if the call is successful. May allocate memory.
268 * KERN_SUCCESS An entry was allocated.
269 * KERN_INVALID_TASK The space is dead.
270 * KERN_NO_SPACE No room for an entry in the space.
271 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory for an entry.
277 mach_port_name_t
*namep
,
282 is_write_lock(space
);
285 if (!space
->is_active
) {
286 is_write_unlock(space
);
287 return KERN_INVALID_TASK
;
290 kr
= ipc_entry_get(space
, namep
, entryp
);
291 if (kr
== KERN_SUCCESS
)
294 kr
= ipc_entry_grow_table(space
, ITS_SIZE_NONE
);
295 if (kr
!= KERN_SUCCESS
)
296 return kr
; /* space is unlocked */
301 * Routine: ipc_entry_alloc_name
303 * Allocates/finds an entry with a specific name.
304 * If an existing entry is returned, its type will be nonzero.
306 * The space is not locked before, but it is write-locked after
307 * if the call is successful. May allocate memory.
309 * KERN_SUCCESS Found existing entry with same name.
310 * KERN_SUCCESS Allocated a new entry.
311 * KERN_INVALID_TASK The space is dead.
312 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
316 ipc_entry_alloc_name(
318 mach_port_name_t name
,
321 mach_port_index_t index
= MACH_PORT_INDEX(name
);
322 mach_port_gen_t gen
= MACH_PORT_GEN(name
);
323 ipc_tree_entry_t tentry
= ITE_NULL
;
325 assert(MACH_PORT_VALID(name
));
328 is_write_lock(space
);
332 ipc_tree_entry_t tentry2
;
333 ipc_table_size_t its
;
335 if (!space
->is_active
) {
336 is_write_unlock(space
);
337 if (tentry
) ite_free(tentry
);
338 return KERN_INVALID_TASK
;
342 * If we are under the table cutoff,
343 * there are usually four cases:
344 * 1) The entry is reserved (index 0)
345 * 2) The entry is inuse, for the same name
346 * 3) The entry is inuse, for a different name
347 * 4) The entry is free
348 * For a task with a "fast" IPC space, we disallow
349 * cases 1) and 3), because ports cannot be renamed.
351 if (index
< space
->is_table_size
) {
352 ipc_entry_t table
= space
->is_table
;
354 entry
= &table
[index
];
357 assert(!IE_BITS_TYPE(entry
->ie_bits
));
358 assert(!IE_BITS_GEN(entry
->ie_bits
));
359 } else if (IE_BITS_TYPE(entry
->ie_bits
)) {
360 if (IE_BITS_GEN(entry
->ie_bits
) == gen
) {
366 mach_port_index_t free_index
, next_index
;
369 * Rip the entry out of the free list.
373 (next_index
= table
[free_index
].ie_next
)
375 free_index
= next_index
)
378 table
[free_index
].ie_next
=
379 table
[next_index
].ie_next
;
381 entry
->ie_bits
= gen
;
382 entry
->ie_request
= 0;
385 assert(entry
->ie_object
== IO_NULL
);
386 if (is_fast_space(space
))
395 * In a fast space, ipc_entry_alloc_name may be
396 * used only to add a right to a port name already
397 * known in this space.
399 if (is_fast_space(space
)) {
400 is_write_unlock(space
);
406 * Before trying to allocate any memory,
407 * check if the entry already exists in the tree.
408 * This avoids spurious resource errors.
409 * The splay tree makes a subsequent lookup/insert
410 * of the same name cheap, so this costs little.
413 if ((space
->is_tree_total
> 0) &&
414 ((tentry2
= ipc_splay_tree_lookup(&space
->is_tree
, name
))
416 assert(tentry2
->ite_space
== space
);
417 assert(IE_BITS_TYPE(tentry2
->ite_bits
));
419 *entryp
= &tentry2
->ite_entry
;
420 if (tentry
) ite_free(tentry
);
424 its
= space
->is_table_next
;
427 * Check if the table should be grown.
429 * Note that if space->is_table_size == its->its_size,
430 * then we won't ever try to grow the table.
432 * Note that we are optimistically assuming that name
433 * doesn't collide with any existing names. (So if
434 * it were entered into the tree, is_tree_small would
435 * be incremented.) This is OK, because even in that
436 * case, we don't lose memory by growing the table.
438 if ((space
->is_table_size
<= index
) &&
439 (index
< its
->its_size
) &&
440 (((its
->its_size
- space
->is_table_size
) *
441 sizeof(struct ipc_entry
)) <
442 ((space
->is_tree_small
+ 1) *
443 sizeof(struct ipc_tree_entry
)))) {
447 * Can save space by growing the table.
448 * Because the space will be unlocked,
452 kr
= ipc_entry_grow_table(space
, ITS_SIZE_NONE
);
453 assert(kr
!= KERN_NO_SPACE
);
454 if (kr
!= KERN_SUCCESS
) {
455 /* space is unlocked */
456 if (tentry
) ite_free(tentry
);
464 * If a splay-tree entry was allocated previously,
465 * go ahead and insert it into the tree.
468 if (tentry
!= ITE_NULL
) {
470 space
->is_tree_total
++;
472 if (index
< space
->is_table_size
) {
473 entry
= &space
->is_table
[index
];
474 entry
->ie_bits
|= IE_BITS_COLLISION
;
475 } else if ((index
< its
->its_size
) &&
476 !ipc_entry_tree_collision(space
, name
))
477 space
->is_tree_small
++;
479 ipc_splay_tree_insert(&space
->is_tree
, name
, tentry
);
480 tentry
->ite_bits
= 0;
481 tentry
->ite_request
= 0;
482 tentry
->ite_object
= IO_NULL
;
483 tentry
->ite_space
= space
;
484 *entryp
= &tentry
->ite_entry
;
489 * Allocate a tree entry and try again.
492 is_write_unlock(space
);
493 tentry
= ite_alloc();
494 if (tentry
== ITE_NULL
)
495 return KERN_RESOURCE_SHORTAGE
;
496 is_write_lock(space
);
501 * Routine: ipc_entry_dealloc
503 * Deallocates an entry from a space.
505 * The space must be write-locked throughout.
506 * The space must be active.
512 mach_port_name_t name
,
516 ipc_entry_num_t size
;
517 mach_port_index_t index
;
519 assert(space
->is_active
);
520 assert(entry
->ie_object
== IO_NULL
);
521 assert(entry
->ie_request
== 0);
523 index
= MACH_PORT_INDEX(name
);
524 table
= space
->is_table
;
525 size
= space
->is_table_size
;
527 if (is_fast_space(space
)) {
528 assert(index
< size
);
529 assert(entry
== &table
[index
]);
530 assert(IE_BITS_GEN(entry
->ie_bits
) == MACH_PORT_GEN(name
));
531 assert(!(entry
->ie_bits
& IE_BITS_COLLISION
));
532 entry
->ie_bits
&= IE_BITS_GEN_MASK
;
533 entry
->ie_next
= table
->ie_next
;
534 table
->ie_next
= index
;
539 if ((index
< size
) && (entry
== &table
[index
])) {
540 assert(IE_BITS_GEN(entry
->ie_bits
) == MACH_PORT_GEN(name
));
542 if (entry
->ie_bits
& IE_BITS_COLLISION
) {
543 struct ipc_splay_tree small
, collisions
;
544 ipc_tree_entry_t tentry
;
545 mach_port_name_t tname
;
549 /* must move an entry from tree to table */
551 ipc_splay_tree_split(&space
->is_tree
,
552 MACH_PORT_MAKE(index
+1, 0),
554 ipc_splay_tree_split(&collisions
,
555 MACH_PORT_MAKE(index
, 0),
558 pick
= ipc_splay_tree_pick(&collisions
,
561 assert(MACH_PORT_INDEX(tname
) == index
);
563 entry
->ie_object
= obj
= tentry
->ite_object
;
564 entry
->ie_bits
= tentry
->ite_bits
|MACH_PORT_GEN(tname
);
565 entry
->ie_request
= tentry
->ite_request
;
567 assert(tentry
->ite_space
== space
);
569 if (IE_BITS_TYPE(tentry
->ite_bits
)==MACH_PORT_TYPE_SEND
) {
570 ipc_hash_global_delete(space
, obj
,
572 ipc_hash_local_insert(space
, obj
,
576 ipc_splay_tree_delete(&collisions
, tname
, tentry
);
578 assert(space
->is_tree_total
> 0);
579 space
->is_tree_total
--;
581 /* check if collision bit should still be on */
583 pick
= ipc_splay_tree_pick(&collisions
,
586 entry
->ie_bits
|= IE_BITS_COLLISION
;
587 ipc_splay_tree_join(&space
->is_tree
,
591 ipc_splay_tree_join(&space
->is_tree
, &small
);
594 entry
->ie_bits
&= IE_BITS_GEN_MASK
;
595 entry
->ie_next
= table
->ie_next
;
596 table
->ie_next
= index
;
600 ipc_tree_entry_t tentry
= (ipc_tree_entry_t
) entry
;
602 assert(tentry
->ite_space
== space
);
604 ipc_splay_tree_delete(&space
->is_tree
, name
, tentry
);
606 assert(space
->is_tree_total
> 0);
607 space
->is_tree_total
--;
610 ipc_entry_t ientry
= &table
[index
];
612 assert(ientry
->ie_bits
& IE_BITS_COLLISION
);
614 if (!ipc_entry_tree_collision(space
, name
))
615 ientry
->ie_bits
&= ~IE_BITS_COLLISION
;
617 } else if ((index
< space
->is_table_next
->its_size
) &&
618 !ipc_entry_tree_collision(space
, name
)) {
620 assert(space
->is_tree_small
> 0);
622 space
->is_tree_small
--;
628 * Routine: ipc_entry_grow_table
630 * Grows the table in a space.
632 * The space must be write-locked and active before.
633 * If successful, it is also returned locked.
636 * KERN_SUCCESS Grew the table.
637 * KERN_SUCCESS Somebody else grew the table.
638 * KERN_SUCCESS The space died.
639 * KERN_NO_SPACE Table has maximum size already.
640 * KERN_RESOURCE_SHORTAGE Couldn't allocate a new table.
644 ipc_entry_grow_table(
646 ipc_table_elems_t target_size
)
648 ipc_entry_num_t osize
, size
, nsize
, psize
;
651 boolean_t reallocated
=FALSE
;
653 ipc_entry_t otable
, table
;
654 ipc_table_size_t oits
, its
, nits
;
655 mach_port_index_t i
, free_index
;
657 assert(space
->is_active
);
659 if (space
->is_growing
) {
661 * Somebody else is growing the table.
662 * We just wait for them to finish.
665 is_write_sleep(space
);
669 otable
= space
->is_table
;
671 its
= space
->is_table_next
;
672 size
= its
->its_size
;
675 * Since is_table_next points to the next natural size
676 * we can identify the current size entry.
679 osize
= oits
->its_size
;
682 * If there is no target size, then the new size is simply
683 * specified by is_table_next. If there is a target
684 * size, then search for the next entry.
686 if (target_size
!= ITS_SIZE_NONE
) {
687 if (target_size
<= osize
) {
688 is_write_unlock(space
);
693 while ((psize
!= size
) && (target_size
> size
)) {
696 size
= its
->its_size
;
699 is_write_unlock(space
);
700 return KERN_NO_SPACE
;
705 is_write_unlock(space
);
706 return KERN_NO_SPACE
;
710 nsize
= nits
->its_size
;
712 assert((osize
< size
) && (size
<= nsize
));
715 * OK, we'll attempt to grow the table.
716 * The realloc requires that the old table
717 * remain in existence.
720 space
->is_growing
= TRUE
;
721 is_write_unlock(space
);
723 if (it_entries_reallocable(oits
)) {
724 table
= it_entries_realloc(oits
, otable
, its
);
728 table
= it_entries_alloc(its
);
731 is_write_lock(space
);
732 space
->is_growing
= FALSE
;
735 * We need to do a wakeup on the space,
736 * to rouse waiting threads. We defer
737 * this until the space is unlocked,
738 * because we don't want them to spin.
741 if (table
== IE_NULL
) {
742 is_write_unlock(space
);
743 thread_wakeup((event_t
) space
);
744 return KERN_RESOURCE_SHORTAGE
;
747 if (!space
->is_active
) {
749 * The space died while it was unlocked.
752 is_write_unlock(space
);
753 thread_wakeup((event_t
) space
);
754 it_entries_free(its
, table
);
755 is_write_lock(space
);
759 assert(space
->is_table
== otable
);
760 assert((space
->is_table_next
== its
) ||
761 (target_size
!= ITS_SIZE_NONE
));
762 assert(space
->is_table_size
== osize
);
764 space
->is_table
= table
;
765 space
->is_table_size
= size
;
766 space
->is_table_next
= nits
;
769 * If we did a realloc, it remapped the data.
770 * Otherwise we copy by hand first. Then we have
771 * to zero the new part and the old local hash
775 (void) memcpy((void *) table
, (const void *) otable
,
776 osize
* (sizeof(struct ipc_entry
)));
778 for (i
= 0; i
< osize
; i
++)
779 table
[i
].ie_index
= 0;
781 (void) memset((void *) (table
+ osize
) , 0,
782 ((size
- osize
) * (sizeof(struct ipc_entry
))));
785 * Put old entries into the reverse hash table.
787 for (i
= 0; i
< osize
; i
++) {
788 ipc_entry_t entry
= &table
[i
];
790 if (IE_BITS_TYPE(entry
->ie_bits
)==MACH_PORT_TYPE_SEND
) {
791 ipc_hash_local_insert(space
, entry
->ie_object
,
797 * If there are entries in the splay tree,
798 * then we have work to do:
799 * 1) transfer entries to the table
800 * 2) update is_tree_small
802 assert(!is_fast_space(space
) || space
->is_tree_total
== 0);
803 if (space
->is_tree_total
> 0) {
804 mach_port_index_t index
;
806 struct ipc_splay_tree ignore
;
807 struct ipc_splay_tree move
;
808 struct ipc_splay_tree small
;
809 ipc_entry_num_t nosmall
;
810 ipc_tree_entry_t tentry
;
813 * The splay tree divides into four regions,
814 * based on the index of the entries:
815 * 1) 0 <= index < osize
816 * 2) osize <= index < size
817 * 3) size <= index < nsize
820 * Entries in the first part are ignored.
821 * Entries in the second part, that don't
822 * collide, are moved into the table.
823 * Entries in the third part, that don't
824 * collide, are counted for is_tree_small.
825 * Entries in the fourth part are ignored.
828 ipc_splay_tree_split(&space
->is_tree
,
829 MACH_PORT_MAKE(nsize
, 0),
831 ipc_splay_tree_split(&small
,
832 MACH_PORT_MAKE(size
, 0),
834 ipc_splay_tree_split(&move
,
835 MACH_PORT_MAKE(osize
, 0),
838 /* move entries into the table */
840 for (tentry
= ipc_splay_traverse_start(&move
);
842 tentry
= ipc_splay_traverse_next(&move
, delete)) {
844 mach_port_name_t name
;
846 mach_port_type_t type
;
847 ipc_entry_bits_t bits
;
851 name
= tentry
->ite_name
;
852 gen
= MACH_PORT_GEN(name
);
853 index
= MACH_PORT_INDEX(name
);
855 assert(tentry
->ite_space
== space
);
856 assert((osize
<= index
) && (index
< size
));
858 entry
= &table
[index
];
859 bits
= entry
->ie_bits
;
860 if (IE_BITS_TYPE(bits
)) {
861 assert(IE_BITS_GEN(bits
) != gen
);
862 entry
->ie_bits
|= IE_BITS_COLLISION
;
867 bits
= tentry
->ite_bits
;
868 type
= IE_BITS_TYPE(bits
);
869 assert(type
!= MACH_PORT_TYPE_NONE
);
871 entry
->ie_bits
= bits
| gen
;
872 entry
->ie_request
= tentry
->ite_request
;
873 entry
->ie_object
= obj
= tentry
->ite_object
;
875 if (type
== MACH_PORT_TYPE_SEND
) {
876 ipc_hash_global_delete(space
, obj
,
878 ipc_hash_local_insert(space
, obj
,
881 space
->is_tree_total
--;
884 ipc_splay_traverse_finish(&move
);
886 /* count entries for is_tree_small */
888 nosmall
= 0; index
= 0;
889 for (tentry
= ipc_splay_traverse_start(&small
);
891 tentry
= ipc_splay_traverse_next(&small
, FALSE
)) {
892 mach_port_index_t nindex
;
894 nindex
= MACH_PORT_INDEX(tentry
->ite_name
);
896 if (nindex
!= index
) {
901 ipc_splay_traverse_finish(&small
);
903 assert(nosmall
<= (nsize
- size
));
904 assert(nosmall
<= space
->is_tree_total
);
905 space
->is_tree_small
= nosmall
;
907 /* put the splay tree back together */
909 ipc_splay_tree_join(&space
->is_tree
, &small
);
910 ipc_splay_tree_join(&space
->is_tree
, &move
);
911 ipc_splay_tree_join(&space
->is_tree
, &ignore
);
915 * Add entries in the new part which still aren't used
916 * to the free list. Add them in reverse order,
917 * and set the generation number to -1, so that
918 * early allocations produce "natural" names.
921 free_index
= table
[0].ie_next
;
922 for (i
= size
-1; i
>= osize
; --i
) {
923 ipc_entry_t entry
= &table
[i
];
925 if (entry
->ie_bits
== 0) {
926 entry
->ie_bits
= IE_BITS_GEN_MASK
;
927 entry
->ie_next
= free_index
;
931 table
[0].ie_next
= free_index
;
934 * Now we need to free the old table.
935 * If the space dies or grows while unlocked,
936 * then we can quit here.
938 is_write_unlock(space
);
939 thread_wakeup((event_t
) space
);
941 it_entries_free(oits
, otable
);
942 is_write_lock(space
);
943 if (!space
->is_active
|| (space
->is_table_next
!= nits
))
947 * We might have moved enough entries from
948 * the splay tree into the table that
949 * the table can be profitably grown again.
951 * Note that if size == nsize, then
952 * space->is_tree_small == 0.
954 } while ((space
->is_tree_small
> 0) &&
955 (((nsize
- size
) * sizeof(struct ipc_entry
)) <
956 (space
->is_tree_small
* sizeof(struct ipc_tree_entry
))));
963 #include <ddb/db_output.h>
964 #define printf kdbprintf
966 ipc_entry_t
db_ipc_object_by_name(
968 mach_port_name_t name
);
972 db_ipc_object_by_name(
974 mach_port_name_t name
)
976 ipc_space_t space
= task
->itk_space
;
980 entry
= ipc_entry_lookup(space
, name
);
981 if(entry
!= IE_NULL
) {
982 iprintf("(task 0x%x, name 0x%x) ==> object 0x%x\n",
983 task
, name
, entry
->ie_object
);
984 return (ipc_entry_t
) entry
->ie_object
;
988 #endif /* MACH_KDB */