]>
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 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
28 * Revision 1.1.1.1 1998/09/22 21:05:28 wsanchez
29 * Import of Mac OS X kernel (~semeria)
31 * Revision 1.1.1.1 1998/03/07 02:26:16 wsanchez
32 * Import of OSF Mach kernel (~mburg)
34 * Revision 1.1.6.1 1994/09/23 02:11:47 ezf
35 * change marker to not FREE
36 * [1994/09/22 21:30:41 ezf]
38 * Revision 1.1.2.3 1993/07/22 16:17:25 rod
39 * Add ANSI prototypes. CR #9523.
40 * [1993/07/22 13:33:20 rod]
42 * Revision 1.1.2.2 1993/06/02 23:33:40 jeffc
43 * Added to OSF/1 R1.3 from NMK15.0.
44 * [1993/06/02 21:11:07 jeffc]
46 * Revision 1.1 1992/09/30 02:08:11 robert
53 * Revision 2.5 91/10/09 16:10:41 af
54 * Revision 2.4.2.1 91/09/16 10:16:00 rpd
55 * Added MACH_PORT_SMALLEST, MACH_PORT_LARGEST definitions to reduce lint.
58 * Revision 2.4.2.1 91/09/16 10:16:00 rpd
59 * Added MACH_PORT_SMALLEST, MACH_PORT_LARGEST definitions to reduce lint.
62 * Revision 2.4 91/05/14 16:37:08 mrt
63 * Correcting copyright
65 * Revision 2.3 91/02/05 17:23:52 mrt
66 * Changed to new Mach copyright
67 * [91/02/01 15:51:43 mrt]
69 * Revision 2.2 90/06/02 14:51:49 rpd
70 * Created for new IPC.
71 * [90/03/26 21:03:46 rpd]
76 * Mach Operating System
77 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
78 * All Rights Reserved.
80 * Permission to use, copy, modify and distribute this software and its
81 * documentation is hereby granted, provided that both the copyright
82 * notice and this permission notice appear in all copies of the
83 * software, derivative works or modified versions, and any portions
84 * thereof, and that both notices appear in supporting documentation.
86 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
87 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
88 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
90 * Carnegie Mellon requests users of this software to return to
92 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
93 * School of Computer Science
94 * Carnegie Mellon University
95 * Pittsburgh PA 15213-3890
97 * any improvements or extensions that they make and grant Carnegie Mellon
98 * the rights to redistribute these changes.
103 * File: ipc/ipc_splay.c
104 * Author: Rich Draves
107 * Primitive splay tree operations.
110 #include <mach/port.h>
111 #include <kern/assert.h>
112 #include <kern/macro_help.h>
113 #include <ipc/ipc_entry.h>
114 #include <ipc/ipc_splay.h>
117 * Splay trees are self-adjusting binary search trees.
118 * They have the following attractive properties:
119 * 1) Space efficient; only two pointers per entry.
120 * 2) Robust performance; amortized O(log n) per operation.
121 * 3) Recursion not needed.
122 * This makes them a good fall-back data structure for those
123 * entries that don't fit into the lookup table.
125 * The paper by Sleator and Tarjan, JACM v. 32, no. 3, pp. 652-686,
126 * describes the splaying operation. ipc_splay_prim_lookup
127 * and ipc_splay_prim_assemble implement the top-down splay
128 * described on p. 669.
130 * The tree is stored in an unassembled form. If ist_root is null,
131 * then the tree has no entries. Otherwise, ist_name records
132 * the value used for the last lookup. ist_root points to the
133 * middle tree obtained from the top-down splay. ist_ltree and
134 * ist_rtree point to left and right subtrees, whose entries
135 * are all smaller (larger) than those in the middle tree.
136 * ist_ltreep and ist_rtreep are pointers to fields in the
137 * left and right subtrees. ist_ltreep points to the rchild field
138 * of the largest entry in ltree, and ist_rtreep points to the
139 * lchild field of the smallest entry in rtree. The pointed-to
140 * fields aren't initialized. If the left (right) subtree is null,
141 * then ist_ltreep (ist_rtreep) points to the ist_ltree (ist_rtree)
142 * field in the splay structure itself.
144 * The primary advantage of the unassembled form is that repeated
145 * unsuccessful lookups are efficient. In particular, an unsuccessful
146 * lookup followed by an insert only requires one splaying operation.
148 * The traversal algorithm works via pointer inversion.
149 * When descending down the tree, child pointers are reversed
150 * to point back to the parent entry. When ascending,
151 * the pointers are restored to their original value.
153 * The biggest potential problem with the splay tree implementation
154 * is that the operations, even lookup, require an exclusive lock.
155 * If IPC spaces are protected with exclusive locks, then
156 * the splay tree doesn't require its own lock, and ist_lock/ist_unlock
157 * needn't do anything. If IPC spaces are protected with read/write
158 * locks then ist_lock/ist_unlock should provide exclusive access.
160 * If it becomes important to let lookups run in parallel,
161 * or if the restructuring makes lookups too expensive, then
162 * there is hope. Use a read/write lock on the splay tree.
163 * Keep track of the number of entries in the tree. When doing
164 * a lookup, first try a non-restructuring lookup with a read lock held,
165 * with a bound (based on log of size of the tree) on the number of
166 * entries to traverse. If the lookup runs up against the bound,
167 * then take a write lock and do a reorganizing lookup.
168 * This way, if lookups only access roughly balanced parts
169 * of the tree, then lookups run in parallel and do no restructuring.
171 * The traversal algorithm currently requires an exclusive lock.
172 * If that is a problem, the tree could be changed from an lchild/rchild
173 * representation to a leftmost child/right sibling representation.
174 * In conjunction with non-restructing lookups, this would let
175 * lookups and traversals all run in parallel. But this representation
176 * is more complicated and would slow down the operations.
180 * Boundary values to hand to ipc_splay_prim_lookup:
183 #define MACH_PORT_SMALLEST ((mach_port_name_t) 0)
184 #define MACH_PORT_LARGEST ((mach_port_name_t) ~0)
187 * Routine: ipc_splay_prim_lookup
189 * Searches for the node labeled name in the splay tree.
190 * Returns three nodes (treep, ltreep, rtreep) and
191 * two pointers to nodes (ltreepp, rtreepp).
193 * ipc_splay_prim_lookup splits the supplied tree into
194 * three subtrees, left, middle, and right, returned
195 * in ltreep, treep, and rtreep.
197 * If name is present in the tree, then it is at
198 * the root of the middle tree. Otherwise, the root
199 * of the middle tree is the last node traversed.
201 * ipc_splay_prim_lookup returns a pointer into
202 * the left subtree, to the rchild field of its
203 * largest node, in ltreepp. It returns a pointer
204 * into the right subtree, to the lchild field of its
205 * smallest node, in rtreepp.
209 ipc_splay_prim_lookup(
210 mach_port_name_t name
,
211 ipc_tree_entry_t tree
,
212 ipc_tree_entry_t
*treep
,
213 ipc_tree_entry_t
*ltreep
,
214 ipc_tree_entry_t
**ltreepp
,
215 ipc_tree_entry_t
*rtreep
,
216 ipc_tree_entry_t
**rtreepp
)
218 mach_port_name_t tname
; /* temp name */
219 ipc_tree_entry_t lchild
, rchild
; /* temp child pointers */
221 assert(tree
!= ITE_NULL
);
226 ltreep = &tree->ite_rchild; \
233 rtreep = &tree->ite_lchild; \
237 #define rotate_left \
239 ipc_tree_entry_t temp = tree; \
241 tree = temp->ite_rchild; \
242 temp->ite_rchild = tree->ite_lchild; \
243 tree->ite_lchild = temp; \
246 #define rotate_right \
248 ipc_tree_entry_t temp = tree; \
250 tree = temp->ite_lchild; \
251 temp->ite_lchild = tree->ite_rchild; \
252 tree->ite_rchild = temp; \
255 while (name
!= (tname
= tree
->ite_name
)) {
257 /* descend to left */
259 lchild
= tree
->ite_lchild
;
260 if (lchild
== ITE_NULL
)
262 tname
= lchild
->ite_name
;
264 if ((name
< tname
) &&
265 (lchild
->ite_lchild
!= ITE_NULL
))
268 if ((name
> tname
) &&
269 (lchild
->ite_rchild
!= ITE_NULL
))
272 /* descend to right */
274 rchild
= tree
->ite_rchild
;
275 if (rchild
== ITE_NULL
)
277 tname
= rchild
->ite_name
;
279 if ((name
> tname
) &&
280 (rchild
->ite_rchild
!= ITE_NULL
))
283 if ((name
< tname
) &&
284 (rchild
->ite_lchild
!= ITE_NULL
))
288 assert(tree
!= ITE_NULL
);
302 * Routine: ipc_splay_prim_assemble
304 * Assembles the results of ipc_splay_prim_lookup
305 * into a splay tree with the found node at the root.
307 * ltree and rtree are by-reference so storing
308 * through ltreep and rtreep can change them.
312 ipc_splay_prim_assemble(
313 ipc_tree_entry_t tree
,
314 ipc_tree_entry_t
*ltree
,
315 ipc_tree_entry_t
*ltreep
,
316 ipc_tree_entry_t
*rtree
,
317 ipc_tree_entry_t
*rtreep
)
319 assert(tree
!= ITE_NULL
);
321 *ltreep
= tree
->ite_lchild
;
322 *rtreep
= tree
->ite_rchild
;
324 tree
->ite_lchild
= *ltree
;
325 tree
->ite_rchild
= *rtree
;
329 * Routine: ipc_splay_tree_init
331 * Initialize a raw splay tree for use.
336 ipc_splay_tree_t splay
)
338 splay
->ist_root
= ITE_NULL
;
342 * Routine: ipc_splay_tree_pick
344 * Picks and returns a random entry in a splay tree.
345 * Returns FALSE if the splay tree is empty.
350 ipc_splay_tree_t splay
,
351 mach_port_name_t
*namep
,
352 ipc_tree_entry_t
*entryp
)
354 ipc_tree_entry_t root
;
358 root
= splay
->ist_root
;
359 if (root
!= ITE_NULL
) {
360 *namep
= root
->ite_name
;
366 return root
!= ITE_NULL
;
370 * Routine: ipc_splay_tree_lookup
372 * Finds an entry in a splay tree.
373 * Returns ITE_NULL if not found.
377 ipc_splay_tree_lookup(
378 ipc_splay_tree_t splay
,
379 mach_port_name_t name
)
381 ipc_tree_entry_t root
;
385 root
= splay
->ist_root
;
386 if (root
!= ITE_NULL
) {
387 if (splay
->ist_name
!= name
) {
388 ipc_splay_prim_assemble(root
,
389 &splay
->ist_ltree
, splay
->ist_ltreep
,
390 &splay
->ist_rtree
, splay
->ist_rtreep
);
391 ipc_splay_prim_lookup(name
, root
, &root
,
392 &splay
->ist_ltree
, &splay
->ist_ltreep
,
393 &splay
->ist_rtree
, &splay
->ist_rtreep
);
394 splay
->ist_name
= name
;
395 splay
->ist_root
= root
;
398 if (name
!= root
->ite_name
)
408 * Routine: ipc_splay_tree_insert
410 * Inserts a new entry into a splay tree.
411 * The caller supplies a new entry.
412 * The name can't already be present in the tree.
416 ipc_splay_tree_insert(
417 ipc_splay_tree_t splay
,
418 mach_port_name_t name
,
419 ipc_tree_entry_t entry
)
421 ipc_tree_entry_t root
;
423 assert(entry
!= ITE_NULL
);
427 root
= splay
->ist_root
;
428 if (root
== ITE_NULL
) {
429 entry
->ite_lchild
= ITE_NULL
;
430 entry
->ite_rchild
= ITE_NULL
;
432 if (splay
->ist_name
!= name
) {
433 ipc_splay_prim_assemble(root
,
434 &splay
->ist_ltree
, splay
->ist_ltreep
,
435 &splay
->ist_rtree
, splay
->ist_rtreep
);
436 ipc_splay_prim_lookup(name
, root
, &root
,
437 &splay
->ist_ltree
, &splay
->ist_ltreep
,
438 &splay
->ist_rtree
, &splay
->ist_rtreep
);
441 assert(root
->ite_name
!= name
);
443 if (name
< root
->ite_name
) {
444 assert(root
->ite_lchild
== ITE_NULL
);
446 *splay
->ist_ltreep
= ITE_NULL
;
447 *splay
->ist_rtreep
= root
;
449 assert(root
->ite_rchild
== ITE_NULL
);
451 *splay
->ist_ltreep
= root
;
452 *splay
->ist_rtreep
= ITE_NULL
;
455 entry
->ite_lchild
= splay
->ist_ltree
;
456 entry
->ite_rchild
= splay
->ist_rtree
;
459 entry
->ite_name
= name
;
460 splay
->ist_root
= entry
;
461 splay
->ist_name
= name
;
462 splay
->ist_ltreep
= &splay
->ist_ltree
;
463 splay
->ist_rtreep
= &splay
->ist_rtree
;
469 * Routine: ipc_splay_tree_delete
471 * Deletes an entry from a splay tree.
472 * The name must be present in the tree.
475 * The "entry" argument isn't currently used.
476 * Other implementations might want it, though.
480 ipc_splay_tree_delete(
481 ipc_splay_tree_t splay
,
482 mach_port_name_t name
,
483 ipc_tree_entry_t entry
)
485 ipc_tree_entry_t root
, saved
;
489 root
= splay
->ist_root
;
490 assert(root
!= ITE_NULL
);
492 if (splay
->ist_name
!= name
) {
493 ipc_splay_prim_assemble(root
,
494 &splay
->ist_ltree
, splay
->ist_ltreep
,
495 &splay
->ist_rtree
, splay
->ist_rtreep
);
496 ipc_splay_prim_lookup(name
, root
, &root
,
497 &splay
->ist_ltree
, &splay
->ist_ltreep
,
498 &splay
->ist_rtree
, &splay
->ist_rtreep
);
501 assert(root
->ite_name
== name
);
502 assert(root
== entry
);
504 *splay
->ist_ltreep
= root
->ite_lchild
;
505 *splay
->ist_rtreep
= root
->ite_rchild
;
508 root
= splay
->ist_ltree
;
509 saved
= splay
->ist_rtree
;
511 if (root
== ITE_NULL
)
513 else if (saved
!= ITE_NULL
) {
515 * Find the largest node in the left subtree, and splay it
516 * to the root. Then add the saved right subtree.
519 ipc_splay_prim_lookup(MACH_PORT_LARGEST
, root
, &root
,
520 &splay
->ist_ltree
, &splay
->ist_ltreep
,
521 &splay
->ist_rtree
, &splay
->ist_rtreep
);
522 ipc_splay_prim_assemble(root
,
523 &splay
->ist_ltree
, splay
->ist_ltreep
,
524 &splay
->ist_rtree
, splay
->ist_rtreep
);
526 assert(root
->ite_rchild
== ITE_NULL
);
527 root
->ite_rchild
= saved
;
530 splay
->ist_root
= root
;
531 if (root
!= ITE_NULL
) {
532 splay
->ist_name
= root
->ite_name
;
533 splay
->ist_ltreep
= &splay
->ist_ltree
;
534 splay
->ist_rtreep
= &splay
->ist_rtree
;
541 * Routine: ipc_splay_tree_split
543 * Split a splay tree. Puts all entries smaller than "name"
544 * into a new tree, "small".
546 * Doesn't do locking on "small", because nobody else
547 * should be fiddling with the uninitialized tree.
551 ipc_splay_tree_split(
552 ipc_splay_tree_t splay
,
553 mach_port_name_t name
,
554 ipc_splay_tree_t small
)
556 ipc_tree_entry_t root
;
558 ipc_splay_tree_init(small
);
562 root
= splay
->ist_root
;
563 if (root
!= ITE_NULL
) {
564 /* lookup name, to get it (or last traversed) to the top */
566 if (splay
->ist_name
!= name
) {
567 ipc_splay_prim_assemble(root
,
568 &splay
->ist_ltree
, splay
->ist_ltreep
,
569 &splay
->ist_rtree
, splay
->ist_rtreep
);
570 ipc_splay_prim_lookup(name
, root
, &root
,
571 &splay
->ist_ltree
, &splay
->ist_ltreep
,
572 &splay
->ist_rtree
, &splay
->ist_rtreep
);
575 if (root
->ite_name
< name
) {
576 /* root goes into small */
578 *splay
->ist_ltreep
= root
->ite_lchild
;
579 *splay
->ist_rtreep
= ITE_NULL
;
580 root
->ite_lchild
= splay
->ist_ltree
;
581 assert(root
->ite_rchild
== ITE_NULL
);
583 small
->ist_root
= root
;
584 small
->ist_name
= root
->ite_name
;
585 small
->ist_ltreep
= &small
->ist_ltree
;
586 small
->ist_rtreep
= &small
->ist_rtree
;
588 /* rtree goes into splay */
590 root
= splay
->ist_rtree
;
591 splay
->ist_root
= root
;
592 if (root
!= ITE_NULL
) {
593 splay
->ist_name
= root
->ite_name
;
594 splay
->ist_ltreep
= &splay
->ist_ltree
;
595 splay
->ist_rtreep
= &splay
->ist_rtree
;
598 /* root stays in splay */
600 *splay
->ist_ltreep
= root
->ite_lchild
;
601 root
->ite_lchild
= ITE_NULL
;
603 splay
->ist_root
= root
;
604 splay
->ist_name
= name
;
605 splay
->ist_ltreep
= &splay
->ist_ltree
;
607 /* ltree goes into small */
609 root
= splay
->ist_ltree
;
610 small
->ist_root
= root
;
611 if (root
!= ITE_NULL
) {
612 small
->ist_name
= root
->ite_name
;
613 small
->ist_ltreep
= &small
->ist_ltree
;
614 small
->ist_rtreep
= &small
->ist_rtree
;
623 * Routine: ipc_splay_tree_join
625 * Joins two splay trees. Merges the entries in "small",
626 * which must all be smaller than the entries in "splay",
632 ipc_splay_tree_t splay
,
633 ipc_splay_tree_t small
)
635 ipc_tree_entry_t sroot
;
637 /* pull entries out of small */
641 sroot
= small
->ist_root
;
642 if (sroot
!= ITE_NULL
) {
643 ipc_splay_prim_assemble(sroot
,
644 &small
->ist_ltree
, small
->ist_ltreep
,
645 &small
->ist_rtree
, small
->ist_rtreep
);
646 small
->ist_root
= ITE_NULL
;
651 /* put entries, if any, into splay */
653 if (sroot
!= ITE_NULL
) {
654 ipc_tree_entry_t root
;
658 root
= splay
->ist_root
;
659 if (root
== ITE_NULL
) {
662 /* get smallest entry in splay tree to top */
664 if (splay
->ist_name
!= MACH_PORT_SMALLEST
) {
665 ipc_splay_prim_assemble(root
,
666 &splay
->ist_ltree
, splay
->ist_ltreep
,
667 &splay
->ist_rtree
, splay
->ist_rtreep
);
668 ipc_splay_prim_lookup(MACH_PORT_SMALLEST
,
670 &splay
->ist_ltree
, &splay
->ist_ltreep
,
671 &splay
->ist_rtree
, &splay
->ist_rtreep
);
674 ipc_splay_prim_assemble(root
,
675 &splay
->ist_ltree
, splay
->ist_ltreep
,
676 &splay
->ist_rtree
, splay
->ist_rtreep
);
678 assert(root
->ite_lchild
== ITE_NULL
);
679 assert(sroot
->ite_name
< root
->ite_name
);
680 root
->ite_lchild
= sroot
;
683 splay
->ist_root
= root
;
684 splay
->ist_name
= root
->ite_name
;
685 splay
->ist_ltreep
= &splay
->ist_ltree
;
686 splay
->ist_rtreep
= &splay
->ist_rtree
;
693 * Routine: ipc_splay_tree_bounds
695 * Given a name, returns the largest value present
696 * in the tree that is smaller than or equal to the name,
697 * or ~0 if no such value exists. Similarly, returns
698 * the smallest value present that is greater than or
699 * equal to the name, or 0 if no such value exists.
702 * lower = upper, then lower = name = upper
703 * and name is present in the tree
704 * lower = ~0 and upper = 0,
705 * then the tree is empty
706 * lower = ~0 and upper > 0, then name < upper
707 * and upper is smallest value in tree
708 * lower < ~0 and upper = 0, then lower < name
709 * and lower is largest value in tree
710 * lower < ~0 and upper > 0, then lower < name < upper
711 * and they are tight bounds on name
713 * (Note MACH_PORT_SMALLEST = 0 and MACH_PORT_LARGEST = ~0.)
717 ipc_splay_tree_bounds(
718 ipc_splay_tree_t splay
,
719 mach_port_name_t name
,
720 mach_port_name_t
*lowerp
,
721 mach_port_name_t
*upperp
)
723 ipc_tree_entry_t root
;
727 root
= splay
->ist_root
;
728 if (root
== ITE_NULL
) {
729 *lowerp
= MACH_PORT_LARGEST
;
730 *upperp
= MACH_PORT_SMALLEST
;
732 mach_port_name_t rname
;
734 if (splay
->ist_name
!= name
) {
735 ipc_splay_prim_assemble(root
,
736 &splay
->ist_ltree
, splay
->ist_ltreep
,
737 &splay
->ist_rtree
, splay
->ist_rtreep
);
738 ipc_splay_prim_lookup(name
, root
, &root
,
739 &splay
->ist_ltree
, &splay
->ist_ltreep
,
740 &splay
->ist_rtree
, &splay
->ist_rtreep
);
741 splay
->ist_name
= name
;
742 splay
->ist_root
= root
;
745 rname
= root
->ite_name
;
748 * OK, it's a hack. We convert the ltreep and rtreep
749 * pointers back into real entry pointers,
750 * so we can pick the names out of the entries.
755 else if (splay
->ist_ltreep
== &splay
->ist_ltree
)
756 *lowerp
= MACH_PORT_LARGEST
;
758 ipc_tree_entry_t entry
;
760 entry
= (ipc_tree_entry_t
)
761 ((char *)splay
->ist_ltreep
-
762 ((char *)&root
->ite_rchild
-
764 *lowerp
= entry
->ite_name
;
769 else if (splay
->ist_rtreep
== &splay
->ist_rtree
)
770 *upperp
= MACH_PORT_SMALLEST
;
772 ipc_tree_entry_t entry
;
774 entry
= (ipc_tree_entry_t
)
775 ((char *)splay
->ist_rtreep
-
776 ((char *)&root
->ite_lchild
-
778 *upperp
= entry
->ite_name
;
786 * Routine: ipc_splay_traverse_start
787 * Routine: ipc_splay_traverse_next
788 * Routine: ipc_splay_traverse_finish
790 * Perform a symmetric order traversal of a splay tree.
792 * for (entry = ipc_splay_traverse_start(splay);
794 * entry = ipc_splay_traverse_next(splay, delete)) {
795 * do something with entry
797 * ipc_splay_traverse_finish(splay);
799 * If "delete" is TRUE, then the current entry
800 * is removed from the tree and deallocated.
802 * During the traversal, the splay tree is locked.
806 ipc_splay_traverse_start(
807 ipc_splay_tree_t splay
)
809 ipc_tree_entry_t current
, parent
;
813 current
= splay
->ist_root
;
814 if (current
!= ITE_NULL
) {
815 ipc_splay_prim_assemble(current
,
816 &splay
->ist_ltree
, splay
->ist_ltreep
,
817 &splay
->ist_rtree
, splay
->ist_rtreep
);
821 while (current
->ite_lchild
!= ITE_NULL
) {
822 ipc_tree_entry_t next
;
824 next
= current
->ite_lchild
;
825 current
->ite_lchild
= parent
;
830 splay
->ist_ltree
= current
;
831 splay
->ist_rtree
= parent
;
838 ipc_splay_traverse_next(
839 ipc_splay_tree_t splay
,
842 ipc_tree_entry_t current
, parent
;
844 /* pick up where traverse_entry left off */
846 current
= splay
->ist_ltree
;
847 parent
= splay
->ist_rtree
;
848 assert(current
!= ITE_NULL
);
853 /* we must delete current and patch the tree */
855 if (current
->ite_lchild
== ITE_NULL
) {
856 if (current
->ite_rchild
== ITE_NULL
) {
857 /* like traverse_back, but with deletion */
859 if (parent
== ITE_NULL
) {
862 splay
->ist_root
= ITE_NULL
;
866 if (current
->ite_name
< parent
->ite_name
) {
870 parent
= current
->ite_lchild
;
871 current
->ite_lchild
= ITE_NULL
;
877 parent
= current
->ite_rchild
;
878 current
->ite_rchild
= ITE_NULL
;
882 ipc_tree_entry_t prev
;
885 current
= current
->ite_rchild
;
890 if (current
->ite_rchild
== ITE_NULL
) {
891 ipc_tree_entry_t prev
;
894 current
= current
->ite_lchild
;
898 ipc_tree_entry_t prev
;
899 ipc_tree_entry_t ltree
, rtree
;
900 ipc_tree_entry_t
*ltreep
, *rtreep
;
902 /* replace current with largest of left children */
905 ipc_splay_prim_lookup(MACH_PORT_LARGEST
,
906 current
->ite_lchild
, ¤t
,
907 <ree
, <reep
, &rtree
, &rtreep
);
908 ipc_splay_prim_assemble(current
,
909 <ree
, ltreep
, &rtree
, rtreep
);
911 assert(current
->ite_rchild
== ITE_NULL
);
912 current
->ite_rchild
= prev
->ite_rchild
;
920 * A state machine: for each entry, we
921 * 1) traverse left subtree
922 * 2) traverse the entry
923 * 3) traverse right subtree
924 * 4) traverse back to parent
928 if (current
->ite_lchild
!= ITE_NULL
) {
929 ipc_tree_entry_t next
;
931 next
= current
->ite_lchild
;
932 current
->ite_lchild
= parent
;
939 splay
->ist_ltree
= current
;
940 splay
->ist_rtree
= parent
;
944 if (current
->ite_rchild
!= ITE_NULL
) {
945 ipc_tree_entry_t next
;
947 next
= current
->ite_rchild
;
948 current
->ite_rchild
= parent
;
955 if (parent
== ITE_NULL
) {
956 splay
->ist_root
= current
;
960 if (current
->ite_name
< parent
->ite_name
) {
961 ipc_tree_entry_t prev
;
965 parent
= current
->ite_lchild
;
966 current
->ite_lchild
= prev
;
969 ipc_tree_entry_t prev
;
973 parent
= current
->ite_rchild
;
974 current
->ite_rchild
= prev
;
980 ipc_splay_traverse_finish(
981 ipc_splay_tree_t splay
)
983 ipc_tree_entry_t root
;
985 root
= splay
->ist_root
;
986 if (root
!= ITE_NULL
) {
987 splay
->ist_name
= root
->ite_name
;
988 splay
->ist_ltreep
= &splay
->ist_ltree
;
989 splay
->ist_rtreep
= &splay
->ist_rtree
;