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_splay.c
65 * Primitive splay tree operations.
68 #include <mach/port.h>
69 #include <kern/assert.h>
70 #include <kern/macro_help.h>
71 #include <ipc/ipc_entry.h>
72 #include <ipc/ipc_splay.h>
75 * Splay trees are self-adjusting binary search trees.
76 * They have the following attractive properties:
77 * 1) Space efficient; only two pointers per entry.
78 * 2) Robust performance; amortized O(log n) per operation.
79 * 3) Recursion not needed.
80 * This makes them a good fall-back data structure for those
81 * entries that don't fit into the lookup table.
83 * The paper by Sleator and Tarjan, JACM v. 32, no. 3, pp. 652-686,
84 * describes the splaying operation. ipc_splay_prim_lookup
85 * and ipc_splay_prim_assemble implement the top-down splay
86 * described on p. 669.
88 * The tree is stored in an unassembled form. If ist_root is null,
89 * then the tree has no entries. Otherwise, ist_name records
90 * the value used for the last lookup. ist_root points to the
91 * middle tree obtained from the top-down splay. ist_ltree and
92 * ist_rtree point to left and right subtrees, whose entries
93 * are all smaller (larger) than those in the middle tree.
94 * ist_ltreep and ist_rtreep are pointers to fields in the
95 * left and right subtrees. ist_ltreep points to the rchild field
96 * of the largest entry in ltree, and ist_rtreep points to the
97 * lchild field of the smallest entry in rtree. The pointed-to
98 * fields aren't initialized. If the left (right) subtree is null,
99 * then ist_ltreep (ist_rtreep) points to the ist_ltree (ist_rtree)
100 * field in the splay structure itself.
102 * The primary advantage of the unassembled form is that repeated
103 * unsuccessful lookups are efficient. In particular, an unsuccessful
104 * lookup followed by an insert only requires one splaying operation.
106 * The traversal algorithm works via pointer inversion.
107 * When descending down the tree, child pointers are reversed
108 * to point back to the parent entry. When ascending,
109 * the pointers are restored to their original value.
111 * The biggest potential problem with the splay tree implementation
112 * is that the operations, even lookup, require an exclusive lock.
113 * If IPC spaces are protected with exclusive locks, then
114 * the splay tree doesn't require its own lock, and ist_lock/ist_unlock
115 * needn't do anything. If IPC spaces are protected with read/write
116 * locks then ist_lock/ist_unlock should provide exclusive access.
118 * If it becomes important to let lookups run in parallel,
119 * or if the restructuring makes lookups too expensive, then
120 * there is hope. Use a read/write lock on the splay tree.
121 * Keep track of the number of entries in the tree. When doing
122 * a lookup, first try a non-restructuring lookup with a read lock held,
123 * with a bound (based on log of size of the tree) on the number of
124 * entries to traverse. If the lookup runs up against the bound,
125 * then take a write lock and do a reorganizing lookup.
126 * This way, if lookups only access roughly balanced parts
127 * of the tree, then lookups run in parallel and do no restructuring.
129 * The traversal algorithm currently requires an exclusive lock.
130 * If that is a problem, the tree could be changed from an lchild/rchild
131 * representation to a leftmost child/right sibling representation.
132 * In conjunction with non-restructing lookups, this would let
133 * lookups and traversals all run in parallel. But this representation
134 * is more complicated and would slow down the operations.
138 * Boundary values to hand to ipc_splay_prim_lookup:
141 #define MACH_PORT_SMALLEST ((mach_port_name_t) 0)
142 #define MACH_PORT_LARGEST ((mach_port_name_t) ~0)
145 * Routine: ipc_splay_prim_lookup
147 * Searches for the node labeled name in the splay tree.
148 * Returns three nodes (treep, ltreep, rtreep) and
149 * two pointers to nodes (ltreepp, rtreepp).
151 * ipc_splay_prim_lookup splits the supplied tree into
152 * three subtrees, left, middle, and right, returned
153 * in ltreep, treep, and rtreep.
155 * If name is present in the tree, then it is at
156 * the root of the middle tree. Otherwise, the root
157 * of the middle tree is the last node traversed.
159 * ipc_splay_prim_lookup returns a pointer into
160 * the left subtree, to the rchild field of its
161 * largest node, in ltreepp. It returns a pointer
162 * into the right subtree, to the lchild field of its
163 * smallest node, in rtreepp.
167 ipc_splay_prim_lookup(
168 mach_port_name_t name
,
169 ipc_tree_entry_t tree
,
170 ipc_tree_entry_t
*treep
,
171 ipc_tree_entry_t
*ltreep
,
172 ipc_tree_entry_t
**ltreepp
,
173 ipc_tree_entry_t
*rtreep
,
174 ipc_tree_entry_t
**rtreepp
)
176 mach_port_name_t tname
; /* temp name */
177 ipc_tree_entry_t lchild
, rchild
; /* temp child pointers */
179 assert(tree
!= ITE_NULL
);
184 ltreep = &tree->ite_rchild; \
191 rtreep = &tree->ite_lchild; \
195 #define rotate_left \
197 ipc_tree_entry_t temp = tree; \
199 tree = temp->ite_rchild; \
200 temp->ite_rchild = tree->ite_lchild; \
201 tree->ite_lchild = temp; \
204 #define rotate_right \
206 ipc_tree_entry_t temp = tree; \
208 tree = temp->ite_lchild; \
209 temp->ite_lchild = tree->ite_rchild; \
210 tree->ite_rchild = temp; \
213 while (name
!= (tname
= tree
->ite_name
)) {
215 /* descend to left */
217 lchild
= tree
->ite_lchild
;
218 if (lchild
== ITE_NULL
)
220 tname
= lchild
->ite_name
;
222 if ((name
< tname
) &&
223 (lchild
->ite_lchild
!= ITE_NULL
))
226 if ((name
> tname
) &&
227 (lchild
->ite_rchild
!= ITE_NULL
))
230 /* descend to right */
232 rchild
= tree
->ite_rchild
;
233 if (rchild
== ITE_NULL
)
235 tname
= rchild
->ite_name
;
237 if ((name
> tname
) &&
238 (rchild
->ite_rchild
!= ITE_NULL
))
241 if ((name
< tname
) &&
242 (rchild
->ite_lchild
!= ITE_NULL
))
246 assert(tree
!= ITE_NULL
);
260 * Routine: ipc_splay_prim_assemble
262 * Assembles the results of ipc_splay_prim_lookup
263 * into a splay tree with the found node at the root.
265 * ltree and rtree are by-reference so storing
266 * through ltreep and rtreep can change them.
270 ipc_splay_prim_assemble(
271 ipc_tree_entry_t tree
,
272 ipc_tree_entry_t
*ltree
,
273 ipc_tree_entry_t
*ltreep
,
274 ipc_tree_entry_t
*rtree
,
275 ipc_tree_entry_t
*rtreep
)
277 assert(tree
!= ITE_NULL
);
279 *ltreep
= tree
->ite_lchild
;
280 *rtreep
= tree
->ite_rchild
;
282 tree
->ite_lchild
= *ltree
;
283 tree
->ite_rchild
= *rtree
;
287 * Routine: ipc_splay_tree_init
289 * Initialize a raw splay tree for use.
294 ipc_splay_tree_t splay
)
296 splay
->ist_root
= ITE_NULL
;
300 * Routine: ipc_splay_tree_pick
302 * Picks and returns a random entry in a splay tree.
303 * Returns FALSE if the splay tree is empty.
308 ipc_splay_tree_t splay
,
309 mach_port_name_t
*namep
,
310 ipc_tree_entry_t
*entryp
)
312 ipc_tree_entry_t root
;
316 root
= splay
->ist_root
;
317 if (root
!= ITE_NULL
) {
318 *namep
= root
->ite_name
;
324 return root
!= ITE_NULL
;
328 * Routine: ipc_splay_tree_lookup
330 * Finds an entry in a splay tree.
331 * Returns ITE_NULL if not found.
335 ipc_splay_tree_lookup(
336 ipc_splay_tree_t splay
,
337 mach_port_name_t name
)
339 ipc_tree_entry_t root
;
343 root
= splay
->ist_root
;
344 if (root
!= ITE_NULL
) {
345 if (splay
->ist_name
!= name
) {
346 ipc_splay_prim_assemble(root
,
347 &splay
->ist_ltree
, splay
->ist_ltreep
,
348 &splay
->ist_rtree
, splay
->ist_rtreep
);
349 ipc_splay_prim_lookup(name
, root
, &root
,
350 &splay
->ist_ltree
, &splay
->ist_ltreep
,
351 &splay
->ist_rtree
, &splay
->ist_rtreep
);
352 splay
->ist_name
= name
;
353 splay
->ist_root
= root
;
356 if (name
!= root
->ite_name
)
366 * Routine: ipc_splay_tree_insert
368 * Inserts a new entry into a splay tree.
369 * The caller supplies a new entry.
370 * The name can't already be present in the tree.
374 ipc_splay_tree_insert(
375 ipc_splay_tree_t splay
,
376 mach_port_name_t name
,
377 ipc_tree_entry_t entry
)
379 ipc_tree_entry_t root
;
381 assert(entry
!= ITE_NULL
);
385 root
= splay
->ist_root
;
386 if (root
== ITE_NULL
) {
387 entry
->ite_lchild
= ITE_NULL
;
388 entry
->ite_rchild
= ITE_NULL
;
390 if (splay
->ist_name
!= name
) {
391 ipc_splay_prim_assemble(root
,
392 &splay
->ist_ltree
, splay
->ist_ltreep
,
393 &splay
->ist_rtree
, splay
->ist_rtreep
);
394 ipc_splay_prim_lookup(name
, root
, &root
,
395 &splay
->ist_ltree
, &splay
->ist_ltreep
,
396 &splay
->ist_rtree
, &splay
->ist_rtreep
);
399 assert(root
->ite_name
!= name
);
401 if (name
< root
->ite_name
) {
402 assert(root
->ite_lchild
== ITE_NULL
);
404 *splay
->ist_ltreep
= ITE_NULL
;
405 *splay
->ist_rtreep
= root
;
407 assert(root
->ite_rchild
== ITE_NULL
);
409 *splay
->ist_ltreep
= root
;
410 *splay
->ist_rtreep
= ITE_NULL
;
413 entry
->ite_lchild
= splay
->ist_ltree
;
414 entry
->ite_rchild
= splay
->ist_rtree
;
417 entry
->ite_name
= name
;
418 splay
->ist_root
= entry
;
419 splay
->ist_name
= name
;
420 splay
->ist_ltreep
= &splay
->ist_ltree
;
421 splay
->ist_rtreep
= &splay
->ist_rtree
;
427 * Routine: ipc_splay_tree_delete
429 * Deletes an entry from a splay tree.
430 * The name must be present in the tree.
433 * The "entry" argument isn't currently used.
434 * Other implementations might want it, though.
438 ipc_splay_tree_delete(
439 ipc_splay_tree_t splay
,
440 mach_port_name_t name
,
441 __assert_only ipc_tree_entry_t entry
)
443 ipc_tree_entry_t root
, saved
;
447 root
= splay
->ist_root
;
448 assert(root
!= ITE_NULL
);
450 if (splay
->ist_name
!= name
) {
451 ipc_splay_prim_assemble(root
,
452 &splay
->ist_ltree
, splay
->ist_ltreep
,
453 &splay
->ist_rtree
, splay
->ist_rtreep
);
454 ipc_splay_prim_lookup(name
, root
, &root
,
455 &splay
->ist_ltree
, &splay
->ist_ltreep
,
456 &splay
->ist_rtree
, &splay
->ist_rtreep
);
459 assert(root
->ite_name
== name
);
460 assert(root
== entry
);
462 *splay
->ist_ltreep
= root
->ite_lchild
;
463 *splay
->ist_rtreep
= root
->ite_rchild
;
466 root
= splay
->ist_ltree
;
467 saved
= splay
->ist_rtree
;
469 if (root
== ITE_NULL
)
471 else if (saved
!= ITE_NULL
) {
473 * Find the largest node in the left subtree, and splay it
474 * to the root. Then add the saved right subtree.
477 ipc_splay_prim_lookup(MACH_PORT_LARGEST
, root
, &root
,
478 &splay
->ist_ltree
, &splay
->ist_ltreep
,
479 &splay
->ist_rtree
, &splay
->ist_rtreep
);
480 ipc_splay_prim_assemble(root
,
481 &splay
->ist_ltree
, splay
->ist_ltreep
,
482 &splay
->ist_rtree
, splay
->ist_rtreep
);
484 assert(root
->ite_rchild
== ITE_NULL
);
485 root
->ite_rchild
= saved
;
488 splay
->ist_root
= root
;
489 if (root
!= ITE_NULL
) {
490 splay
->ist_name
= root
->ite_name
;
491 splay
->ist_ltreep
= &splay
->ist_ltree
;
492 splay
->ist_rtreep
= &splay
->ist_rtree
;
499 * Routine: ipc_splay_tree_split
501 * Split a splay tree. Puts all entries smaller than "name"
502 * into a new tree, "small".
504 * Doesn't do locking on "small", because nobody else
505 * should be fiddling with the uninitialized tree.
509 ipc_splay_tree_split(
510 ipc_splay_tree_t splay
,
511 mach_port_name_t name
,
512 ipc_splay_tree_t small
)
514 ipc_tree_entry_t root
;
516 ipc_splay_tree_init(small
);
520 root
= splay
->ist_root
;
521 if (root
!= ITE_NULL
) {
522 /* lookup name, to get it (or last traversed) to the top */
524 if (splay
->ist_name
!= name
) {
525 ipc_splay_prim_assemble(root
,
526 &splay
->ist_ltree
, splay
->ist_ltreep
,
527 &splay
->ist_rtree
, splay
->ist_rtreep
);
528 ipc_splay_prim_lookup(name
, root
, &root
,
529 &splay
->ist_ltree
, &splay
->ist_ltreep
,
530 &splay
->ist_rtree
, &splay
->ist_rtreep
);
533 if (root
->ite_name
< name
) {
534 /* root goes into small */
536 *splay
->ist_ltreep
= root
->ite_lchild
;
537 *splay
->ist_rtreep
= ITE_NULL
;
538 root
->ite_lchild
= splay
->ist_ltree
;
539 assert(root
->ite_rchild
== ITE_NULL
);
541 small
->ist_root
= root
;
542 small
->ist_name
= root
->ite_name
;
543 small
->ist_ltreep
= &small
->ist_ltree
;
544 small
->ist_rtreep
= &small
->ist_rtree
;
546 /* rtree goes into splay */
548 root
= splay
->ist_rtree
;
549 splay
->ist_root
= root
;
550 if (root
!= ITE_NULL
) {
551 splay
->ist_name
= root
->ite_name
;
552 splay
->ist_ltreep
= &splay
->ist_ltree
;
553 splay
->ist_rtreep
= &splay
->ist_rtree
;
556 /* root stays in splay */
558 *splay
->ist_ltreep
= root
->ite_lchild
;
559 root
->ite_lchild
= ITE_NULL
;
561 splay
->ist_root
= root
;
562 splay
->ist_name
= name
;
563 splay
->ist_ltreep
= &splay
->ist_ltree
;
565 /* ltree goes into small */
567 root
= splay
->ist_ltree
;
568 small
->ist_root
= root
;
569 if (root
!= ITE_NULL
) {
570 small
->ist_name
= root
->ite_name
;
571 small
->ist_ltreep
= &small
->ist_ltree
;
572 small
->ist_rtreep
= &small
->ist_rtree
;
581 * Routine: ipc_splay_tree_join
583 * Joins two splay trees. Merges the entries in "small",
584 * which must all be smaller than the entries in "splay",
590 ipc_splay_tree_t splay
,
591 ipc_splay_tree_t small
)
593 ipc_tree_entry_t sroot
;
595 /* pull entries out of small */
599 sroot
= small
->ist_root
;
600 if (sroot
!= ITE_NULL
) {
601 ipc_splay_prim_assemble(sroot
,
602 &small
->ist_ltree
, small
->ist_ltreep
,
603 &small
->ist_rtree
, small
->ist_rtreep
);
604 small
->ist_root
= ITE_NULL
;
609 /* put entries, if any, into splay */
611 if (sroot
!= ITE_NULL
) {
612 ipc_tree_entry_t root
;
616 root
= splay
->ist_root
;
617 if (root
== ITE_NULL
) {
620 /* get smallest entry in splay tree to top */
622 if (splay
->ist_name
!= MACH_PORT_SMALLEST
) {
623 ipc_splay_prim_assemble(root
,
624 &splay
->ist_ltree
, splay
->ist_ltreep
,
625 &splay
->ist_rtree
, splay
->ist_rtreep
);
626 ipc_splay_prim_lookup(MACH_PORT_SMALLEST
,
628 &splay
->ist_ltree
, &splay
->ist_ltreep
,
629 &splay
->ist_rtree
, &splay
->ist_rtreep
);
632 ipc_splay_prim_assemble(root
,
633 &splay
->ist_ltree
, splay
->ist_ltreep
,
634 &splay
->ist_rtree
, splay
->ist_rtreep
);
636 assert(root
->ite_lchild
== ITE_NULL
);
637 assert(sroot
->ite_name
< root
->ite_name
);
638 root
->ite_lchild
= sroot
;
641 splay
->ist_root
= root
;
642 splay
->ist_name
= root
->ite_name
;
643 splay
->ist_ltreep
= &splay
->ist_ltree
;
644 splay
->ist_rtreep
= &splay
->ist_rtree
;
651 * Routine: ipc_splay_tree_bounds
653 * Given a name, returns the largest value present
654 * in the tree that is smaller than or equal to the name,
655 * or ~0 if no such value exists. Similarly, returns
656 * the smallest value present that is greater than or
657 * equal to the name, or 0 if no such value exists.
660 * lower = upper, then lower = name = upper
661 * and name is present in the tree
662 * lower = ~0 and upper = 0,
663 * then the tree is empty
664 * lower = ~0 and upper > 0, then name < upper
665 * and upper is smallest value in tree
666 * lower < ~0 and upper = 0, then lower < name
667 * and lower is largest value in tree
668 * lower < ~0 and upper > 0, then lower < name < upper
669 * and they are tight bounds on name
671 * (Note MACH_PORT_SMALLEST = 0 and MACH_PORT_LARGEST = ~0.)
675 ipc_splay_tree_bounds(
676 ipc_splay_tree_t splay
,
677 mach_port_name_t name
,
678 mach_port_name_t
*lowerp
,
679 mach_port_name_t
*upperp
)
681 ipc_tree_entry_t root
;
685 root
= splay
->ist_root
;
686 if (root
== ITE_NULL
) {
687 *lowerp
= MACH_PORT_LARGEST
;
688 *upperp
= MACH_PORT_SMALLEST
;
690 mach_port_name_t rname
;
692 if (splay
->ist_name
!= name
) {
693 ipc_splay_prim_assemble(root
,
694 &splay
->ist_ltree
, splay
->ist_ltreep
,
695 &splay
->ist_rtree
, splay
->ist_rtreep
);
696 ipc_splay_prim_lookup(name
, root
, &root
,
697 &splay
->ist_ltree
, &splay
->ist_ltreep
,
698 &splay
->ist_rtree
, &splay
->ist_rtreep
);
699 splay
->ist_name
= name
;
700 splay
->ist_root
= root
;
703 rname
= root
->ite_name
;
706 * OK, it's a hack. We convert the ltreep and rtreep
707 * pointers back into real entry pointers,
708 * so we can pick the names out of the entries.
713 else if (splay
->ist_ltreep
== &splay
->ist_ltree
)
714 *lowerp
= MACH_PORT_LARGEST
;
716 ipc_tree_entry_t entry
;
718 entry
= (ipc_tree_entry_t
)
719 ((char *)splay
->ist_ltreep
-
720 ((char *)&root
->ite_rchild
-
722 *lowerp
= entry
->ite_name
;
727 else if (splay
->ist_rtreep
== &splay
->ist_rtree
)
728 *upperp
= MACH_PORT_SMALLEST
;
730 ipc_tree_entry_t entry
;
732 entry
= (ipc_tree_entry_t
)
733 ((char *)splay
->ist_rtreep
-
734 ((char *)&root
->ite_lchild
-
736 *upperp
= entry
->ite_name
;
744 * Routine: ipc_splay_traverse_start
745 * Routine: ipc_splay_traverse_next
746 * Routine: ipc_splay_traverse_finish
748 * Perform a symmetric order traversal of a splay tree.
750 * for (entry = ipc_splay_traverse_start(splay);
752 * entry = ipc_splay_traverse_next(splay, delete)) {
753 * do something with entry
755 * ipc_splay_traverse_finish(splay);
757 * If "delete" is TRUE, then the current entry
758 * is removed from the tree and deallocated.
760 * During the traversal, the splay tree is locked.
764 ipc_splay_traverse_start(
765 ipc_splay_tree_t splay
)
767 ipc_tree_entry_t current
, parent
;
771 current
= splay
->ist_root
;
772 if (current
!= ITE_NULL
) {
773 ipc_splay_prim_assemble(current
,
774 &splay
->ist_ltree
, splay
->ist_ltreep
,
775 &splay
->ist_rtree
, splay
->ist_rtreep
);
779 while (current
->ite_lchild
!= ITE_NULL
) {
780 ipc_tree_entry_t next
;
782 next
= current
->ite_lchild
;
783 current
->ite_lchild
= parent
;
788 splay
->ist_ltree
= current
;
789 splay
->ist_rtree
= parent
;
796 ipc_splay_traverse_next(
797 ipc_splay_tree_t splay
,
800 ipc_tree_entry_t current
, parent
;
802 /* pick up where traverse_entry left off */
804 current
= splay
->ist_ltree
;
805 parent
= splay
->ist_rtree
;
806 assert(current
!= ITE_NULL
);
811 /* we must delete current and patch the tree */
813 if (current
->ite_lchild
== ITE_NULL
) {
814 if (current
->ite_rchild
== ITE_NULL
) {
815 /* like traverse_back, but with deletion */
817 if (parent
== ITE_NULL
) {
820 splay
->ist_root
= ITE_NULL
;
824 if (current
->ite_name
< parent
->ite_name
) {
828 parent
= current
->ite_lchild
;
829 current
->ite_lchild
= ITE_NULL
;
835 parent
= current
->ite_rchild
;
836 current
->ite_rchild
= ITE_NULL
;
840 ipc_tree_entry_t prev
;
843 current
= current
->ite_rchild
;
848 if (current
->ite_rchild
== ITE_NULL
) {
849 ipc_tree_entry_t prev
;
852 current
= current
->ite_lchild
;
856 ipc_tree_entry_t prev
;
857 ipc_tree_entry_t ltree
, rtree
;
858 ipc_tree_entry_t
*ltreep
, *rtreep
;
860 /* replace current with largest of left children */
863 ipc_splay_prim_lookup(MACH_PORT_LARGEST
,
864 current
->ite_lchild
, ¤t
,
865 <ree
, <reep
, &rtree
, &rtreep
);
866 ipc_splay_prim_assemble(current
,
867 <ree
, ltreep
, &rtree
, rtreep
);
869 assert(current
->ite_rchild
== ITE_NULL
);
870 current
->ite_rchild
= prev
->ite_rchild
;
878 * A state machine: for each entry, we
879 * 1) traverse left subtree
880 * 2) traverse the entry
881 * 3) traverse right subtree
882 * 4) traverse back to parent
886 if (current
->ite_lchild
!= ITE_NULL
) {
887 ipc_tree_entry_t next
;
889 next
= current
->ite_lchild
;
890 current
->ite_lchild
= parent
;
897 splay
->ist_ltree
= current
;
898 splay
->ist_rtree
= parent
;
902 if (current
->ite_rchild
!= ITE_NULL
) {
903 ipc_tree_entry_t next
;
905 next
= current
->ite_rchild
;
906 current
->ite_rchild
= parent
;
913 if (parent
== ITE_NULL
) {
914 splay
->ist_root
= current
;
918 if (current
->ite_name
< parent
->ite_name
) {
919 ipc_tree_entry_t prev
;
923 parent
= current
->ite_lchild
;
924 current
->ite_lchild
= prev
;
927 ipc_tree_entry_t prev
;
931 parent
= current
->ite_rchild
;
932 current
->ite_rchild
= prev
;
938 ipc_splay_traverse_finish(
939 ipc_splay_tree_t splay
)
941 ipc_tree_entry_t root
;
943 root
= splay
->ist_root
;
944 if (root
!= ITE_NULL
) {
945 splay
->ist_name
= root
->ite_name
;
946 splay
->ist_ltreep
= &splay
->ist_ltree
;
947 splay
->ist_rtreep
= &splay
->ist_rtree
;