2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
59 * File: ipc/ipc_entry.c
63 * Primitive functions to manipulate translation entries.
67 #include <mach_debug.h>
69 #include <mach/kern_return.h>
70 #include <mach/port.h>
71 #include <kern/assert.h>
72 #include <kern/sched_prim.h>
73 #include <kern/zalloc.h>
74 #include <kern/misc_protos.h>
76 #include <kern/task.h>
79 #include <ipc/ipc_entry.h>
80 #include <ipc/ipc_space.h>
81 #include <ipc/ipc_splay.h>
82 #include <ipc/ipc_object.h>
83 #include <ipc/ipc_hash.h>
84 #include <ipc/ipc_table.h>
85 #include <ipc/ipc_port.h>
88 zone_t ipc_tree_entry_zone
;
93 * Forward declarations
95 boolean_t
ipc_entry_tree_collision(
97 mach_port_name_t name
);
100 * Routine: ipc_entry_tree_collision
102 * Checks if "name" collides with an allocated name
103 * in the space's tree. That is, returns TRUE
104 * if the splay tree contains a name with the same
107 * The space is locked (read or write) and active.
111 ipc_entry_tree_collision(
113 mach_port_name_t name
)
115 mach_port_index_t index
;
116 mach_port_name_t lower
, upper
;
118 assert(space
->is_active
);
121 * Check if we collide with the next smaller name
122 * or the next larger name.
125 ipc_splay_tree_bounds(&space
->is_tree
, name
, &lower
, &upper
);
127 index
= MACH_PORT_INDEX(name
);
128 return (((lower
!= (mach_port_name_t
)~0) &&
129 (MACH_PORT_INDEX(lower
) == index
)) ||
130 ((upper
!= 0) && (MACH_PORT_INDEX(upper
) == index
)));
134 * Routine: ipc_entry_lookup
136 * Searches for an entry, given its name.
138 * The space must be read or write locked throughout.
139 * The space must be active.
145 mach_port_name_t name
)
147 mach_port_index_t index
;
150 assert(space
->is_active
);
153 index
= MACH_PORT_INDEX(name
);
155 * If space is fast, we assume no splay tree and name within table
156 * bounds, but still check generation numbers (if enabled) and
157 * look for null entries.
159 if (is_fast_space(space
)) {
160 entry
= &space
->is_table
[index
];
161 if (IE_BITS_GEN(entry
->ie_bits
) != MACH_PORT_GEN(name
) ||
162 IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
166 if (index
< space
->is_table_size
) {
167 entry
= &space
->is_table
[index
];
168 if (IE_BITS_GEN(entry
->ie_bits
) != MACH_PORT_GEN(name
))
169 if (entry
->ie_bits
& IE_BITS_COLLISION
) {
170 assert(space
->is_tree_total
> 0);
174 else if (IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_NONE
)
176 } else if (space
->is_tree_total
== 0)
180 entry
= (ipc_entry_t
)
181 ipc_splay_tree_lookup(&space
->is_tree
, name
);
182 /* with sub-space introduction, an entry may appear in */
183 /* the splay tree and yet not show rights for this subspace */
184 if(entry
!= IE_NULL
) {
185 if(!(IE_BITS_TYPE(entry
->ie_bits
)))
190 assert((entry
== IE_NULL
) || IE_BITS_TYPE(entry
->ie_bits
));
195 * Routine: ipc_entry_get
197 * Tries to allocate an entry out of the space.
199 * The space is write-locked and active throughout.
200 * An object may be locked. Will not allocate memory.
202 * KERN_SUCCESS A free entry was found.
203 * KERN_NO_SPACE No entry allocated.
209 mach_port_name_t
*namep
,
213 mach_port_index_t first_free
;
214 ipc_entry_t free_entry
;
216 assert(space
->is_active
);
219 table
= space
->is_table
;
220 first_free
= table
->ie_next
;
223 return KERN_NO_SPACE
;
225 free_entry
= &table
[first_free
];
226 table
->ie_next
= free_entry
->ie_next
;
230 * Initialize the new entry. We need only
231 * increment the generation number and clear ie_request.
234 mach_port_name_t new_name
;
237 gen
= IE_BITS_NEW_GEN(free_entry
->ie_bits
);
238 free_entry
->ie_bits
= gen
;
239 free_entry
->ie_request
= 0;
242 * The new name can't be MACH_PORT_NULL because index
243 * is non-zero. It can't be MACH_PORT_DEAD because
244 * the table isn't allowed to grow big enough.
245 * (See comment in ipc/ipc_table.h.)
247 new_name
= MACH_PORT_MAKE(first_free
, gen
);
248 assert(MACH_PORT_VALID(new_name
));
252 assert(free_entry
->ie_object
== IO_NULL
);
254 *entryp
= free_entry
;
259 * Routine: ipc_entry_alloc
261 * Allocate an entry out of the space.
263 * The space is not locked before, but it is write-locked after
264 * if the call is successful. May allocate memory.
266 * KERN_SUCCESS An entry was allocated.
267 * KERN_INVALID_TASK The space is dead.
268 * KERN_NO_SPACE No room for an entry in the space.
269 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory for an entry.
275 mach_port_name_t
*namep
,
280 is_write_lock(space
);
283 if (!space
->is_active
) {
284 is_write_unlock(space
);
285 return KERN_INVALID_TASK
;
288 kr
= ipc_entry_get(space
, namep
, entryp
);
289 if (kr
== KERN_SUCCESS
)
292 kr
= ipc_entry_grow_table(space
, ITS_SIZE_NONE
);
293 if (kr
!= KERN_SUCCESS
)
294 return kr
; /* space is unlocked */
299 * Routine: ipc_entry_alloc_name
301 * Allocates/finds an entry with a specific name.
302 * If an existing entry is returned, its type will be nonzero.
304 * The space is not locked before, but it is write-locked after
305 * if the call is successful. May allocate memory.
307 * KERN_SUCCESS Found existing entry with same name.
308 * KERN_SUCCESS Allocated a new entry.
309 * KERN_INVALID_TASK The space is dead.
310 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
314 ipc_entry_alloc_name(
316 mach_port_name_t name
,
319 mach_port_index_t index
= MACH_PORT_INDEX(name
);
320 mach_port_gen_t gen
= MACH_PORT_GEN(name
);
321 ipc_tree_entry_t tentry
= ITE_NULL
;
323 assert(MACH_PORT_VALID(name
));
326 is_write_lock(space
);
330 ipc_tree_entry_t tentry2
;
331 ipc_table_size_t its
;
333 if (!space
->is_active
) {
334 is_write_unlock(space
);
335 if (tentry
) ite_free(tentry
);
336 return KERN_INVALID_TASK
;
340 * If we are under the table cutoff,
341 * there are usually four cases:
342 * 1) The entry is reserved (index 0)
343 * 2) The entry is inuse, for the same name
344 * 3) The entry is inuse, for a different name
345 * 4) The entry is free
346 * For a task with a "fast" IPC space, we disallow
347 * cases 1) and 3), because ports cannot be renamed.
349 if (index
< space
->is_table_size
) {
350 ipc_entry_t table
= space
->is_table
;
352 entry
= &table
[index
];
355 assert(!IE_BITS_TYPE(entry
->ie_bits
));
356 assert(!IE_BITS_GEN(entry
->ie_bits
));
357 } else if (IE_BITS_TYPE(entry
->ie_bits
)) {
358 if (IE_BITS_GEN(entry
->ie_bits
) == gen
) {
364 mach_port_index_t free_index
, next_index
;
367 * Rip the entry out of the free list.
371 (next_index
= table
[free_index
].ie_next
)
373 free_index
= next_index
)
376 table
[free_index
].ie_next
=
377 table
[next_index
].ie_next
;
379 entry
->ie_bits
= gen
;
380 entry
->ie_request
= 0;
383 assert(entry
->ie_object
== IO_NULL
);
384 if (is_fast_space(space
))
393 * In a fast space, ipc_entry_alloc_name may be
394 * used only to add a right to a port name already
395 * known in this space.
397 if (is_fast_space(space
)) {
398 is_write_unlock(space
);
404 * Before trying to allocate any memory,
405 * check if the entry already exists in the tree.
406 * This avoids spurious resource errors.
407 * The splay tree makes a subsequent lookup/insert
408 * of the same name cheap, so this costs little.
411 if ((space
->is_tree_total
> 0) &&
412 ((tentry2
= ipc_splay_tree_lookup(&space
->is_tree
, name
))
414 assert(tentry2
->ite_space
== space
);
415 assert(IE_BITS_TYPE(tentry2
->ite_bits
));
417 *entryp
= &tentry2
->ite_entry
;
418 if (tentry
) ite_free(tentry
);
422 its
= space
->is_table_next
;
425 * Check if the table should be grown.
427 * Note that if space->is_table_size == its->its_size,
428 * then we won't ever try to grow the table.
430 * Note that we are optimistically assuming that name
431 * doesn't collide with any existing names. (So if
432 * it were entered into the tree, is_tree_small would
433 * be incremented.) This is OK, because even in that
434 * case, we don't lose memory by growing the table.
436 if ((space
->is_table_size
<= index
) &&
437 (index
< its
->its_size
) &&
438 (((its
->its_size
- space
->is_table_size
) *
439 sizeof(struct ipc_entry
)) <
440 ((space
->is_tree_small
+ 1) *
441 sizeof(struct ipc_tree_entry
)))) {
445 * Can save space by growing the table.
446 * Because the space will be unlocked,
450 kr
= ipc_entry_grow_table(space
, ITS_SIZE_NONE
);
451 assert(kr
!= KERN_NO_SPACE
);
452 if (kr
!= KERN_SUCCESS
) {
453 /* space is unlocked */
454 if (tentry
) ite_free(tentry
);
462 * If a splay-tree entry was allocated previously,
463 * go ahead and insert it into the tree.
466 if (tentry
!= ITE_NULL
) {
468 space
->is_tree_total
++;
470 if (index
< space
->is_table_size
) {
471 entry
= &space
->is_table
[index
];
472 entry
->ie_bits
|= IE_BITS_COLLISION
;
473 } else if ((index
< its
->its_size
) &&
474 !ipc_entry_tree_collision(space
, name
))
475 space
->is_tree_small
++;
477 ipc_splay_tree_insert(&space
->is_tree
, name
, tentry
);
478 tentry
->ite_bits
= 0;
479 tentry
->ite_request
= 0;
480 tentry
->ite_object
= IO_NULL
;
481 tentry
->ite_space
= space
;
482 *entryp
= &tentry
->ite_entry
;
487 * Allocate a tree entry and try again.
490 is_write_unlock(space
);
491 tentry
= ite_alloc();
492 if (tentry
== ITE_NULL
)
493 return KERN_RESOURCE_SHORTAGE
;
494 is_write_lock(space
);
499 * Routine: ipc_entry_dealloc
501 * Deallocates an entry from a space.
503 * The space must be write-locked throughout.
504 * The space must be active.
510 mach_port_name_t name
,
514 ipc_entry_num_t size
;
515 mach_port_index_t index
;
517 assert(space
->is_active
);
518 assert(entry
->ie_object
== IO_NULL
);
519 assert(entry
->ie_request
== 0);
521 index
= MACH_PORT_INDEX(name
);
522 table
= space
->is_table
;
523 size
= space
->is_table_size
;
525 if (is_fast_space(space
)) {
526 assert(index
< size
);
527 assert(entry
== &table
[index
]);
528 assert(IE_BITS_GEN(entry
->ie_bits
) == MACH_PORT_GEN(name
));
529 assert(!(entry
->ie_bits
& IE_BITS_COLLISION
));
530 entry
->ie_bits
&= IE_BITS_GEN_MASK
;
531 entry
->ie_next
= table
->ie_next
;
532 table
->ie_next
= index
;
537 if ((index
< size
) && (entry
== &table
[index
])) {
538 assert(IE_BITS_GEN(entry
->ie_bits
) == MACH_PORT_GEN(name
));
540 if (entry
->ie_bits
& IE_BITS_COLLISION
) {
541 struct ipc_splay_tree small
, collisions
;
542 ipc_tree_entry_t tentry
;
543 mach_port_name_t tname
;
547 /* must move an entry from tree to table */
549 ipc_splay_tree_split(&space
->is_tree
,
550 MACH_PORT_MAKE(index
+1, 0),
552 ipc_splay_tree_split(&collisions
,
553 MACH_PORT_MAKE(index
, 0),
556 pick
= ipc_splay_tree_pick(&collisions
,
559 assert(MACH_PORT_INDEX(tname
) == index
);
561 entry
->ie_object
= obj
= tentry
->ite_object
;
562 entry
->ie_bits
= tentry
->ite_bits
|MACH_PORT_GEN(tname
);
563 entry
->ie_request
= tentry
->ite_request
;
565 assert(tentry
->ite_space
== space
);
567 if (IE_BITS_TYPE(tentry
->ite_bits
)==MACH_PORT_TYPE_SEND
) {
568 ipc_hash_global_delete(space
, obj
,
570 ipc_hash_local_insert(space
, obj
,
574 ipc_splay_tree_delete(&collisions
, tname
, tentry
);
576 assert(space
->is_tree_total
> 0);
577 space
->is_tree_total
--;
579 /* check if collision bit should still be on */
581 pick
= ipc_splay_tree_pick(&collisions
,
584 entry
->ie_bits
|= IE_BITS_COLLISION
;
585 ipc_splay_tree_join(&space
->is_tree
,
589 ipc_splay_tree_join(&space
->is_tree
, &small
);
592 entry
->ie_bits
&= IE_BITS_GEN_MASK
;
593 entry
->ie_next
= table
->ie_next
;
594 table
->ie_next
= index
;
598 ipc_tree_entry_t tentry
= (ipc_tree_entry_t
) entry
;
600 assert(tentry
->ite_space
== space
);
602 ipc_splay_tree_delete(&space
->is_tree
, name
, tentry
);
604 assert(space
->is_tree_total
> 0);
605 space
->is_tree_total
--;
608 ipc_entry_t ientry
= &table
[index
];
610 assert(ientry
->ie_bits
& IE_BITS_COLLISION
);
612 if (!ipc_entry_tree_collision(space
, name
))
613 ientry
->ie_bits
&= ~IE_BITS_COLLISION
;
615 } else if ((index
< space
->is_table_next
->its_size
) &&
616 !ipc_entry_tree_collision(space
, name
)) {
618 assert(space
->is_tree_small
> 0);
620 space
->is_tree_small
--;
626 * Routine: ipc_entry_grow_table
628 * Grows the table in a space.
630 * The space must be write-locked and active before.
631 * If successful, it is also returned locked.
634 * KERN_SUCCESS Grew the table.
635 * KERN_SUCCESS Somebody else grew the table.
636 * KERN_SUCCESS The space died.
637 * KERN_NO_SPACE Table has maximum size already.
638 * KERN_RESOURCE_SHORTAGE Couldn't allocate a new table.
642 ipc_entry_grow_table(
644 ipc_table_elems_t target_size
)
646 ipc_entry_num_t osize
, size
, nsize
, psize
;
649 boolean_t reallocated
=FALSE
;
651 ipc_entry_t otable
, table
;
652 ipc_table_size_t oits
, its
, nits
;
653 mach_port_index_t i
, free_index
;
655 assert(space
->is_active
);
657 if (space
->is_growing
) {
659 * Somebody else is growing the table.
660 * We just wait for them to finish.
663 is_write_sleep(space
);
667 otable
= space
->is_table
;
669 its
= space
->is_table_next
;
670 size
= its
->its_size
;
673 * Since is_table_next points to the next natural size
674 * we can identify the current size entry.
677 osize
= oits
->its_size
;
680 * If there is no target size, then the new size is simply
681 * specified by is_table_next. If there is a target
682 * size, then search for the next entry.
684 if (target_size
!= ITS_SIZE_NONE
) {
685 if (target_size
<= osize
) {
686 is_write_unlock(space
);
691 while ((psize
!= size
) && (target_size
> size
)) {
694 size
= its
->its_size
;
697 is_write_unlock(space
);
698 return KERN_NO_SPACE
;
703 is_write_unlock(space
);
704 return KERN_NO_SPACE
;
708 nsize
= nits
->its_size
;
710 assert((osize
< size
) && (size
<= nsize
));
713 * OK, we'll attempt to grow the table.
714 * The realloc requires that the old table
715 * remain in existence.
718 space
->is_growing
= TRUE
;
719 is_write_unlock(space
);
721 if (it_entries_reallocable(oits
)) {
722 table
= it_entries_realloc(oits
, otable
, its
);
726 table
= it_entries_alloc(its
);
729 is_write_lock(space
);
730 space
->is_growing
= FALSE
;
733 * We need to do a wakeup on the space,
734 * to rouse waiting threads. We defer
735 * this until the space is unlocked,
736 * because we don't want them to spin.
739 if (table
== IE_NULL
) {
740 is_write_unlock(space
);
741 thread_wakeup((event_t
) space
);
742 return KERN_RESOURCE_SHORTAGE
;
745 if (!space
->is_active
) {
747 * The space died while it was unlocked.
750 is_write_unlock(space
);
751 thread_wakeup((event_t
) space
);
752 it_entries_free(its
, table
);
753 is_write_lock(space
);
757 assert(space
->is_table
== otable
);
758 assert((space
->is_table_next
== its
) ||
759 (target_size
!= ITS_SIZE_NONE
));
760 assert(space
->is_table_size
== osize
);
762 space
->is_table
= table
;
763 space
->is_table_size
= size
;
764 space
->is_table_next
= nits
;
767 * If we did a realloc, it remapped the data.
768 * Otherwise we copy by hand first. Then we have
769 * to zero the new part and the old local hash
773 (void) memcpy((void *) table
, (const void *) otable
,
774 osize
* (sizeof(struct ipc_entry
)));
776 for (i
= 0; i
< osize
; i
++)
777 table
[i
].ie_index
= 0;
779 (void) memset((void *) (table
+ osize
) , 0,
780 ((size
- osize
) * (sizeof(struct ipc_entry
))));
783 * Put old entries into the reverse hash table.
785 for (i
= 0; i
< osize
; i
++) {
786 ipc_entry_t entry
= &table
[i
];
788 if (IE_BITS_TYPE(entry
->ie_bits
)==MACH_PORT_TYPE_SEND
) {
789 ipc_hash_local_insert(space
, entry
->ie_object
,
795 * If there are entries in the splay tree,
796 * then we have work to do:
797 * 1) transfer entries to the table
798 * 2) update is_tree_small
800 assert(!is_fast_space(space
) || space
->is_tree_total
== 0);
801 if (space
->is_tree_total
> 0) {
802 mach_port_index_t index
;
804 struct ipc_splay_tree ignore
;
805 struct ipc_splay_tree move
;
806 struct ipc_splay_tree small
;
807 ipc_entry_num_t nosmall
;
808 ipc_tree_entry_t tentry
;
811 * The splay tree divides into four regions,
812 * based on the index of the entries:
813 * 1) 0 <= index < osize
814 * 2) osize <= index < size
815 * 3) size <= index < nsize
818 * Entries in the first part are ignored.
819 * Entries in the second part, that don't
820 * collide, are moved into the table.
821 * Entries in the third part, that don't
822 * collide, are counted for is_tree_small.
823 * Entries in the fourth part are ignored.
826 ipc_splay_tree_split(&space
->is_tree
,
827 MACH_PORT_MAKE(nsize
, 0),
829 ipc_splay_tree_split(&small
,
830 MACH_PORT_MAKE(size
, 0),
832 ipc_splay_tree_split(&move
,
833 MACH_PORT_MAKE(osize
, 0),
836 /* move entries into the table */
838 for (tentry
= ipc_splay_traverse_start(&move
);
840 tentry
= ipc_splay_traverse_next(&move
, delete)) {
842 mach_port_name_t name
;
844 mach_port_type_t type
;
845 ipc_entry_bits_t bits
;
849 name
= tentry
->ite_name
;
850 gen
= MACH_PORT_GEN(name
);
851 index
= MACH_PORT_INDEX(name
);
853 assert(tentry
->ite_space
== space
);
854 assert((osize
<= index
) && (index
< size
));
856 entry
= &table
[index
];
857 bits
= entry
->ie_bits
;
858 if (IE_BITS_TYPE(bits
)) {
859 assert(IE_BITS_GEN(bits
) != gen
);
860 entry
->ie_bits
|= IE_BITS_COLLISION
;
865 bits
= tentry
->ite_bits
;
866 type
= IE_BITS_TYPE(bits
);
867 assert(type
!= MACH_PORT_TYPE_NONE
);
869 entry
->ie_bits
= bits
| gen
;
870 entry
->ie_request
= tentry
->ite_request
;
871 entry
->ie_object
= obj
= tentry
->ite_object
;
873 if (type
== MACH_PORT_TYPE_SEND
) {
874 ipc_hash_global_delete(space
, obj
,
876 ipc_hash_local_insert(space
, obj
,
879 space
->is_tree_total
--;
882 ipc_splay_traverse_finish(&move
);
884 /* count entries for is_tree_small */
886 nosmall
= 0; index
= 0;
887 for (tentry
= ipc_splay_traverse_start(&small
);
889 tentry
= ipc_splay_traverse_next(&small
, FALSE
)) {
890 mach_port_index_t nindex
;
892 nindex
= MACH_PORT_INDEX(tentry
->ite_name
);
894 if (nindex
!= index
) {
899 ipc_splay_traverse_finish(&small
);
901 assert(nosmall
<= (nsize
- size
));
902 assert(nosmall
<= space
->is_tree_total
);
903 space
->is_tree_small
= nosmall
;
905 /* put the splay tree back together */
907 ipc_splay_tree_join(&space
->is_tree
, &small
);
908 ipc_splay_tree_join(&space
->is_tree
, &move
);
909 ipc_splay_tree_join(&space
->is_tree
, &ignore
);
913 * Add entries in the new part which still aren't used
914 * to the free list. Add them in reverse order,
915 * and set the generation number to -1, so that
916 * early allocations produce "natural" names.
919 free_index
= table
[0].ie_next
;
920 for (i
= size
-1; i
>= osize
; --i
) {
921 ipc_entry_t entry
= &table
[i
];
923 if (entry
->ie_bits
== 0) {
924 entry
->ie_bits
= IE_BITS_GEN_MASK
;
925 entry
->ie_next
= free_index
;
929 table
[0].ie_next
= free_index
;
932 * Now we need to free the old table.
933 * If the space dies or grows while unlocked,
934 * then we can quit here.
936 is_write_unlock(space
);
937 thread_wakeup((event_t
) space
);
939 it_entries_free(oits
, otable
);
940 is_write_lock(space
);
941 if (!space
->is_active
|| (space
->is_table_next
!= nits
))
945 * We might have moved enough entries from
946 * the splay tree into the table that
947 * the table can be profitably grown again.
949 * Note that if size == nsize, then
950 * space->is_tree_small == 0.
952 } while ((space
->is_tree_small
> 0) &&
953 (((nsize
- size
) * sizeof(struct ipc_entry
)) <
954 (space
->is_tree_small
* sizeof(struct ipc_tree_entry
))));
961 #include <ddb/db_output.h>
962 #define printf kdbprintf
964 ipc_entry_t
db_ipc_object_by_name(
966 mach_port_name_t name
);
970 db_ipc_object_by_name(
972 mach_port_name_t name
)
974 ipc_space_t space
= task
->itk_space
;
978 entry
= ipc_entry_lookup(space
, name
);
979 if(entry
!= IE_NULL
) {
980 iprintf("(task 0x%x, name 0x%x) ==> object 0x%x\n",
981 task
, name
, entry
->ie_object
);
982 return (ipc_entry_t
) entry
->ie_object
;
986 #endif /* MACH_KDB */