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_splay.c
63 * Primitive splay tree operations.
66 #include <mach/port.h>
67 #include <kern/assert.h>
68 #include <kern/macro_help.h>
69 #include <ipc/ipc_entry.h>
70 #include <ipc/ipc_splay.h>
73 * Splay trees are self-adjusting binary search trees.
74 * They have the following attractive properties:
75 * 1) Space efficient; only two pointers per entry.
76 * 2) Robust performance; amortized O(log n) per operation.
77 * 3) Recursion not needed.
78 * This makes them a good fall-back data structure for those
79 * entries that don't fit into the lookup table.
81 * The paper by Sleator and Tarjan, JACM v. 32, no. 3, pp. 652-686,
82 * describes the splaying operation. ipc_splay_prim_lookup
83 * and ipc_splay_prim_assemble implement the top-down splay
84 * described on p. 669.
86 * The tree is stored in an unassembled form. If ist_root is null,
87 * then the tree has no entries. Otherwise, ist_name records
88 * the value used for the last lookup. ist_root points to the
89 * middle tree obtained from the top-down splay. ist_ltree and
90 * ist_rtree point to left and right subtrees, whose entries
91 * are all smaller (larger) than those in the middle tree.
92 * ist_ltreep and ist_rtreep are pointers to fields in the
93 * left and right subtrees. ist_ltreep points to the rchild field
94 * of the largest entry in ltree, and ist_rtreep points to the
95 * lchild field of the smallest entry in rtree. The pointed-to
96 * fields aren't initialized. If the left (right) subtree is null,
97 * then ist_ltreep (ist_rtreep) points to the ist_ltree (ist_rtree)
98 * field in the splay structure itself.
100 * The primary advantage of the unassembled form is that repeated
101 * unsuccessful lookups are efficient. In particular, an unsuccessful
102 * lookup followed by an insert only requires one splaying operation.
104 * The traversal algorithm works via pointer inversion.
105 * When descending down the tree, child pointers are reversed
106 * to point back to the parent entry. When ascending,
107 * the pointers are restored to their original value.
109 * The biggest potential problem with the splay tree implementation
110 * is that the operations, even lookup, require an exclusive lock.
111 * If IPC spaces are protected with exclusive locks, then
112 * the splay tree doesn't require its own lock, and ist_lock/ist_unlock
113 * needn't do anything. If IPC spaces are protected with read/write
114 * locks then ist_lock/ist_unlock should provide exclusive access.
116 * If it becomes important to let lookups run in parallel,
117 * or if the restructuring makes lookups too expensive, then
118 * there is hope. Use a read/write lock on the splay tree.
119 * Keep track of the number of entries in the tree. When doing
120 * a lookup, first try a non-restructuring lookup with a read lock held,
121 * with a bound (based on log of size of the tree) on the number of
122 * entries to traverse. If the lookup runs up against the bound,
123 * then take a write lock and do a reorganizing lookup.
124 * This way, if lookups only access roughly balanced parts
125 * of the tree, then lookups run in parallel and do no restructuring.
127 * The traversal algorithm currently requires an exclusive lock.
128 * If that is a problem, the tree could be changed from an lchild/rchild
129 * representation to a leftmost child/right sibling representation.
130 * In conjunction with non-restructing lookups, this would let
131 * lookups and traversals all run in parallel. But this representation
132 * is more complicated and would slow down the operations.
136 * Boundary values to hand to ipc_splay_prim_lookup:
139 #define MACH_PORT_SMALLEST ((mach_port_name_t) 0)
140 #define MACH_PORT_LARGEST ((mach_port_name_t) ~0)
143 * Routine: ipc_splay_prim_lookup
145 * Searches for the node labeled name in the splay tree.
146 * Returns three nodes (treep, ltreep, rtreep) and
147 * two pointers to nodes (ltreepp, rtreepp).
149 * ipc_splay_prim_lookup splits the supplied tree into
150 * three subtrees, left, middle, and right, returned
151 * in ltreep, treep, and rtreep.
153 * If name is present in the tree, then it is at
154 * the root of the middle tree. Otherwise, the root
155 * of the middle tree is the last node traversed.
157 * ipc_splay_prim_lookup returns a pointer into
158 * the left subtree, to the rchild field of its
159 * largest node, in ltreepp. It returns a pointer
160 * into the right subtree, to the lchild field of its
161 * smallest node, in rtreepp.
165 ipc_splay_prim_lookup(
166 mach_port_name_t name
,
167 ipc_tree_entry_t tree
,
168 ipc_tree_entry_t
*treep
,
169 ipc_tree_entry_t
*ltreep
,
170 ipc_tree_entry_t
**ltreepp
,
171 ipc_tree_entry_t
*rtreep
,
172 ipc_tree_entry_t
**rtreepp
)
174 mach_port_name_t tname
; /* temp name */
175 ipc_tree_entry_t lchild
, rchild
; /* temp child pointers */
177 assert(tree
!= ITE_NULL
);
182 ltreep = &tree->ite_rchild; \
189 rtreep = &tree->ite_lchild; \
193 #define rotate_left \
195 ipc_tree_entry_t temp = tree; \
197 tree = temp->ite_rchild; \
198 temp->ite_rchild = tree->ite_lchild; \
199 tree->ite_lchild = temp; \
202 #define rotate_right \
204 ipc_tree_entry_t temp = tree; \
206 tree = temp->ite_lchild; \
207 temp->ite_lchild = tree->ite_rchild; \
208 tree->ite_rchild = temp; \
211 while (name
!= (tname
= tree
->ite_name
)) {
213 /* descend to left */
215 lchild
= tree
->ite_lchild
;
216 if (lchild
== ITE_NULL
)
218 tname
= lchild
->ite_name
;
220 if ((name
< tname
) &&
221 (lchild
->ite_lchild
!= ITE_NULL
))
224 if ((name
> tname
) &&
225 (lchild
->ite_rchild
!= ITE_NULL
))
228 /* descend to right */
230 rchild
= tree
->ite_rchild
;
231 if (rchild
== ITE_NULL
)
233 tname
= rchild
->ite_name
;
235 if ((name
> tname
) &&
236 (rchild
->ite_rchild
!= ITE_NULL
))
239 if ((name
< tname
) &&
240 (rchild
->ite_lchild
!= ITE_NULL
))
244 assert(tree
!= ITE_NULL
);
258 * Routine: ipc_splay_prim_assemble
260 * Assembles the results of ipc_splay_prim_lookup
261 * into a splay tree with the found node at the root.
263 * ltree and rtree are by-reference so storing
264 * through ltreep and rtreep can change them.
268 ipc_splay_prim_assemble(
269 ipc_tree_entry_t tree
,
270 ipc_tree_entry_t
*ltree
,
271 ipc_tree_entry_t
*ltreep
,
272 ipc_tree_entry_t
*rtree
,
273 ipc_tree_entry_t
*rtreep
)
275 assert(tree
!= ITE_NULL
);
277 *ltreep
= tree
->ite_lchild
;
278 *rtreep
= tree
->ite_rchild
;
280 tree
->ite_lchild
= *ltree
;
281 tree
->ite_rchild
= *rtree
;
285 * Routine: ipc_splay_tree_init
287 * Initialize a raw splay tree for use.
292 ipc_splay_tree_t splay
)
294 splay
->ist_root
= ITE_NULL
;
298 * Routine: ipc_splay_tree_pick
300 * Picks and returns a random entry in a splay tree.
301 * Returns FALSE if the splay tree is empty.
306 ipc_splay_tree_t splay
,
307 mach_port_name_t
*namep
,
308 ipc_tree_entry_t
*entryp
)
310 ipc_tree_entry_t root
;
314 root
= splay
->ist_root
;
315 if (root
!= ITE_NULL
) {
316 *namep
= root
->ite_name
;
322 return root
!= ITE_NULL
;
326 * Routine: ipc_splay_tree_lookup
328 * Finds an entry in a splay tree.
329 * Returns ITE_NULL if not found.
333 ipc_splay_tree_lookup(
334 ipc_splay_tree_t splay
,
335 mach_port_name_t name
)
337 ipc_tree_entry_t root
;
341 root
= splay
->ist_root
;
342 if (root
!= ITE_NULL
) {
343 if (splay
->ist_name
!= name
) {
344 ipc_splay_prim_assemble(root
,
345 &splay
->ist_ltree
, splay
->ist_ltreep
,
346 &splay
->ist_rtree
, splay
->ist_rtreep
);
347 ipc_splay_prim_lookup(name
, root
, &root
,
348 &splay
->ist_ltree
, &splay
->ist_ltreep
,
349 &splay
->ist_rtree
, &splay
->ist_rtreep
);
350 splay
->ist_name
= name
;
351 splay
->ist_root
= root
;
354 if (name
!= root
->ite_name
)
364 * Routine: ipc_splay_tree_insert
366 * Inserts a new entry into a splay tree.
367 * The caller supplies a new entry.
368 * The name can't already be present in the tree.
372 ipc_splay_tree_insert(
373 ipc_splay_tree_t splay
,
374 mach_port_name_t name
,
375 ipc_tree_entry_t entry
)
377 ipc_tree_entry_t root
;
379 assert(entry
!= ITE_NULL
);
383 root
= splay
->ist_root
;
384 if (root
== ITE_NULL
) {
385 entry
->ite_lchild
= ITE_NULL
;
386 entry
->ite_rchild
= ITE_NULL
;
388 if (splay
->ist_name
!= name
) {
389 ipc_splay_prim_assemble(root
,
390 &splay
->ist_ltree
, splay
->ist_ltreep
,
391 &splay
->ist_rtree
, splay
->ist_rtreep
);
392 ipc_splay_prim_lookup(name
, root
, &root
,
393 &splay
->ist_ltree
, &splay
->ist_ltreep
,
394 &splay
->ist_rtree
, &splay
->ist_rtreep
);
397 assert(root
->ite_name
!= name
);
399 if (name
< root
->ite_name
) {
400 assert(root
->ite_lchild
== ITE_NULL
);
402 *splay
->ist_ltreep
= ITE_NULL
;
403 *splay
->ist_rtreep
= root
;
405 assert(root
->ite_rchild
== ITE_NULL
);
407 *splay
->ist_ltreep
= root
;
408 *splay
->ist_rtreep
= ITE_NULL
;
411 entry
->ite_lchild
= splay
->ist_ltree
;
412 entry
->ite_rchild
= splay
->ist_rtree
;
415 entry
->ite_name
= name
;
416 splay
->ist_root
= entry
;
417 splay
->ist_name
= name
;
418 splay
->ist_ltreep
= &splay
->ist_ltree
;
419 splay
->ist_rtreep
= &splay
->ist_rtree
;
425 * Routine: ipc_splay_tree_delete
427 * Deletes an entry from a splay tree.
428 * The name must be present in the tree.
431 * The "entry" argument isn't currently used.
432 * Other implementations might want it, though.
436 ipc_splay_tree_delete(
437 ipc_splay_tree_t splay
,
438 mach_port_name_t name
,
439 __assert_only ipc_tree_entry_t entry
)
441 ipc_tree_entry_t root
, saved
;
445 root
= splay
->ist_root
;
446 assert(root
!= ITE_NULL
);
448 if (splay
->ist_name
!= name
) {
449 ipc_splay_prim_assemble(root
,
450 &splay
->ist_ltree
, splay
->ist_ltreep
,
451 &splay
->ist_rtree
, splay
->ist_rtreep
);
452 ipc_splay_prim_lookup(name
, root
, &root
,
453 &splay
->ist_ltree
, &splay
->ist_ltreep
,
454 &splay
->ist_rtree
, &splay
->ist_rtreep
);
457 assert(root
->ite_name
== name
);
458 assert(root
== entry
);
460 *splay
->ist_ltreep
= root
->ite_lchild
;
461 *splay
->ist_rtreep
= root
->ite_rchild
;
464 root
= splay
->ist_ltree
;
465 saved
= splay
->ist_rtree
;
467 if (root
== ITE_NULL
)
469 else if (saved
!= ITE_NULL
) {
471 * Find the largest node in the left subtree, and splay it
472 * to the root. Then add the saved right subtree.
475 ipc_splay_prim_lookup(MACH_PORT_LARGEST
, root
, &root
,
476 &splay
->ist_ltree
, &splay
->ist_ltreep
,
477 &splay
->ist_rtree
, &splay
->ist_rtreep
);
478 ipc_splay_prim_assemble(root
,
479 &splay
->ist_ltree
, splay
->ist_ltreep
,
480 &splay
->ist_rtree
, splay
->ist_rtreep
);
482 assert(root
->ite_rchild
== ITE_NULL
);
483 root
->ite_rchild
= saved
;
486 splay
->ist_root
= root
;
487 if (root
!= ITE_NULL
) {
488 splay
->ist_name
= root
->ite_name
;
489 splay
->ist_ltreep
= &splay
->ist_ltree
;
490 splay
->ist_rtreep
= &splay
->ist_rtree
;
497 * Routine: ipc_splay_tree_split
499 * Split a splay tree. Puts all entries smaller than "name"
500 * into a new tree, "small".
502 * Doesn't do locking on "small", because nobody else
503 * should be fiddling with the uninitialized tree.
507 ipc_splay_tree_split(
508 ipc_splay_tree_t splay
,
509 mach_port_name_t name
,
510 ipc_splay_tree_t small
)
512 ipc_tree_entry_t root
;
514 ipc_splay_tree_init(small
);
518 root
= splay
->ist_root
;
519 if (root
!= ITE_NULL
) {
520 /* lookup name, to get it (or last traversed) to the top */
522 if (splay
->ist_name
!= name
) {
523 ipc_splay_prim_assemble(root
,
524 &splay
->ist_ltree
, splay
->ist_ltreep
,
525 &splay
->ist_rtree
, splay
->ist_rtreep
);
526 ipc_splay_prim_lookup(name
, root
, &root
,
527 &splay
->ist_ltree
, &splay
->ist_ltreep
,
528 &splay
->ist_rtree
, &splay
->ist_rtreep
);
531 if (root
->ite_name
< name
) {
532 /* root goes into small */
534 *splay
->ist_ltreep
= root
->ite_lchild
;
535 *splay
->ist_rtreep
= ITE_NULL
;
536 root
->ite_lchild
= splay
->ist_ltree
;
537 assert(root
->ite_rchild
== ITE_NULL
);
539 small
->ist_root
= root
;
540 small
->ist_name
= root
->ite_name
;
541 small
->ist_ltreep
= &small
->ist_ltree
;
542 small
->ist_rtreep
= &small
->ist_rtree
;
544 /* rtree goes into splay */
546 root
= splay
->ist_rtree
;
547 splay
->ist_root
= root
;
548 if (root
!= ITE_NULL
) {
549 splay
->ist_name
= root
->ite_name
;
550 splay
->ist_ltreep
= &splay
->ist_ltree
;
551 splay
->ist_rtreep
= &splay
->ist_rtree
;
554 /* root stays in splay */
556 *splay
->ist_ltreep
= root
->ite_lchild
;
557 root
->ite_lchild
= ITE_NULL
;
559 splay
->ist_root
= root
;
560 splay
->ist_name
= name
;
561 splay
->ist_ltreep
= &splay
->ist_ltree
;
563 /* ltree goes into small */
565 root
= splay
->ist_ltree
;
566 small
->ist_root
= root
;
567 if (root
!= ITE_NULL
) {
568 small
->ist_name
= root
->ite_name
;
569 small
->ist_ltreep
= &small
->ist_ltree
;
570 small
->ist_rtreep
= &small
->ist_rtree
;
579 * Routine: ipc_splay_tree_join
581 * Joins two splay trees. Merges the entries in "small",
582 * which must all be smaller than the entries in "splay",
588 ipc_splay_tree_t splay
,
589 ipc_splay_tree_t small
)
591 ipc_tree_entry_t sroot
;
593 /* pull entries out of small */
597 sroot
= small
->ist_root
;
598 if (sroot
!= ITE_NULL
) {
599 ipc_splay_prim_assemble(sroot
,
600 &small
->ist_ltree
, small
->ist_ltreep
,
601 &small
->ist_rtree
, small
->ist_rtreep
);
602 small
->ist_root
= ITE_NULL
;
607 /* put entries, if any, into splay */
609 if (sroot
!= ITE_NULL
) {
610 ipc_tree_entry_t root
;
614 root
= splay
->ist_root
;
615 if (root
== ITE_NULL
) {
618 /* get smallest entry in splay tree to top */
620 if (splay
->ist_name
!= MACH_PORT_SMALLEST
) {
621 ipc_splay_prim_assemble(root
,
622 &splay
->ist_ltree
, splay
->ist_ltreep
,
623 &splay
->ist_rtree
, splay
->ist_rtreep
);
624 ipc_splay_prim_lookup(MACH_PORT_SMALLEST
,
626 &splay
->ist_ltree
, &splay
->ist_ltreep
,
627 &splay
->ist_rtree
, &splay
->ist_rtreep
);
630 ipc_splay_prim_assemble(root
,
631 &splay
->ist_ltree
, splay
->ist_ltreep
,
632 &splay
->ist_rtree
, splay
->ist_rtreep
);
634 assert(root
->ite_lchild
== ITE_NULL
);
635 assert(sroot
->ite_name
< root
->ite_name
);
636 root
->ite_lchild
= sroot
;
639 splay
->ist_root
= root
;
640 splay
->ist_name
= root
->ite_name
;
641 splay
->ist_ltreep
= &splay
->ist_ltree
;
642 splay
->ist_rtreep
= &splay
->ist_rtree
;
649 * Routine: ipc_splay_tree_bounds
651 * Given a name, returns the largest value present
652 * in the tree that is smaller than or equal to the name,
653 * or ~0 if no such value exists. Similarly, returns
654 * the smallest value present that is greater than or
655 * equal to the name, or 0 if no such value exists.
658 * lower = upper, then lower = name = upper
659 * and name is present in the tree
660 * lower = ~0 and upper = 0,
661 * then the tree is empty
662 * lower = ~0 and upper > 0, then name < upper
663 * and upper is smallest value in tree
664 * lower < ~0 and upper = 0, then lower < name
665 * and lower is largest value in tree
666 * lower < ~0 and upper > 0, then lower < name < upper
667 * and they are tight bounds on name
669 * (Note MACH_PORT_SMALLEST = 0 and MACH_PORT_LARGEST = ~0.)
673 ipc_splay_tree_bounds(
674 ipc_splay_tree_t splay
,
675 mach_port_name_t name
,
676 mach_port_name_t
*lowerp
,
677 mach_port_name_t
*upperp
)
679 ipc_tree_entry_t root
;
683 root
= splay
->ist_root
;
684 if (root
== ITE_NULL
) {
685 *lowerp
= MACH_PORT_LARGEST
;
686 *upperp
= MACH_PORT_SMALLEST
;
688 mach_port_name_t rname
;
690 if (splay
->ist_name
!= name
) {
691 ipc_splay_prim_assemble(root
,
692 &splay
->ist_ltree
, splay
->ist_ltreep
,
693 &splay
->ist_rtree
, splay
->ist_rtreep
);
694 ipc_splay_prim_lookup(name
, root
, &root
,
695 &splay
->ist_ltree
, &splay
->ist_ltreep
,
696 &splay
->ist_rtree
, &splay
->ist_rtreep
);
697 splay
->ist_name
= name
;
698 splay
->ist_root
= root
;
701 rname
= root
->ite_name
;
704 * OK, it's a hack. We convert the ltreep and rtreep
705 * pointers back into real entry pointers,
706 * so we can pick the names out of the entries.
711 else if (splay
->ist_ltreep
== &splay
->ist_ltree
)
712 *lowerp
= MACH_PORT_LARGEST
;
714 ipc_tree_entry_t entry
;
716 entry
= (ipc_tree_entry_t
)
717 ((char *)splay
->ist_ltreep
-
718 ((char *)&root
->ite_rchild
-
720 *lowerp
= entry
->ite_name
;
725 else if (splay
->ist_rtreep
== &splay
->ist_rtree
)
726 *upperp
= MACH_PORT_SMALLEST
;
728 ipc_tree_entry_t entry
;
730 entry
= (ipc_tree_entry_t
)
731 ((char *)splay
->ist_rtreep
-
732 ((char *)&root
->ite_lchild
-
734 *upperp
= entry
->ite_name
;
742 * Routine: ipc_splay_traverse_start
743 * Routine: ipc_splay_traverse_next
744 * Routine: ipc_splay_traverse_finish
746 * Perform a symmetric order traversal of a splay tree.
748 * for (entry = ipc_splay_traverse_start(splay);
750 * entry = ipc_splay_traverse_next(splay, delete)) {
751 * do something with entry
753 * ipc_splay_traverse_finish(splay);
755 * If "delete" is TRUE, then the current entry
756 * is removed from the tree and deallocated.
758 * During the traversal, the splay tree is locked.
762 ipc_splay_traverse_start(
763 ipc_splay_tree_t splay
)
765 ipc_tree_entry_t current
, parent
;
769 current
= splay
->ist_root
;
770 if (current
!= ITE_NULL
) {
771 ipc_splay_prim_assemble(current
,
772 &splay
->ist_ltree
, splay
->ist_ltreep
,
773 &splay
->ist_rtree
, splay
->ist_rtreep
);
777 while (current
->ite_lchild
!= ITE_NULL
) {
778 ipc_tree_entry_t next
;
780 next
= current
->ite_lchild
;
781 current
->ite_lchild
= parent
;
786 splay
->ist_ltree
= current
;
787 splay
->ist_rtree
= parent
;
794 ipc_splay_traverse_next(
795 ipc_splay_tree_t splay
,
798 ipc_tree_entry_t current
, parent
;
800 /* pick up where traverse_entry left off */
802 current
= splay
->ist_ltree
;
803 parent
= splay
->ist_rtree
;
804 assert(current
!= ITE_NULL
);
809 /* we must delete current and patch the tree */
811 if (current
->ite_lchild
== ITE_NULL
) {
812 if (current
->ite_rchild
== ITE_NULL
) {
813 /* like traverse_back, but with deletion */
815 if (parent
== ITE_NULL
) {
818 splay
->ist_root
= ITE_NULL
;
822 if (current
->ite_name
< parent
->ite_name
) {
826 parent
= current
->ite_lchild
;
827 current
->ite_lchild
= ITE_NULL
;
833 parent
= current
->ite_rchild
;
834 current
->ite_rchild
= ITE_NULL
;
838 ipc_tree_entry_t prev
;
841 current
= current
->ite_rchild
;
846 if (current
->ite_rchild
== ITE_NULL
) {
847 ipc_tree_entry_t prev
;
850 current
= current
->ite_lchild
;
854 ipc_tree_entry_t prev
;
855 ipc_tree_entry_t ltree
, rtree
;
856 ipc_tree_entry_t
*ltreep
, *rtreep
;
858 /* replace current with largest of left children */
861 ipc_splay_prim_lookup(MACH_PORT_LARGEST
,
862 current
->ite_lchild
, ¤t
,
863 <ree
, <reep
, &rtree
, &rtreep
);
864 ipc_splay_prim_assemble(current
,
865 <ree
, ltreep
, &rtree
, rtreep
);
867 assert(current
->ite_rchild
== ITE_NULL
);
868 current
->ite_rchild
= prev
->ite_rchild
;
876 * A state machine: for each entry, we
877 * 1) traverse left subtree
878 * 2) traverse the entry
879 * 3) traverse right subtree
880 * 4) traverse back to parent
884 if (current
->ite_lchild
!= ITE_NULL
) {
885 ipc_tree_entry_t next
;
887 next
= current
->ite_lchild
;
888 current
->ite_lchild
= parent
;
895 splay
->ist_ltree
= current
;
896 splay
->ist_rtree
= parent
;
900 if (current
->ite_rchild
!= ITE_NULL
) {
901 ipc_tree_entry_t next
;
903 next
= current
->ite_rchild
;
904 current
->ite_rchild
= parent
;
911 if (parent
== ITE_NULL
) {
912 splay
->ist_root
= current
;
916 if (current
->ite_name
< parent
->ite_name
) {
917 ipc_tree_entry_t prev
;
921 parent
= current
->ite_lchild
;
922 current
->ite_lchild
= prev
;
925 ipc_tree_entry_t prev
;
929 parent
= current
->ite_rchild
;
930 current
->ite_rchild
= prev
;
936 ipc_splay_traverse_finish(
937 ipc_splay_tree_t splay
)
939 ipc_tree_entry_t root
;
941 root
= splay
->ist_root
;
942 if (root
!= ITE_NULL
) {
943 splay
->ist_name
= root
->ite_name
;
944 splay
->ist_ltreep
= &splay
->ist_ltree
;
945 splay
->ist_rtreep
= &splay
->ist_rtree
;