]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/ipc/ipc_splay.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
31 * Revision 1.1.1.1 1998/09/22 21:05:28 wsanchez
32 * Import of Mac OS X kernel (~semeria)
34 * Revision 1.1.1.1 1998/03/07 02:26:16 wsanchez
35 * Import of OSF Mach kernel (~mburg)
37 * Revision 1.1.6.1 1994/09/23 02:11:47 ezf
38 * change marker to not FREE
39 * [1994/09/22 21:30:41 ezf]
41 * Revision 1.1.2.3 1993/07/22 16:17:25 rod
42 * Add ANSI prototypes. CR #9523.
43 * [1993/07/22 13:33:20 rod]
45 * Revision 1.1.2.2 1993/06/02 23:33:40 jeffc
46 * Added to OSF/1 R1.3 from NMK15.0.
47 * [1993/06/02 21:11:07 jeffc]
49 * Revision 1.1 1992/09/30 02:08:11 robert
56 * Revision 2.5 91/10/09 16:10:41 af
57 * Revision 2.4.2.1 91/09/16 10:16:00 rpd
58 * Added MACH_PORT_SMALLEST, MACH_PORT_LARGEST definitions to reduce lint.
61 * Revision 2.4.2.1 91/09/16 10:16:00 rpd
62 * Added MACH_PORT_SMALLEST, MACH_PORT_LARGEST definitions to reduce lint.
65 * Revision 2.4 91/05/14 16:37:08 mrt
66 * Correcting copyright
68 * Revision 2.3 91/02/05 17:23:52 mrt
69 * Changed to new Mach copyright
70 * [91/02/01 15:51:43 mrt]
72 * Revision 2.2 90/06/02 14:51:49 rpd
73 * Created for new IPC.
74 * [90/03/26 21:03:46 rpd]
79 * Mach Operating System
80 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
81 * All Rights Reserved.
83 * Permission to use, copy, modify and distribute this software and its
84 * documentation is hereby granted, provided that both the copyright
85 * notice and this permission notice appear in all copies of the
86 * software, derivative works or modified versions, and any portions
87 * thereof, and that both notices appear in supporting documentation.
89 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
90 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
91 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
93 * Carnegie Mellon requests users of this software to return to
95 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
96 * School of Computer Science
97 * Carnegie Mellon University
98 * Pittsburgh PA 15213-3890
100 * any improvements or extensions that they make and grant Carnegie Mellon
101 * the rights to redistribute these changes.
106 * File: ipc/ipc_splay.c
107 * Author: Rich Draves
110 * Primitive splay tree operations.
113 #include <mach/port.h>
114 #include <kern/assert.h>
115 #include <kern/macro_help.h>
116 #include <ipc/ipc_entry.h>
117 #include <ipc/ipc_splay.h>
120 * Splay trees are self-adjusting binary search trees.
121 * They have the following attractive properties:
122 * 1) Space efficient; only two pointers per entry.
123 * 2) Robust performance; amortized O(log n) per operation.
124 * 3) Recursion not needed.
125 * This makes them a good fall-back data structure for those
126 * entries that don't fit into the lookup table.
128 * The paper by Sleator and Tarjan, JACM v. 32, no. 3, pp. 652-686,
129 * describes the splaying operation. ipc_splay_prim_lookup
130 * and ipc_splay_prim_assemble implement the top-down splay
131 * described on p. 669.
133 * The tree is stored in an unassembled form. If ist_root is null,
134 * then the tree has no entries. Otherwise, ist_name records
135 * the value used for the last lookup. ist_root points to the
136 * middle tree obtained from the top-down splay. ist_ltree and
137 * ist_rtree point to left and right subtrees, whose entries
138 * are all smaller (larger) than those in the middle tree.
139 * ist_ltreep and ist_rtreep are pointers to fields in the
140 * left and right subtrees. ist_ltreep points to the rchild field
141 * of the largest entry in ltree, and ist_rtreep points to the
142 * lchild field of the smallest entry in rtree. The pointed-to
143 * fields aren't initialized. If the left (right) subtree is null,
144 * then ist_ltreep (ist_rtreep) points to the ist_ltree (ist_rtree)
145 * field in the splay structure itself.
147 * The primary advantage of the unassembled form is that repeated
148 * unsuccessful lookups are efficient. In particular, an unsuccessful
149 * lookup followed by an insert only requires one splaying operation.
151 * The traversal algorithm works via pointer inversion.
152 * When descending down the tree, child pointers are reversed
153 * to point back to the parent entry. When ascending,
154 * the pointers are restored to their original value.
156 * The biggest potential problem with the splay tree implementation
157 * is that the operations, even lookup, require an exclusive lock.
158 * If IPC spaces are protected with exclusive locks, then
159 * the splay tree doesn't require its own lock, and ist_lock/ist_unlock
160 * needn't do anything. If IPC spaces are protected with read/write
161 * locks then ist_lock/ist_unlock should provide exclusive access.
163 * If it becomes important to let lookups run in parallel,
164 * or if the restructuring makes lookups too expensive, then
165 * there is hope. Use a read/write lock on the splay tree.
166 * Keep track of the number of entries in the tree. When doing
167 * a lookup, first try a non-restructuring lookup with a read lock held,
168 * with a bound (based on log of size of the tree) on the number of
169 * entries to traverse. If the lookup runs up against the bound,
170 * then take a write lock and do a reorganizing lookup.
171 * This way, if lookups only access roughly balanced parts
172 * of the tree, then lookups run in parallel and do no restructuring.
174 * The traversal algorithm currently requires an exclusive lock.
175 * If that is a problem, the tree could be changed from an lchild/rchild
176 * representation to a leftmost child/right sibling representation.
177 * In conjunction with non-restructing lookups, this would let
178 * lookups and traversals all run in parallel. But this representation
179 * is more complicated and would slow down the operations.
183 * Boundary values to hand to ipc_splay_prim_lookup:
186 #define MACH_PORT_SMALLEST ((mach_port_name_t) 0)
187 #define MACH_PORT_LARGEST ((mach_port_name_t) ~0)
190 * Routine: ipc_splay_prim_lookup
192 * Searches for the node labeled name in the splay tree.
193 * Returns three nodes (treep, ltreep, rtreep) and
194 * two pointers to nodes (ltreepp, rtreepp).
196 * ipc_splay_prim_lookup splits the supplied tree into
197 * three subtrees, left, middle, and right, returned
198 * in ltreep, treep, and rtreep.
200 * If name is present in the tree, then it is at
201 * the root of the middle tree. Otherwise, the root
202 * of the middle tree is the last node traversed.
204 * ipc_splay_prim_lookup returns a pointer into
205 * the left subtree, to the rchild field of its
206 * largest node, in ltreepp. It returns a pointer
207 * into the right subtree, to the lchild field of its
208 * smallest node, in rtreepp.
212 ipc_splay_prim_lookup(
213 mach_port_name_t name
,
214 ipc_tree_entry_t tree
,
215 ipc_tree_entry_t
*treep
,
216 ipc_tree_entry_t
*ltreep
,
217 ipc_tree_entry_t
**ltreepp
,
218 ipc_tree_entry_t
*rtreep
,
219 ipc_tree_entry_t
**rtreepp
)
221 mach_port_name_t tname
; /* temp name */
222 ipc_tree_entry_t lchild
, rchild
; /* temp child pointers */
224 assert(tree
!= ITE_NULL
);
229 ltreep = &tree->ite_rchild; \
236 rtreep = &tree->ite_lchild; \
240 #define rotate_left \
242 ipc_tree_entry_t temp = tree; \
244 tree = temp->ite_rchild; \
245 temp->ite_rchild = tree->ite_lchild; \
246 tree->ite_lchild = temp; \
249 #define rotate_right \
251 ipc_tree_entry_t temp = tree; \
253 tree = temp->ite_lchild; \
254 temp->ite_lchild = tree->ite_rchild; \
255 tree->ite_rchild = temp; \
258 while (name
!= (tname
= tree
->ite_name
)) {
260 /* descend to left */
262 lchild
= tree
->ite_lchild
;
263 if (lchild
== ITE_NULL
)
265 tname
= lchild
->ite_name
;
267 if ((name
< tname
) &&
268 (lchild
->ite_lchild
!= ITE_NULL
))
271 if ((name
> tname
) &&
272 (lchild
->ite_rchild
!= ITE_NULL
))
275 /* descend to right */
277 rchild
= tree
->ite_rchild
;
278 if (rchild
== ITE_NULL
)
280 tname
= rchild
->ite_name
;
282 if ((name
> tname
) &&
283 (rchild
->ite_rchild
!= ITE_NULL
))
286 if ((name
< tname
) &&
287 (rchild
->ite_lchild
!= ITE_NULL
))
291 assert(tree
!= ITE_NULL
);
305 * Routine: ipc_splay_prim_assemble
307 * Assembles the results of ipc_splay_prim_lookup
308 * into a splay tree with the found node at the root.
310 * ltree and rtree are by-reference so storing
311 * through ltreep and rtreep can change them.
315 ipc_splay_prim_assemble(
316 ipc_tree_entry_t tree
,
317 ipc_tree_entry_t
*ltree
,
318 ipc_tree_entry_t
*ltreep
,
319 ipc_tree_entry_t
*rtree
,
320 ipc_tree_entry_t
*rtreep
)
322 assert(tree
!= ITE_NULL
);
324 *ltreep
= tree
->ite_lchild
;
325 *rtreep
= tree
->ite_rchild
;
327 tree
->ite_lchild
= *ltree
;
328 tree
->ite_rchild
= *rtree
;
332 * Routine: ipc_splay_tree_init
334 * Initialize a raw splay tree for use.
339 ipc_splay_tree_t splay
)
341 splay
->ist_root
= ITE_NULL
;
345 * Routine: ipc_splay_tree_pick
347 * Picks and returns a random entry in a splay tree.
348 * Returns FALSE if the splay tree is empty.
353 ipc_splay_tree_t splay
,
354 mach_port_name_t
*namep
,
355 ipc_tree_entry_t
*entryp
)
357 ipc_tree_entry_t root
;
361 root
= splay
->ist_root
;
362 if (root
!= ITE_NULL
) {
363 *namep
= root
->ite_name
;
369 return root
!= ITE_NULL
;
373 * Routine: ipc_splay_tree_lookup
375 * Finds an entry in a splay tree.
376 * Returns ITE_NULL if not found.
380 ipc_splay_tree_lookup(
381 ipc_splay_tree_t splay
,
382 mach_port_name_t name
)
384 ipc_tree_entry_t root
;
388 root
= splay
->ist_root
;
389 if (root
!= 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
);
397 splay
->ist_name
= name
;
398 splay
->ist_root
= root
;
401 if (name
!= root
->ite_name
)
411 * Routine: ipc_splay_tree_insert
413 * Inserts a new entry into a splay tree.
414 * The caller supplies a new entry.
415 * The name can't already be present in the tree.
419 ipc_splay_tree_insert(
420 ipc_splay_tree_t splay
,
421 mach_port_name_t name
,
422 ipc_tree_entry_t entry
)
424 ipc_tree_entry_t root
;
426 assert(entry
!= ITE_NULL
);
430 root
= splay
->ist_root
;
431 if (root
== ITE_NULL
) {
432 entry
->ite_lchild
= ITE_NULL
;
433 entry
->ite_rchild
= ITE_NULL
;
435 if (splay
->ist_name
!= name
) {
436 ipc_splay_prim_assemble(root
,
437 &splay
->ist_ltree
, splay
->ist_ltreep
,
438 &splay
->ist_rtree
, splay
->ist_rtreep
);
439 ipc_splay_prim_lookup(name
, root
, &root
,
440 &splay
->ist_ltree
, &splay
->ist_ltreep
,
441 &splay
->ist_rtree
, &splay
->ist_rtreep
);
444 assert(root
->ite_name
!= name
);
446 if (name
< root
->ite_name
) {
447 assert(root
->ite_lchild
== ITE_NULL
);
449 *splay
->ist_ltreep
= ITE_NULL
;
450 *splay
->ist_rtreep
= root
;
452 assert(root
->ite_rchild
== ITE_NULL
);
454 *splay
->ist_ltreep
= root
;
455 *splay
->ist_rtreep
= ITE_NULL
;
458 entry
->ite_lchild
= splay
->ist_ltree
;
459 entry
->ite_rchild
= splay
->ist_rtree
;
462 entry
->ite_name
= name
;
463 splay
->ist_root
= entry
;
464 splay
->ist_name
= name
;
465 splay
->ist_ltreep
= &splay
->ist_ltree
;
466 splay
->ist_rtreep
= &splay
->ist_rtree
;
472 * Routine: ipc_splay_tree_delete
474 * Deletes an entry from a splay tree.
475 * The name must be present in the tree.
478 * The "entry" argument isn't currently used.
479 * Other implementations might want it, though.
483 ipc_splay_tree_delete(
484 ipc_splay_tree_t splay
,
485 mach_port_name_t name
,
486 ipc_tree_entry_t entry
)
488 ipc_tree_entry_t root
, saved
;
492 root
= splay
->ist_root
;
493 assert(root
!= ITE_NULL
);
495 if (splay
->ist_name
!= name
) {
496 ipc_splay_prim_assemble(root
,
497 &splay
->ist_ltree
, splay
->ist_ltreep
,
498 &splay
->ist_rtree
, splay
->ist_rtreep
);
499 ipc_splay_prim_lookup(name
, root
, &root
,
500 &splay
->ist_ltree
, &splay
->ist_ltreep
,
501 &splay
->ist_rtree
, &splay
->ist_rtreep
);
504 assert(root
->ite_name
== name
);
505 assert(root
== entry
);
507 *splay
->ist_ltreep
= root
->ite_lchild
;
508 *splay
->ist_rtreep
= root
->ite_rchild
;
511 root
= splay
->ist_ltree
;
512 saved
= splay
->ist_rtree
;
514 if (root
== ITE_NULL
)
516 else if (saved
!= ITE_NULL
) {
518 * Find the largest node in the left subtree, and splay it
519 * to the root. Then add the saved right subtree.
522 ipc_splay_prim_lookup(MACH_PORT_LARGEST
, root
, &root
,
523 &splay
->ist_ltree
, &splay
->ist_ltreep
,
524 &splay
->ist_rtree
, &splay
->ist_rtreep
);
525 ipc_splay_prim_assemble(root
,
526 &splay
->ist_ltree
, splay
->ist_ltreep
,
527 &splay
->ist_rtree
, splay
->ist_rtreep
);
529 assert(root
->ite_rchild
== ITE_NULL
);
530 root
->ite_rchild
= saved
;
533 splay
->ist_root
= root
;
534 if (root
!= ITE_NULL
) {
535 splay
->ist_name
= root
->ite_name
;
536 splay
->ist_ltreep
= &splay
->ist_ltree
;
537 splay
->ist_rtreep
= &splay
->ist_rtree
;
544 * Routine: ipc_splay_tree_split
546 * Split a splay tree. Puts all entries smaller than "name"
547 * into a new tree, "small".
549 * Doesn't do locking on "small", because nobody else
550 * should be fiddling with the uninitialized tree.
554 ipc_splay_tree_split(
555 ipc_splay_tree_t splay
,
556 mach_port_name_t name
,
557 ipc_splay_tree_t small
)
559 ipc_tree_entry_t root
;
561 ipc_splay_tree_init(small
);
565 root
= splay
->ist_root
;
566 if (root
!= ITE_NULL
) {
567 /* lookup name, to get it (or last traversed) to the top */
569 if (splay
->ist_name
!= name
) {
570 ipc_splay_prim_assemble(root
,
571 &splay
->ist_ltree
, splay
->ist_ltreep
,
572 &splay
->ist_rtree
, splay
->ist_rtreep
);
573 ipc_splay_prim_lookup(name
, root
, &root
,
574 &splay
->ist_ltree
, &splay
->ist_ltreep
,
575 &splay
->ist_rtree
, &splay
->ist_rtreep
);
578 if (root
->ite_name
< name
) {
579 /* root goes into small */
581 *splay
->ist_ltreep
= root
->ite_lchild
;
582 *splay
->ist_rtreep
= ITE_NULL
;
583 root
->ite_lchild
= splay
->ist_ltree
;
584 assert(root
->ite_rchild
== ITE_NULL
);
586 small
->ist_root
= root
;
587 small
->ist_name
= root
->ite_name
;
588 small
->ist_ltreep
= &small
->ist_ltree
;
589 small
->ist_rtreep
= &small
->ist_rtree
;
591 /* rtree goes into splay */
593 root
= splay
->ist_rtree
;
594 splay
->ist_root
= root
;
595 if (root
!= ITE_NULL
) {
596 splay
->ist_name
= root
->ite_name
;
597 splay
->ist_ltreep
= &splay
->ist_ltree
;
598 splay
->ist_rtreep
= &splay
->ist_rtree
;
601 /* root stays in splay */
603 *splay
->ist_ltreep
= root
->ite_lchild
;
604 root
->ite_lchild
= ITE_NULL
;
606 splay
->ist_root
= root
;
607 splay
->ist_name
= name
;
608 splay
->ist_ltreep
= &splay
->ist_ltree
;
610 /* ltree goes into small */
612 root
= splay
->ist_ltree
;
613 small
->ist_root
= root
;
614 if (root
!= ITE_NULL
) {
615 small
->ist_name
= root
->ite_name
;
616 small
->ist_ltreep
= &small
->ist_ltree
;
617 small
->ist_rtreep
= &small
->ist_rtree
;
626 * Routine: ipc_splay_tree_join
628 * Joins two splay trees. Merges the entries in "small",
629 * which must all be smaller than the entries in "splay",
635 ipc_splay_tree_t splay
,
636 ipc_splay_tree_t small
)
638 ipc_tree_entry_t sroot
;
640 /* pull entries out of small */
644 sroot
= small
->ist_root
;
645 if (sroot
!= ITE_NULL
) {
646 ipc_splay_prim_assemble(sroot
,
647 &small
->ist_ltree
, small
->ist_ltreep
,
648 &small
->ist_rtree
, small
->ist_rtreep
);
649 small
->ist_root
= ITE_NULL
;
654 /* put entries, if any, into splay */
656 if (sroot
!= ITE_NULL
) {
657 ipc_tree_entry_t root
;
661 root
= splay
->ist_root
;
662 if (root
== ITE_NULL
) {
665 /* get smallest entry in splay tree to top */
667 if (splay
->ist_name
!= MACH_PORT_SMALLEST
) {
668 ipc_splay_prim_assemble(root
,
669 &splay
->ist_ltree
, splay
->ist_ltreep
,
670 &splay
->ist_rtree
, splay
->ist_rtreep
);
671 ipc_splay_prim_lookup(MACH_PORT_SMALLEST
,
673 &splay
->ist_ltree
, &splay
->ist_ltreep
,
674 &splay
->ist_rtree
, &splay
->ist_rtreep
);
677 ipc_splay_prim_assemble(root
,
678 &splay
->ist_ltree
, splay
->ist_ltreep
,
679 &splay
->ist_rtree
, splay
->ist_rtreep
);
681 assert(root
->ite_lchild
== ITE_NULL
);
682 assert(sroot
->ite_name
< root
->ite_name
);
683 root
->ite_lchild
= sroot
;
686 splay
->ist_root
= root
;
687 splay
->ist_name
= root
->ite_name
;
688 splay
->ist_ltreep
= &splay
->ist_ltree
;
689 splay
->ist_rtreep
= &splay
->ist_rtree
;
696 * Routine: ipc_splay_tree_bounds
698 * Given a name, returns the largest value present
699 * in the tree that is smaller than or equal to the name,
700 * or ~0 if no such value exists. Similarly, returns
701 * the smallest value present that is greater than or
702 * equal to the name, or 0 if no such value exists.
705 * lower = upper, then lower = name = upper
706 * and name is present in the tree
707 * lower = ~0 and upper = 0,
708 * then the tree is empty
709 * lower = ~0 and upper > 0, then name < upper
710 * and upper is smallest value in tree
711 * lower < ~0 and upper = 0, then lower < name
712 * and lower is largest value in tree
713 * lower < ~0 and upper > 0, then lower < name < upper
714 * and they are tight bounds on name
716 * (Note MACH_PORT_SMALLEST = 0 and MACH_PORT_LARGEST = ~0.)
720 ipc_splay_tree_bounds(
721 ipc_splay_tree_t splay
,
722 mach_port_name_t name
,
723 mach_port_name_t
*lowerp
,
724 mach_port_name_t
*upperp
)
726 ipc_tree_entry_t root
;
730 root
= splay
->ist_root
;
731 if (root
== ITE_NULL
) {
732 *lowerp
= MACH_PORT_LARGEST
;
733 *upperp
= MACH_PORT_SMALLEST
;
735 mach_port_name_t rname
;
737 if (splay
->ist_name
!= name
) {
738 ipc_splay_prim_assemble(root
,
739 &splay
->ist_ltree
, splay
->ist_ltreep
,
740 &splay
->ist_rtree
, splay
->ist_rtreep
);
741 ipc_splay_prim_lookup(name
, root
, &root
,
742 &splay
->ist_ltree
, &splay
->ist_ltreep
,
743 &splay
->ist_rtree
, &splay
->ist_rtreep
);
744 splay
->ist_name
= name
;
745 splay
->ist_root
= root
;
748 rname
= root
->ite_name
;
751 * OK, it's a hack. We convert the ltreep and rtreep
752 * pointers back into real entry pointers,
753 * so we can pick the names out of the entries.
758 else if (splay
->ist_ltreep
== &splay
->ist_ltree
)
759 *lowerp
= MACH_PORT_LARGEST
;
761 ipc_tree_entry_t entry
;
763 entry
= (ipc_tree_entry_t
)
764 ((char *)splay
->ist_ltreep
-
765 ((char *)&root
->ite_rchild
-
767 *lowerp
= entry
->ite_name
;
772 else if (splay
->ist_rtreep
== &splay
->ist_rtree
)
773 *upperp
= MACH_PORT_SMALLEST
;
775 ipc_tree_entry_t entry
;
777 entry
= (ipc_tree_entry_t
)
778 ((char *)splay
->ist_rtreep
-
779 ((char *)&root
->ite_lchild
-
781 *upperp
= entry
->ite_name
;
789 * Routine: ipc_splay_traverse_start
790 * Routine: ipc_splay_traverse_next
791 * Routine: ipc_splay_traverse_finish
793 * Perform a symmetric order traversal of a splay tree.
795 * for (entry = ipc_splay_traverse_start(splay);
797 * entry = ipc_splay_traverse_next(splay, delete)) {
798 * do something with entry
800 * ipc_splay_traverse_finish(splay);
802 * If "delete" is TRUE, then the current entry
803 * is removed from the tree and deallocated.
805 * During the traversal, the splay tree is locked.
809 ipc_splay_traverse_start(
810 ipc_splay_tree_t splay
)
812 ipc_tree_entry_t current
, parent
;
816 current
= splay
->ist_root
;
817 if (current
!= ITE_NULL
) {
818 ipc_splay_prim_assemble(current
,
819 &splay
->ist_ltree
, splay
->ist_ltreep
,
820 &splay
->ist_rtree
, splay
->ist_rtreep
);
824 while (current
->ite_lchild
!= ITE_NULL
) {
825 ipc_tree_entry_t next
;
827 next
= current
->ite_lchild
;
828 current
->ite_lchild
= parent
;
833 splay
->ist_ltree
= current
;
834 splay
->ist_rtree
= parent
;
841 ipc_splay_traverse_next(
842 ipc_splay_tree_t splay
,
845 ipc_tree_entry_t current
, parent
;
847 /* pick up where traverse_entry left off */
849 current
= splay
->ist_ltree
;
850 parent
= splay
->ist_rtree
;
851 assert(current
!= ITE_NULL
);
856 /* we must delete current and patch the tree */
858 if (current
->ite_lchild
== ITE_NULL
) {
859 if (current
->ite_rchild
== ITE_NULL
) {
860 /* like traverse_back, but with deletion */
862 if (parent
== ITE_NULL
) {
865 splay
->ist_root
= ITE_NULL
;
869 if (current
->ite_name
< parent
->ite_name
) {
873 parent
= current
->ite_lchild
;
874 current
->ite_lchild
= ITE_NULL
;
880 parent
= current
->ite_rchild
;
881 current
->ite_rchild
= ITE_NULL
;
885 ipc_tree_entry_t prev
;
888 current
= current
->ite_rchild
;
893 if (current
->ite_rchild
== ITE_NULL
) {
894 ipc_tree_entry_t prev
;
897 current
= current
->ite_lchild
;
901 ipc_tree_entry_t prev
;
902 ipc_tree_entry_t ltree
, rtree
;
903 ipc_tree_entry_t
*ltreep
, *rtreep
;
905 /* replace current with largest of left children */
908 ipc_splay_prim_lookup(MACH_PORT_LARGEST
,
909 current
->ite_lchild
, ¤t
,
910 <ree
, <reep
, &rtree
, &rtreep
);
911 ipc_splay_prim_assemble(current
,
912 <ree
, ltreep
, &rtree
, rtreep
);
914 assert(current
->ite_rchild
== ITE_NULL
);
915 current
->ite_rchild
= prev
->ite_rchild
;
923 * A state machine: for each entry, we
924 * 1) traverse left subtree
925 * 2) traverse the entry
926 * 3) traverse right subtree
927 * 4) traverse back to parent
931 if (current
->ite_lchild
!= ITE_NULL
) {
932 ipc_tree_entry_t next
;
934 next
= current
->ite_lchild
;
935 current
->ite_lchild
= parent
;
942 splay
->ist_ltree
= current
;
943 splay
->ist_rtree
= parent
;
947 if (current
->ite_rchild
!= ITE_NULL
) {
948 ipc_tree_entry_t next
;
950 next
= current
->ite_rchild
;
951 current
->ite_rchild
= parent
;
958 if (parent
== ITE_NULL
) {
959 splay
->ist_root
= current
;
963 if (current
->ite_name
< parent
->ite_name
) {
964 ipc_tree_entry_t prev
;
968 parent
= current
->ite_lchild
;
969 current
->ite_lchild
= prev
;
972 ipc_tree_entry_t prev
;
976 parent
= current
->ite_rchild
;
977 current
->ite_rchild
= prev
;
983 ipc_splay_traverse_finish(
984 ipc_splay_tree_t splay
)
986 ipc_tree_entry_t root
;
988 root
= splay
->ist_root
;
989 if (root
!= ITE_NULL
) {
990 splay
->ist_name
= root
->ite_name
;
991 splay
->ist_ltreep
= &splay
->ist_ltree
;
992 splay
->ist_rtreep
= &splay
->ist_rtree
;