xref: /onnv-gate/usr/src/common/avl/avl.c (revision 2010)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*2010Ssommerfe  * Common Development and Distribution License (the "License").
6*2010Ssommerfe  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*2010Ssommerfe  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * AVL - generic AVL tree implementation for kernel use
310Sstevel@tonic-gate  *
320Sstevel@tonic-gate  * A complete description of AVL trees can be found in many CS textbooks.
330Sstevel@tonic-gate  *
340Sstevel@tonic-gate  * Here is a very brief overview. An AVL tree is a binary search tree that is
350Sstevel@tonic-gate  * almost perfectly balanced. By "almost" perfectly balanced, we mean that at
360Sstevel@tonic-gate  * any given node, the left and right subtrees are allowed to differ in height
370Sstevel@tonic-gate  * by at most 1 level.
380Sstevel@tonic-gate  *
390Sstevel@tonic-gate  * This relaxation from a perfectly balanced binary tree allows doing
400Sstevel@tonic-gate  * insertion and deletion relatively efficiently. Searching the tree is
410Sstevel@tonic-gate  * still a fast operation, roughly O(log(N)).
420Sstevel@tonic-gate  *
430Sstevel@tonic-gate  * The key to insertion and deletion is a set of tree maniuplations called
440Sstevel@tonic-gate  * rotations, which bring unbalanced subtrees back into the semi-balanced state.
450Sstevel@tonic-gate  *
460Sstevel@tonic-gate  * This implementation of AVL trees has the following peculiarities:
470Sstevel@tonic-gate  *
480Sstevel@tonic-gate  *	- The AVL specific data structures are physically embedded as fields
490Sstevel@tonic-gate  *	  in the "using" data structures.  To maintain generality the code
500Sstevel@tonic-gate  *	  must constantly translate between "avl_node_t *" and containing
510Sstevel@tonic-gate  *	  data structure "void *"s by adding/subracting the avl_offset.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  *	- Since the AVL data is always embedded in other structures, there is
540Sstevel@tonic-gate  *	  no locking or memory allocation in the AVL routines. This must be
550Sstevel@tonic-gate  *	  provided for by the enclosing data structure's semantics. Typically,
56789Sahrens  *	  avl_insert()/_add()/_remove()/avl_insert_here() require some kind of
570Sstevel@tonic-gate  *	  exclusive write lock. Other operations require a read lock.
580Sstevel@tonic-gate  *
590Sstevel@tonic-gate  *      - The implementation uses iteration instead of explicit recursion,
600Sstevel@tonic-gate  *	  since it is intended to run on limited size kernel stacks. Since
610Sstevel@tonic-gate  *	  there is no recursion stack present to move "up" in the tree,
620Sstevel@tonic-gate  *	  there is an explicit "parent" link in the avl_node_t.
630Sstevel@tonic-gate  *
640Sstevel@tonic-gate  *      - The left/right children pointers of a node are in an array.
650Sstevel@tonic-gate  *	  In the code, variables (instead of constants) are used to represent
660Sstevel@tonic-gate  *	  left and right indices.  The implementation is written as if it only
670Sstevel@tonic-gate  *	  dealt with left handed manipulations.  By changing the value assigned
680Sstevel@tonic-gate  *	  to "left", the code also works for right handed trees.  The
690Sstevel@tonic-gate  *	  following variables/terms are frequently used:
700Sstevel@tonic-gate  *
710Sstevel@tonic-gate  *		int left;	// 0 when dealing with left children,
720Sstevel@tonic-gate  *				// 1 for dealing with right children
730Sstevel@tonic-gate  *
740Sstevel@tonic-gate  *		int left_heavy;	// -1 when left subtree is taller at some node,
750Sstevel@tonic-gate  *				// +1 when right subtree is taller
760Sstevel@tonic-gate  *
770Sstevel@tonic-gate  *		int right;	// will be the opposite of left (0 or 1)
780Sstevel@tonic-gate  *		int right_heavy;// will be the opposite of left_heavy (-1 or 1)
790Sstevel@tonic-gate  *
800Sstevel@tonic-gate  *		int direction;  // 0 for "<" (ie. left child); 1 for ">" (right)
810Sstevel@tonic-gate  *
820Sstevel@tonic-gate  *	  Though it is a little more confusing to read the code, the approach
830Sstevel@tonic-gate  *	  allows using half as much code (and hence cache footprint) for tree
840Sstevel@tonic-gate  *	  manipulations and eliminates many conditional branches.
850Sstevel@tonic-gate  *
860Sstevel@tonic-gate  *	- The avl_index_t is an opaque "cookie" used to find nodes at or
870Sstevel@tonic-gate  *	  adjacent to where a new value would be inserted in the tree. The value
880Sstevel@tonic-gate  *	  is a modified "avl_node_t *".  The bottom bit (normally 0 for a
890Sstevel@tonic-gate  *	  pointer) is set to indicate if that the new node has a value greater
900Sstevel@tonic-gate  *	  than the value of the indicated "avl_node_t *".
910Sstevel@tonic-gate  */
920Sstevel@tonic-gate 
930Sstevel@tonic-gate #include <sys/types.h>
940Sstevel@tonic-gate #include <sys/param.h>
950Sstevel@tonic-gate #include <sys/debug.h>
960Sstevel@tonic-gate #include <sys/avl.h>
97789Sahrens #include <sys/cmn_err.h>
980Sstevel@tonic-gate 
990Sstevel@tonic-gate /*
1000Sstevel@tonic-gate  * Small arrays to translate between balance (or diff) values and child indeces.
1010Sstevel@tonic-gate  *
1020Sstevel@tonic-gate  * Code that deals with binary tree data structures will randomly use
1030Sstevel@tonic-gate  * left and right children when examining a tree.  C "if()" statements
1040Sstevel@tonic-gate  * which evaluate randomly suffer from very poor hardware branch prediction.
1050Sstevel@tonic-gate  * In this code we avoid some of the branch mispredictions by using the
1060Sstevel@tonic-gate  * following translation arrays. They replace random branches with an
1070Sstevel@tonic-gate  * additional memory reference. Since the translation arrays are both very
1080Sstevel@tonic-gate  * small the data should remain efficiently in cache.
1090Sstevel@tonic-gate  */
1100Sstevel@tonic-gate static const int  avl_child2balance[2]	= {-1, 1};
1110Sstevel@tonic-gate static const int  avl_balance2child[]	= {0, 0, 1};
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate /*
1150Sstevel@tonic-gate  * Walk from one node to the previous valued node (ie. an infix walk
1160Sstevel@tonic-gate  * towards the left). At any given node we do one of 2 things:
1170Sstevel@tonic-gate  *
1180Sstevel@tonic-gate  * - If there is a left child, go to it, then to it's rightmost descendant.
1190Sstevel@tonic-gate  *
1200Sstevel@tonic-gate  * - otherwise we return thru parent nodes until we've come from a right child.
1210Sstevel@tonic-gate  *
1220Sstevel@tonic-gate  * Return Value:
1230Sstevel@tonic-gate  * NULL - if at the end of the nodes
1240Sstevel@tonic-gate  * otherwise next node
1250Sstevel@tonic-gate  */
1260Sstevel@tonic-gate void *
1270Sstevel@tonic-gate avl_walk(avl_tree_t *tree, void	*oldnode, int left)
1280Sstevel@tonic-gate {
1290Sstevel@tonic-gate 	size_t off = tree->avl_offset;
1300Sstevel@tonic-gate 	avl_node_t *node = AVL_DATA2NODE(oldnode, off);
1310Sstevel@tonic-gate 	int right = 1 - left;
1320Sstevel@tonic-gate 	int was_child;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	/*
1360Sstevel@tonic-gate 	 * nowhere to walk to if tree is empty
1370Sstevel@tonic-gate 	 */
1380Sstevel@tonic-gate 	if (node == NULL)
1390Sstevel@tonic-gate 		return (NULL);
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	/*
1420Sstevel@tonic-gate 	 * Visit the previous valued node. There are two possibilities:
1430Sstevel@tonic-gate 	 *
1440Sstevel@tonic-gate 	 * If this node has a left child, go down one left, then all
1450Sstevel@tonic-gate 	 * the way right.
1460Sstevel@tonic-gate 	 */
1470Sstevel@tonic-gate 	if (node->avl_child[left] != NULL) {
1480Sstevel@tonic-gate 		for (node = node->avl_child[left];
1490Sstevel@tonic-gate 		    node->avl_child[right] != NULL;
1500Sstevel@tonic-gate 		    node = node->avl_child[right])
1510Sstevel@tonic-gate 			;
1520Sstevel@tonic-gate 	/*
1530Sstevel@tonic-gate 	 * Otherwise, return thru left children as far as we can.
1540Sstevel@tonic-gate 	 */
1550Sstevel@tonic-gate 	} else {
1560Sstevel@tonic-gate 		for (;;) {
1570Sstevel@tonic-gate 			was_child = AVL_XCHILD(node);
1580Sstevel@tonic-gate 			node = AVL_XPARENT(node);
1590Sstevel@tonic-gate 			if (node == NULL)
1600Sstevel@tonic-gate 				return (NULL);
1610Sstevel@tonic-gate 			if (was_child == right)
1620Sstevel@tonic-gate 				break;
1630Sstevel@tonic-gate 		}
1640Sstevel@tonic-gate 	}
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	return (AVL_NODE2DATA(node, off));
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate  * Return the lowest valued node in a tree or NULL.
1710Sstevel@tonic-gate  * (leftmost child from root of tree)
1720Sstevel@tonic-gate  */
1730Sstevel@tonic-gate void *
1740Sstevel@tonic-gate avl_first(avl_tree_t *tree)
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate 	avl_node_t *node;
1770Sstevel@tonic-gate 	avl_node_t *prev = NULL;
1780Sstevel@tonic-gate 	size_t off = tree->avl_offset;
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	for (node = tree->avl_root; node != NULL; node = node->avl_child[0])
1810Sstevel@tonic-gate 		prev = node;
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 	if (prev != NULL)
1840Sstevel@tonic-gate 		return (AVL_NODE2DATA(prev, off));
1850Sstevel@tonic-gate 	return (NULL);
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate /*
1890Sstevel@tonic-gate  * Return the highest valued node in a tree or NULL.
1900Sstevel@tonic-gate  * (rightmost child from root of tree)
1910Sstevel@tonic-gate  */
1920Sstevel@tonic-gate void *
1930Sstevel@tonic-gate avl_last(avl_tree_t *tree)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate 	avl_node_t *node;
1960Sstevel@tonic-gate 	avl_node_t *prev = NULL;
1970Sstevel@tonic-gate 	size_t off = tree->avl_offset;
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	for (node = tree->avl_root; node != NULL; node = node->avl_child[1])
2000Sstevel@tonic-gate 		prev = node;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	if (prev != NULL)
2030Sstevel@tonic-gate 		return (AVL_NODE2DATA(prev, off));
2040Sstevel@tonic-gate 	return (NULL);
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate /*
2080Sstevel@tonic-gate  * Access the node immediately before or after an insertion point.
2090Sstevel@tonic-gate  *
2100Sstevel@tonic-gate  * "avl_index_t" is a (avl_node_t *) with the bottom bit indicating a child
2110Sstevel@tonic-gate  *
2120Sstevel@tonic-gate  * Return value:
2130Sstevel@tonic-gate  *	NULL: no node in the given direction
2140Sstevel@tonic-gate  *	"void *"  of the found tree node
2150Sstevel@tonic-gate  */
2160Sstevel@tonic-gate void *
2170Sstevel@tonic-gate avl_nearest(avl_tree_t *tree, avl_index_t where, int direction)
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate 	int child = AVL_INDEX2CHILD(where);
2200Sstevel@tonic-gate 	avl_node_t *node = AVL_INDEX2NODE(where);
2210Sstevel@tonic-gate 	void *data;
2220Sstevel@tonic-gate 	size_t off = tree->avl_offset;
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	if (node == NULL) {
2250Sstevel@tonic-gate 		ASSERT(tree->avl_root == NULL);
2260Sstevel@tonic-gate 		return (NULL);
2270Sstevel@tonic-gate 	}
2280Sstevel@tonic-gate 	data = AVL_NODE2DATA(node, off);
2290Sstevel@tonic-gate 	if (child != direction)
2300Sstevel@tonic-gate 		return (data);
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	return (avl_walk(tree, data, direction));
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate /*
2370Sstevel@tonic-gate  * Search for the node which contains "value".  The algorithm is a
2380Sstevel@tonic-gate  * simple binary tree search.
2390Sstevel@tonic-gate  *
2400Sstevel@tonic-gate  * return value:
2410Sstevel@tonic-gate  *	NULL: the value is not in the AVL tree
2420Sstevel@tonic-gate  *		*where (if not NULL)  is set to indicate the insertion point
2430Sstevel@tonic-gate  *	"void *"  of the found tree node
2440Sstevel@tonic-gate  */
2450Sstevel@tonic-gate void *
2460Sstevel@tonic-gate avl_find(avl_tree_t *tree, void *value, avl_index_t *where)
2470Sstevel@tonic-gate {
2480Sstevel@tonic-gate 	avl_node_t *node;
2490Sstevel@tonic-gate 	avl_node_t *prev = NULL;
2500Sstevel@tonic-gate 	int child = 0;
2510Sstevel@tonic-gate 	int diff;
2520Sstevel@tonic-gate 	size_t off = tree->avl_offset;
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	for (node = tree->avl_root; node != NULL;
2550Sstevel@tonic-gate 	    node = node->avl_child[child]) {
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 		prev = node;
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 		diff = tree->avl_compar(value, AVL_NODE2DATA(node, off));
2600Sstevel@tonic-gate 		ASSERT(-1 <= diff && diff <= 1);
2610Sstevel@tonic-gate 		if (diff == 0) {
2620Sstevel@tonic-gate #ifdef DEBUG
2630Sstevel@tonic-gate 			if (where != NULL)
2640Sstevel@tonic-gate 				*where = NULL;
2650Sstevel@tonic-gate #endif
2660Sstevel@tonic-gate 			return (AVL_NODE2DATA(node, off));
2670Sstevel@tonic-gate 		}
2680Sstevel@tonic-gate 		child = avl_balance2child[1 + diff];
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	}
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	if (where != NULL)
2730Sstevel@tonic-gate 		*where = AVL_MKINDEX(prev, child);
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	return (NULL);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate /*
2800Sstevel@tonic-gate  * Perform a rotation to restore balance at the subtree given by depth.
2810Sstevel@tonic-gate  *
2820Sstevel@tonic-gate  * This routine is used by both insertion and deletion. The return value
2830Sstevel@tonic-gate  * indicates:
2840Sstevel@tonic-gate  *	 0 : subtree did not change height
2850Sstevel@tonic-gate  *	!0 : subtree was reduced in height
2860Sstevel@tonic-gate  *
2870Sstevel@tonic-gate  * The code is written as if handling left rotations, right rotations are
2880Sstevel@tonic-gate  * symmetric and handled by swapping values of variables right/left[_heavy]
2890Sstevel@tonic-gate  *
2900Sstevel@tonic-gate  * On input balance is the "new" balance at "node". This value is either
2910Sstevel@tonic-gate  * -2 or +2.
2920Sstevel@tonic-gate  */
2930Sstevel@tonic-gate static int
2940Sstevel@tonic-gate avl_rotation(avl_tree_t *tree, avl_node_t *node, int balance)
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate 	int left = !(balance < 0);	/* when balance = -2, left will be 0 */
2970Sstevel@tonic-gate 	int right = 1 - left;
2980Sstevel@tonic-gate 	int left_heavy = balance >> 1;
2990Sstevel@tonic-gate 	int right_heavy = -left_heavy;
3000Sstevel@tonic-gate 	avl_node_t *parent = AVL_XPARENT(node);
3010Sstevel@tonic-gate 	avl_node_t *child = node->avl_child[left];
3020Sstevel@tonic-gate 	avl_node_t *cright;
3030Sstevel@tonic-gate 	avl_node_t *gchild;
3040Sstevel@tonic-gate 	avl_node_t *gright;
3050Sstevel@tonic-gate 	avl_node_t *gleft;
3060Sstevel@tonic-gate 	int which_child = AVL_XCHILD(node);
3070Sstevel@tonic-gate 	int child_bal = AVL_XBALANCE(child);
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	/* BEGIN CSTYLED */
3100Sstevel@tonic-gate 	/*
3110Sstevel@tonic-gate 	 * case 1 : node is overly left heavy, the left child is balanced or
3120Sstevel@tonic-gate 	 * also left heavy. This requires the following rotation.
3130Sstevel@tonic-gate 	 *
3140Sstevel@tonic-gate 	 *                   (node bal:-2)
3150Sstevel@tonic-gate 	 *                    /           \
3160Sstevel@tonic-gate 	 *                   /             \
3170Sstevel@tonic-gate 	 *              (child bal:0 or -1)
3180Sstevel@tonic-gate 	 *              /    \
3190Sstevel@tonic-gate 	 *             /      \
3200Sstevel@tonic-gate 	 *                     cright
3210Sstevel@tonic-gate 	 *
3220Sstevel@tonic-gate 	 * becomes:
3230Sstevel@tonic-gate 	 *
3240Sstevel@tonic-gate 	 *              (child bal:1 or 0)
3250Sstevel@tonic-gate 	 *              /        \
3260Sstevel@tonic-gate 	 *             /          \
3270Sstevel@tonic-gate 	 *                        (node bal:-1 or 0)
3280Sstevel@tonic-gate 	 *                         /     \
3290Sstevel@tonic-gate 	 *                        /       \
3300Sstevel@tonic-gate 	 *                     cright
3310Sstevel@tonic-gate 	 *
3320Sstevel@tonic-gate 	 * we detect this situation by noting that child's balance is not
3330Sstevel@tonic-gate 	 * right_heavy.
3340Sstevel@tonic-gate 	 */
3350Sstevel@tonic-gate 	/* END CSTYLED */
3360Sstevel@tonic-gate 	if (child_bal != right_heavy) {
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 		/*
3390Sstevel@tonic-gate 		 * compute new balance of nodes
3400Sstevel@tonic-gate 		 *
3410Sstevel@tonic-gate 		 * If child used to be left heavy (now balanced) we reduced
3420Sstevel@tonic-gate 		 * the height of this sub-tree -- used in "return...;" below
3430Sstevel@tonic-gate 		 */
3440Sstevel@tonic-gate 		child_bal += right_heavy; /* adjust towards right */
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 		/*
3470Sstevel@tonic-gate 		 * move "cright" to be node's left child
3480Sstevel@tonic-gate 		 */
3490Sstevel@tonic-gate 		cright = child->avl_child[right];
3500Sstevel@tonic-gate 		node->avl_child[left] = cright;
3510Sstevel@tonic-gate 		if (cright != NULL) {
3520Sstevel@tonic-gate 			AVL_SETPARENT(cright, node);
3530Sstevel@tonic-gate 			AVL_SETCHILD(cright, left);
3540Sstevel@tonic-gate 		}
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 		/*
3570Sstevel@tonic-gate 		 * move node to be child's right child
3580Sstevel@tonic-gate 		 */
3590Sstevel@tonic-gate 		child->avl_child[right] = node;
3600Sstevel@tonic-gate 		AVL_SETBALANCE(node, -child_bal);
3610Sstevel@tonic-gate 		AVL_SETCHILD(node, right);
3620Sstevel@tonic-gate 		AVL_SETPARENT(node, child);
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 		/*
3650Sstevel@tonic-gate 		 * update the pointer into this subtree
3660Sstevel@tonic-gate 		 */
3670Sstevel@tonic-gate 		AVL_SETBALANCE(child, child_bal);
3680Sstevel@tonic-gate 		AVL_SETCHILD(child, which_child);
3690Sstevel@tonic-gate 		AVL_SETPARENT(child, parent);
3700Sstevel@tonic-gate 		if (parent != NULL)
3710Sstevel@tonic-gate 			parent->avl_child[which_child] = child;
3720Sstevel@tonic-gate 		else
3730Sstevel@tonic-gate 			tree->avl_root = child;
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 		return (child_bal == 0);
3760Sstevel@tonic-gate 	}
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	/* BEGIN CSTYLED */
3790Sstevel@tonic-gate 	/*
3800Sstevel@tonic-gate 	 * case 2 : When node is left heavy, but child is right heavy we use
3810Sstevel@tonic-gate 	 * a different rotation.
3820Sstevel@tonic-gate 	 *
3830Sstevel@tonic-gate 	 *                   (node b:-2)
3840Sstevel@tonic-gate 	 *                    /   \
3850Sstevel@tonic-gate 	 *                   /     \
3860Sstevel@tonic-gate 	 *                  /       \
3870Sstevel@tonic-gate 	 *             (child b:+1)
3880Sstevel@tonic-gate 	 *              /     \
3890Sstevel@tonic-gate 	 *             /       \
3900Sstevel@tonic-gate 	 *                   (gchild b: != 0)
3910Sstevel@tonic-gate 	 *                     /  \
3920Sstevel@tonic-gate 	 *                    /    \
3930Sstevel@tonic-gate 	 *                 gleft   gright
3940Sstevel@tonic-gate 	 *
3950Sstevel@tonic-gate 	 * becomes:
3960Sstevel@tonic-gate 	 *
3970Sstevel@tonic-gate 	 *              (gchild b:0)
3980Sstevel@tonic-gate 	 *              /       \
3990Sstevel@tonic-gate 	 *             /         \
4000Sstevel@tonic-gate 	 *            /           \
4010Sstevel@tonic-gate 	 *        (child b:?)   (node b:?)
4020Sstevel@tonic-gate 	 *         /  \          /   \
4030Sstevel@tonic-gate 	 *        /    \        /     \
4040Sstevel@tonic-gate 	 *            gleft   gright
4050Sstevel@tonic-gate 	 *
4060Sstevel@tonic-gate 	 * computing the new balances is more complicated. As an example:
4070Sstevel@tonic-gate 	 *	 if gchild was right_heavy, then child is now left heavy
4080Sstevel@tonic-gate 	 *		else it is balanced
4090Sstevel@tonic-gate 	 */
4100Sstevel@tonic-gate 	/* END CSTYLED */
4110Sstevel@tonic-gate 	gchild = child->avl_child[right];
4120Sstevel@tonic-gate 	gleft = gchild->avl_child[left];
4130Sstevel@tonic-gate 	gright = gchild->avl_child[right];
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	/*
4160Sstevel@tonic-gate 	 * move gright to left child of node and
4170Sstevel@tonic-gate 	 *
4180Sstevel@tonic-gate 	 * move gleft to right child of node
4190Sstevel@tonic-gate 	 */
4200Sstevel@tonic-gate 	node->avl_child[left] = gright;
4210Sstevel@tonic-gate 	if (gright != NULL) {
4220Sstevel@tonic-gate 		AVL_SETPARENT(gright, node);
4230Sstevel@tonic-gate 		AVL_SETCHILD(gright, left);
4240Sstevel@tonic-gate 	}
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 	child->avl_child[right] = gleft;
4270Sstevel@tonic-gate 	if (gleft != NULL) {
4280Sstevel@tonic-gate 		AVL_SETPARENT(gleft, child);
4290Sstevel@tonic-gate 		AVL_SETCHILD(gleft, right);
4300Sstevel@tonic-gate 	}
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	/*
4330Sstevel@tonic-gate 	 * move child to left child of gchild and
4340Sstevel@tonic-gate 	 *
4350Sstevel@tonic-gate 	 * move node to right child of gchild and
4360Sstevel@tonic-gate 	 *
4370Sstevel@tonic-gate 	 * fixup parent of all this to point to gchild
4380Sstevel@tonic-gate 	 */
4390Sstevel@tonic-gate 	balance = AVL_XBALANCE(gchild);
4400Sstevel@tonic-gate 	gchild->avl_child[left] = child;
4410Sstevel@tonic-gate 	AVL_SETBALANCE(child, (balance == right_heavy ? left_heavy : 0));
4420Sstevel@tonic-gate 	AVL_SETPARENT(child, gchild);
4430Sstevel@tonic-gate 	AVL_SETCHILD(child, left);
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	gchild->avl_child[right] = node;
4460Sstevel@tonic-gate 	AVL_SETBALANCE(node, (balance == left_heavy ? right_heavy : 0));
4470Sstevel@tonic-gate 	AVL_SETPARENT(node, gchild);
4480Sstevel@tonic-gate 	AVL_SETCHILD(node, right);
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	AVL_SETBALANCE(gchild, 0);
4510Sstevel@tonic-gate 	AVL_SETPARENT(gchild, parent);
4520Sstevel@tonic-gate 	AVL_SETCHILD(gchild, which_child);
4530Sstevel@tonic-gate 	if (parent != NULL)
4540Sstevel@tonic-gate 		parent->avl_child[which_child] = gchild;
4550Sstevel@tonic-gate 	else
4560Sstevel@tonic-gate 		tree->avl_root = gchild;
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	return (1);	/* the new tree is always shorter */
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate /*
4630Sstevel@tonic-gate  * Insert a new node into an AVL tree at the specified (from avl_find()) place.
4640Sstevel@tonic-gate  *
4650Sstevel@tonic-gate  * Newly inserted nodes are always leaf nodes in the tree, since avl_find()
4660Sstevel@tonic-gate  * searches out to the leaf positions.  The avl_index_t indicates the node
4670Sstevel@tonic-gate  * which will be the parent of the new node.
4680Sstevel@tonic-gate  *
4690Sstevel@tonic-gate  * After the node is inserted, a single rotation further up the tree may
4700Sstevel@tonic-gate  * be necessary to maintain an acceptable AVL balance.
4710Sstevel@tonic-gate  */
4720Sstevel@tonic-gate void
4730Sstevel@tonic-gate avl_insert(avl_tree_t *tree, void *new_data, avl_index_t where)
4740Sstevel@tonic-gate {
4750Sstevel@tonic-gate 	avl_node_t *node;
4760Sstevel@tonic-gate 	avl_node_t *parent = AVL_INDEX2NODE(where);
4770Sstevel@tonic-gate 	int old_balance;
4780Sstevel@tonic-gate 	int new_balance;
4790Sstevel@tonic-gate 	int which_child = AVL_INDEX2CHILD(where);
4800Sstevel@tonic-gate 	size_t off = tree->avl_offset;
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	ASSERT(tree);
4830Sstevel@tonic-gate #ifdef _LP64
4840Sstevel@tonic-gate 	ASSERT(((uintptr_t)new_data & 0x7) == 0);
4850Sstevel@tonic-gate #endif
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	node = AVL_DATA2NODE(new_data, off);
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	/*
4900Sstevel@tonic-gate 	 * First, add the node to the tree at the indicated position.
4910Sstevel@tonic-gate 	 */
4920Sstevel@tonic-gate 	++tree->avl_numnodes;
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	node->avl_child[0] = NULL;
4950Sstevel@tonic-gate 	node->avl_child[1] = NULL;
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	AVL_SETCHILD(node, which_child);
4980Sstevel@tonic-gate 	AVL_SETBALANCE(node, 0);
4990Sstevel@tonic-gate 	AVL_SETPARENT(node, parent);
5000Sstevel@tonic-gate 	if (parent != NULL) {
5010Sstevel@tonic-gate 		ASSERT(parent->avl_child[which_child] == NULL);
5020Sstevel@tonic-gate 		parent->avl_child[which_child] = node;
5030Sstevel@tonic-gate 	} else {
5040Sstevel@tonic-gate 		ASSERT(tree->avl_root == NULL);
5050Sstevel@tonic-gate 		tree->avl_root = node;
5060Sstevel@tonic-gate 	}
5070Sstevel@tonic-gate 	/*
5080Sstevel@tonic-gate 	 * Now, back up the tree modifying the balance of all nodes above the
5090Sstevel@tonic-gate 	 * insertion point. If we get to a highly unbalanced ancestor, we
5100Sstevel@tonic-gate 	 * need to do a rotation.  If we back out of the tree we are done.
5110Sstevel@tonic-gate 	 * If we brought any subtree into perfect balance (0), we are also done.
5120Sstevel@tonic-gate 	 */
5130Sstevel@tonic-gate 	for (;;) {
5140Sstevel@tonic-gate 		node = parent;
5150Sstevel@tonic-gate 		if (node == NULL)
5160Sstevel@tonic-gate 			return;
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 		/*
5190Sstevel@tonic-gate 		 * Compute the new balance
5200Sstevel@tonic-gate 		 */
5210Sstevel@tonic-gate 		old_balance = AVL_XBALANCE(node);
5220Sstevel@tonic-gate 		new_balance = old_balance + avl_child2balance[which_child];
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 		/*
5250Sstevel@tonic-gate 		 * If we introduced equal balance, then we are done immediately
5260Sstevel@tonic-gate 		 */
5270Sstevel@tonic-gate 		if (new_balance == 0) {
5280Sstevel@tonic-gate 			AVL_SETBALANCE(node, 0);
5290Sstevel@tonic-gate 			return;
5300Sstevel@tonic-gate 		}
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 		/*
5330Sstevel@tonic-gate 		 * If both old and new are not zero we went
5340Sstevel@tonic-gate 		 * from -1 to -2 balance, do a rotation.
5350Sstevel@tonic-gate 		 */
5360Sstevel@tonic-gate 		if (old_balance != 0)
5370Sstevel@tonic-gate 			break;
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 		AVL_SETBALANCE(node, new_balance);
5400Sstevel@tonic-gate 		parent = AVL_XPARENT(node);
5410Sstevel@tonic-gate 		which_child = AVL_XCHILD(node);
5420Sstevel@tonic-gate 	}
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	/*
5450Sstevel@tonic-gate 	 * perform a rotation to fix the tree and return
5460Sstevel@tonic-gate 	 */
5470Sstevel@tonic-gate 	(void) avl_rotation(tree, node, new_balance);
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate /*
5510Sstevel@tonic-gate  * Insert "new_data" in "tree" in the given "direction" either after or
5520Sstevel@tonic-gate  * before (AVL_AFTER, AVL_BEFORE) the data "here".
5530Sstevel@tonic-gate  *
5540Sstevel@tonic-gate  * Insertions can only be done at empty leaf points in the tree, therefore
5550Sstevel@tonic-gate  * if the given child of the node is already present we move to either
5560Sstevel@tonic-gate  * the AVL_PREV or AVL_NEXT and reverse the insertion direction. Since
5570Sstevel@tonic-gate  * every other node in the tree is a leaf, this always works.
5580Sstevel@tonic-gate  *
5590Sstevel@tonic-gate  * To help developers using this interface, we assert that the new node
5600Sstevel@tonic-gate  * is correctly ordered at every step of the way in DEBUG kernels.
5610Sstevel@tonic-gate  */
5620Sstevel@tonic-gate void
5630Sstevel@tonic-gate avl_insert_here(
5640Sstevel@tonic-gate 	avl_tree_t *tree,
5650Sstevel@tonic-gate 	void *new_data,
5660Sstevel@tonic-gate 	void *here,
5670Sstevel@tonic-gate 	int direction)
5680Sstevel@tonic-gate {
5690Sstevel@tonic-gate 	avl_node_t *node;
5700Sstevel@tonic-gate 	int child = direction;	/* rely on AVL_BEFORE == 0, AVL_AFTER == 1 */
571*2010Ssommerfe #ifdef DEBUG
572*2010Ssommerfe 	int diff;
573*2010Ssommerfe #endif
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	ASSERT(tree != NULL);
5760Sstevel@tonic-gate 	ASSERT(new_data != NULL);
5770Sstevel@tonic-gate 	ASSERT(here != NULL);
5780Sstevel@tonic-gate 	ASSERT(direction == AVL_BEFORE || direction == AVL_AFTER);
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	/*
5810Sstevel@tonic-gate 	 * If corresponding child of node is not NULL, go to the neighboring
5820Sstevel@tonic-gate 	 * node and reverse the insertion direction.
5830Sstevel@tonic-gate 	 */
5840Sstevel@tonic-gate 	node = AVL_DATA2NODE(here, tree->avl_offset);
585*2010Ssommerfe 
586*2010Ssommerfe #ifdef DEBUG
587*2010Ssommerfe 	diff = tree->avl_compar(new_data, here);
588*2010Ssommerfe 	ASSERT(-1 <= diff && diff <= 1);
589*2010Ssommerfe 	ASSERT(diff != 0);
590*2010Ssommerfe 	ASSERT(diff > 0 ? child == 1 : child == 0);
591*2010Ssommerfe #endif
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	if (node->avl_child[child] != NULL) {
5940Sstevel@tonic-gate 		node = node->avl_child[child];
5950Sstevel@tonic-gate 		child = 1 - child;
5960Sstevel@tonic-gate 		while (node->avl_child[child] != NULL) {
597*2010Ssommerfe #ifdef DEBUG
598*2010Ssommerfe 			diff = tree->avl_compar(new_data,
599*2010Ssommerfe 			    AVL_NODE2DATA(node, tree->avl_offset));
600*2010Ssommerfe 			ASSERT(-1 <= diff && diff <= 1);
601*2010Ssommerfe 			ASSERT(diff != 0);
602*2010Ssommerfe 			ASSERT(diff > 0 ? child == 1 : child == 0);
603*2010Ssommerfe #endif
6040Sstevel@tonic-gate 			node = node->avl_child[child];
6050Sstevel@tonic-gate 		}
606*2010Ssommerfe #ifdef DEBUG
607*2010Ssommerfe 		diff = tree->avl_compar(new_data,
608*2010Ssommerfe 		    AVL_NODE2DATA(node, tree->avl_offset));
609*2010Ssommerfe 		ASSERT(-1 <= diff && diff <= 1);
610*2010Ssommerfe 		ASSERT(diff != 0);
611*2010Ssommerfe 		ASSERT(diff > 0 ? child == 1 : child == 0);
612*2010Ssommerfe #endif
6130Sstevel@tonic-gate 	}
6140Sstevel@tonic-gate 	ASSERT(node->avl_child[child] == NULL);
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	avl_insert(tree, new_data, AVL_MKINDEX(node, child));
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate /*
620789Sahrens  * Add a new node to an AVL tree.
621789Sahrens  */
622789Sahrens void
623789Sahrens avl_add(avl_tree_t *tree, void *new_node)
624789Sahrens {
625789Sahrens 	avl_index_t where;
626789Sahrens 
627789Sahrens 	/*
628789Sahrens 	 * This is unfortunate.  We want to call panic() here, even for
629789Sahrens 	 * non-DEBUG kernels.  In userland, however, we can't depend on anything
630789Sahrens 	 * in libc or else the rtld build process gets confused.  So, all we can
631789Sahrens 	 * do in userland is resort to a normal ASSERT().
632789Sahrens 	 */
633789Sahrens 	if (avl_find(tree, new_node, &where) != NULL)
634789Sahrens #ifdef _KERNEL
635789Sahrens 		panic("avl_find() succeeded inside avl_add()");
636789Sahrens #else
637789Sahrens 		ASSERT(0);
638789Sahrens #endif
639789Sahrens 	avl_insert(tree, new_node, where);
640789Sahrens }
641789Sahrens 
642789Sahrens /*
6430Sstevel@tonic-gate  * Delete a node from the AVL tree.  Deletion is similar to insertion, but
6440Sstevel@tonic-gate  * with 2 complications.
6450Sstevel@tonic-gate  *
6460Sstevel@tonic-gate  * First, we may be deleting an interior node. Consider the following subtree:
6470Sstevel@tonic-gate  *
6480Sstevel@tonic-gate  *     d           c            c
6490Sstevel@tonic-gate  *    / \         / \          / \
6500Sstevel@tonic-gate  *   b   e       b   e        b   e
6510Sstevel@tonic-gate  *  / \	        / \          /
6520Sstevel@tonic-gate  * a   c       a            a
6530Sstevel@tonic-gate  *
6540Sstevel@tonic-gate  * When we are deleting node (d), we find and bring up an adjacent valued leaf
6550Sstevel@tonic-gate  * node, say (c), to take the interior node's place. In the code this is
6560Sstevel@tonic-gate  * handled by temporarily swapping (d) and (c) in the tree and then using
6570Sstevel@tonic-gate  * common code to delete (d) from the leaf position.
6580Sstevel@tonic-gate  *
6590Sstevel@tonic-gate  * Secondly, an interior deletion from a deep tree may require more than one
6600Sstevel@tonic-gate  * rotation to fix the balance. This is handled by moving up the tree through
6610Sstevel@tonic-gate  * parents and applying rotations as needed. The return value from
6620Sstevel@tonic-gate  * avl_rotation() is used to detect when a subtree did not change overall
6630Sstevel@tonic-gate  * height due to a rotation.
6640Sstevel@tonic-gate  */
6650Sstevel@tonic-gate void
6660Sstevel@tonic-gate avl_remove(avl_tree_t *tree, void *data)
6670Sstevel@tonic-gate {
6680Sstevel@tonic-gate 	avl_node_t *delete;
6690Sstevel@tonic-gate 	avl_node_t *parent;
6700Sstevel@tonic-gate 	avl_node_t *node;
6710Sstevel@tonic-gate 	avl_node_t tmp;
6720Sstevel@tonic-gate 	int old_balance;
6730Sstevel@tonic-gate 	int new_balance;
6740Sstevel@tonic-gate 	int left;
6750Sstevel@tonic-gate 	int right;
6760Sstevel@tonic-gate 	int which_child;
6770Sstevel@tonic-gate 	size_t off = tree->avl_offset;
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	ASSERT(tree);
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 	delete = AVL_DATA2NODE(data, off);
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 	/*
6840Sstevel@tonic-gate 	 * Deletion is easiest with a node that has at most 1 child.
6850Sstevel@tonic-gate 	 * We swap a node with 2 children with a sequentially valued
6860Sstevel@tonic-gate 	 * neighbor node. That node will have at most 1 child. Note this
6870Sstevel@tonic-gate 	 * has no effect on the ordering of the remaining nodes.
6880Sstevel@tonic-gate 	 *
6890Sstevel@tonic-gate 	 * As an optimization, we choose the greater neighbor if the tree
6900Sstevel@tonic-gate 	 * is right heavy, otherwise the left neighbor. This reduces the
6910Sstevel@tonic-gate 	 * number of rotations needed.
6920Sstevel@tonic-gate 	 */
6930Sstevel@tonic-gate 	if (delete->avl_child[0] != NULL && delete->avl_child[1] != NULL) {
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate 		/*
6960Sstevel@tonic-gate 		 * choose node to swap from whichever side is taller
6970Sstevel@tonic-gate 		 */
6980Sstevel@tonic-gate 		old_balance = AVL_XBALANCE(delete);
6990Sstevel@tonic-gate 		left = avl_balance2child[old_balance + 1];
7000Sstevel@tonic-gate 		right = 1 - left;
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 		/*
7030Sstevel@tonic-gate 		 * get to the previous value'd node
7040Sstevel@tonic-gate 		 * (down 1 left, as far as possible right)
7050Sstevel@tonic-gate 		 */
7060Sstevel@tonic-gate 		for (node = delete->avl_child[left];
7070Sstevel@tonic-gate 		    node->avl_child[right] != NULL;
7080Sstevel@tonic-gate 		    node = node->avl_child[right])
7090Sstevel@tonic-gate 			;
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 		/*
7120Sstevel@tonic-gate 		 * create a temp placeholder for 'node'
7130Sstevel@tonic-gate 		 * move 'node' to delete's spot in the tree
7140Sstevel@tonic-gate 		 */
7150Sstevel@tonic-gate 		tmp = *node;
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 		*node = *delete;
7180Sstevel@tonic-gate 		if (node->avl_child[left] == node)
7190Sstevel@tonic-gate 			node->avl_child[left] = &tmp;
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 		parent = AVL_XPARENT(node);
7220Sstevel@tonic-gate 		if (parent != NULL)
7230Sstevel@tonic-gate 			parent->avl_child[AVL_XCHILD(node)] = node;
7240Sstevel@tonic-gate 		else
7250Sstevel@tonic-gate 			tree->avl_root = node;
7260Sstevel@tonic-gate 		AVL_SETPARENT(node->avl_child[left], node);
7270Sstevel@tonic-gate 		AVL_SETPARENT(node->avl_child[right], node);
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate 		/*
7300Sstevel@tonic-gate 		 * Put tmp where node used to be (just temporary).
7310Sstevel@tonic-gate 		 * It always has a parent and at most 1 child.
7320Sstevel@tonic-gate 		 */
7330Sstevel@tonic-gate 		delete = &tmp;
7340Sstevel@tonic-gate 		parent = AVL_XPARENT(delete);
7350Sstevel@tonic-gate 		parent->avl_child[AVL_XCHILD(delete)] = delete;
7360Sstevel@tonic-gate 		which_child = (delete->avl_child[1] != 0);
7370Sstevel@tonic-gate 		if (delete->avl_child[which_child] != NULL)
7380Sstevel@tonic-gate 			AVL_SETPARENT(delete->avl_child[which_child], delete);
7390Sstevel@tonic-gate 	}
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	/*
7430Sstevel@tonic-gate 	 * Here we know "delete" is at least partially a leaf node. It can
7440Sstevel@tonic-gate 	 * be easily removed from the tree.
7450Sstevel@tonic-gate 	 */
746*2010Ssommerfe 	ASSERT(tree->avl_numnodes > 0);
7470Sstevel@tonic-gate 	--tree->avl_numnodes;
7480Sstevel@tonic-gate 	parent = AVL_XPARENT(delete);
7490Sstevel@tonic-gate 	which_child = AVL_XCHILD(delete);
7500Sstevel@tonic-gate 	if (delete->avl_child[0] != NULL)
7510Sstevel@tonic-gate 		node = delete->avl_child[0];
7520Sstevel@tonic-gate 	else
7530Sstevel@tonic-gate 		node = delete->avl_child[1];
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 	/*
7560Sstevel@tonic-gate 	 * Connect parent directly to node (leaving out delete).
7570Sstevel@tonic-gate 	 */
7580Sstevel@tonic-gate 	if (node != NULL) {
7590Sstevel@tonic-gate 		AVL_SETPARENT(node, parent);
7600Sstevel@tonic-gate 		AVL_SETCHILD(node, which_child);
7610Sstevel@tonic-gate 	}
7620Sstevel@tonic-gate 	if (parent == NULL) {
7630Sstevel@tonic-gate 		tree->avl_root = node;
7640Sstevel@tonic-gate 		return;
7650Sstevel@tonic-gate 	}
7660Sstevel@tonic-gate 	parent->avl_child[which_child] = node;
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate 	/*
7700Sstevel@tonic-gate 	 * Since the subtree is now shorter, begin adjusting parent balances
7710Sstevel@tonic-gate 	 * and performing any needed rotations.
7720Sstevel@tonic-gate 	 */
7730Sstevel@tonic-gate 	do {
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 		/*
7760Sstevel@tonic-gate 		 * Move up the tree and adjust the balance
7770Sstevel@tonic-gate 		 *
7780Sstevel@tonic-gate 		 * Capture the parent and which_child values for the next
7790Sstevel@tonic-gate 		 * iteration before any rotations occur.
7800Sstevel@tonic-gate 		 */
7810Sstevel@tonic-gate 		node = parent;
7820Sstevel@tonic-gate 		old_balance = AVL_XBALANCE(node);
7830Sstevel@tonic-gate 		new_balance = old_balance - avl_child2balance[which_child];
7840Sstevel@tonic-gate 		parent = AVL_XPARENT(node);
7850Sstevel@tonic-gate 		which_child = AVL_XCHILD(node);
7860Sstevel@tonic-gate 
7870Sstevel@tonic-gate 		/*
7880Sstevel@tonic-gate 		 * If a node was in perfect balance but isn't anymore then
7890Sstevel@tonic-gate 		 * we can stop, since the height didn't change above this point
7900Sstevel@tonic-gate 		 * due to a deletion.
7910Sstevel@tonic-gate 		 */
7920Sstevel@tonic-gate 		if (old_balance == 0) {
7930Sstevel@tonic-gate 			AVL_SETBALANCE(node, new_balance);
7940Sstevel@tonic-gate 			break;
7950Sstevel@tonic-gate 		}
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 		/*
7980Sstevel@tonic-gate 		 * If the new balance is zero, we don't need to rotate
7990Sstevel@tonic-gate 		 * else
8000Sstevel@tonic-gate 		 * need a rotation to fix the balance.
8010Sstevel@tonic-gate 		 * If the rotation doesn't change the height
8020Sstevel@tonic-gate 		 * of the sub-tree we have finished adjusting.
8030Sstevel@tonic-gate 		 */
8040Sstevel@tonic-gate 		if (new_balance == 0)
8050Sstevel@tonic-gate 			AVL_SETBALANCE(node, new_balance);
8060Sstevel@tonic-gate 		else if (!avl_rotation(tree, node, new_balance))
8070Sstevel@tonic-gate 			break;
8080Sstevel@tonic-gate 	} while (parent != NULL);
8090Sstevel@tonic-gate }
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate /*
8120Sstevel@tonic-gate  * initialize a new AVL tree
8130Sstevel@tonic-gate  */
8140Sstevel@tonic-gate void
8150Sstevel@tonic-gate avl_create(avl_tree_t *tree, int (*compar) (const void *, const void *),
8160Sstevel@tonic-gate     size_t size, size_t offset)
8170Sstevel@tonic-gate {
8180Sstevel@tonic-gate 	ASSERT(tree);
8190Sstevel@tonic-gate 	ASSERT(compar);
8200Sstevel@tonic-gate 	ASSERT(size > 0);
8210Sstevel@tonic-gate 	ASSERT(size >= offset + sizeof (avl_node_t));
8220Sstevel@tonic-gate #ifdef _LP64
8230Sstevel@tonic-gate 	ASSERT((offset & 0x7) == 0);
8240Sstevel@tonic-gate #endif
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	tree->avl_compar = compar;
8270Sstevel@tonic-gate 	tree->avl_root = NULL;
8280Sstevel@tonic-gate 	tree->avl_numnodes = 0;
8290Sstevel@tonic-gate 	tree->avl_size = size;
8300Sstevel@tonic-gate 	tree->avl_offset = offset;
8310Sstevel@tonic-gate }
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate /*
8340Sstevel@tonic-gate  * Delete a tree.
8350Sstevel@tonic-gate  */
8360Sstevel@tonic-gate /* ARGSUSED */
8370Sstevel@tonic-gate void
8380Sstevel@tonic-gate avl_destroy(avl_tree_t *tree)
8390Sstevel@tonic-gate {
8400Sstevel@tonic-gate 	ASSERT(tree);
8410Sstevel@tonic-gate 	ASSERT(tree->avl_numnodes == 0);
8420Sstevel@tonic-gate 	ASSERT(tree->avl_root == NULL);
8430Sstevel@tonic-gate }
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate /*
8470Sstevel@tonic-gate  * Return the number of nodes in an AVL tree.
8480Sstevel@tonic-gate  */
8490Sstevel@tonic-gate ulong_t
8500Sstevel@tonic-gate avl_numnodes(avl_tree_t *tree)
8510Sstevel@tonic-gate {
8520Sstevel@tonic-gate 	ASSERT(tree);
8530Sstevel@tonic-gate 	return (tree->avl_numnodes);
8540Sstevel@tonic-gate }
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate #define	CHILDBIT	(1L)
8580Sstevel@tonic-gate 
8590Sstevel@tonic-gate /*
8600Sstevel@tonic-gate  * Post-order tree walk used to visit all tree nodes and destroy the tree
8610Sstevel@tonic-gate  * in post order. This is used for destroying a tree w/o paying any cost
8620Sstevel@tonic-gate  * for rebalancing it.
8630Sstevel@tonic-gate  *
8640Sstevel@tonic-gate  * example:
8650Sstevel@tonic-gate  *
8660Sstevel@tonic-gate  *	void *cookie = NULL;
8670Sstevel@tonic-gate  *	my_data_t *node;
8680Sstevel@tonic-gate  *
8690Sstevel@tonic-gate  *	while ((node = avl_destroy_nodes(tree, &cookie)) != NULL)
8700Sstevel@tonic-gate  *		free(node);
8710Sstevel@tonic-gate  *	avl_destroy(tree);
8720Sstevel@tonic-gate  *
8730Sstevel@tonic-gate  * The cookie is really an avl_node_t to the current node's parent and
8740Sstevel@tonic-gate  * an indication of which child you looked at last.
8750Sstevel@tonic-gate  *
8760Sstevel@tonic-gate  * On input, a cookie value of CHILDBIT indicates the tree is done.
8770Sstevel@tonic-gate  */
8780Sstevel@tonic-gate void *
8790Sstevel@tonic-gate avl_destroy_nodes(avl_tree_t *tree, void **cookie)
8800Sstevel@tonic-gate {
8810Sstevel@tonic-gate 	avl_node_t	*node;
8820Sstevel@tonic-gate 	avl_node_t	*parent;
8830Sstevel@tonic-gate 	int		child;
8840Sstevel@tonic-gate 	void		*first;
8850Sstevel@tonic-gate 	size_t		off = tree->avl_offset;
8860Sstevel@tonic-gate 
8870Sstevel@tonic-gate 	/*
8880Sstevel@tonic-gate 	 * Initial calls go to the first node or it's right descendant.
8890Sstevel@tonic-gate 	 */
8900Sstevel@tonic-gate 	if (*cookie == NULL) {
8910Sstevel@tonic-gate 		first = avl_first(tree);
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate 		/*
8940Sstevel@tonic-gate 		 * deal with an empty tree
8950Sstevel@tonic-gate 		 */
8960Sstevel@tonic-gate 		if (first == NULL) {
8970Sstevel@tonic-gate 			*cookie = (void *)CHILDBIT;
8980Sstevel@tonic-gate 			return (NULL);
8990Sstevel@tonic-gate 		}
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate 		node = AVL_DATA2NODE(first, off);
9020Sstevel@tonic-gate 		parent = AVL_XPARENT(node);
9030Sstevel@tonic-gate 		goto check_right_side;
9040Sstevel@tonic-gate 	}
9050Sstevel@tonic-gate 
9060Sstevel@tonic-gate 	/*
9070Sstevel@tonic-gate 	 * If there is no parent to return to we are done.
9080Sstevel@tonic-gate 	 */
9090Sstevel@tonic-gate 	parent = (avl_node_t *)((uintptr_t)(*cookie) & ~CHILDBIT);
9100Sstevel@tonic-gate 	if (parent == NULL) {
9110Sstevel@tonic-gate 		if (tree->avl_root != NULL) {
9120Sstevel@tonic-gate 			ASSERT(tree->avl_numnodes == 1);
9130Sstevel@tonic-gate 			tree->avl_root = NULL;
9140Sstevel@tonic-gate 			tree->avl_numnodes = 0;
9150Sstevel@tonic-gate 		}
9160Sstevel@tonic-gate 		return (NULL);
9170Sstevel@tonic-gate 	}
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate 	/*
9200Sstevel@tonic-gate 	 * Remove the child pointer we just visited from the parent and tree.
9210Sstevel@tonic-gate 	 */
9220Sstevel@tonic-gate 	child = (uintptr_t)(*cookie) & CHILDBIT;
9230Sstevel@tonic-gate 	parent->avl_child[child] = NULL;
9240Sstevel@tonic-gate 	ASSERT(tree->avl_numnodes > 1);
9250Sstevel@tonic-gate 	--tree->avl_numnodes;
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate 	/*
9280Sstevel@tonic-gate 	 * If we just did a right child or there isn't one, go up to parent.
9290Sstevel@tonic-gate 	 */
9300Sstevel@tonic-gate 	if (child == 1 || parent->avl_child[1] == NULL) {
9310Sstevel@tonic-gate 		node = parent;
9320Sstevel@tonic-gate 		parent = AVL_XPARENT(parent);
9330Sstevel@tonic-gate 		goto done;
9340Sstevel@tonic-gate 	}
9350Sstevel@tonic-gate 
9360Sstevel@tonic-gate 	/*
9370Sstevel@tonic-gate 	 * Do parent's right child, then leftmost descendent.
9380Sstevel@tonic-gate 	 */
9390Sstevel@tonic-gate 	node = parent->avl_child[1];
9400Sstevel@tonic-gate 	while (node->avl_child[0] != NULL) {
9410Sstevel@tonic-gate 		parent = node;
9420Sstevel@tonic-gate 		node = node->avl_child[0];
9430Sstevel@tonic-gate 	}
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 	/*
9460Sstevel@tonic-gate 	 * If here, we moved to a left child. It may have one
9470Sstevel@tonic-gate 	 * child on the right (when balance == +1).
9480Sstevel@tonic-gate 	 */
9490Sstevel@tonic-gate check_right_side:
9500Sstevel@tonic-gate 	if (node->avl_child[1] != NULL) {
9510Sstevel@tonic-gate 		ASSERT(AVL_XBALANCE(node) == 1);
9520Sstevel@tonic-gate 		parent = node;
9530Sstevel@tonic-gate 		node = node->avl_child[1];
9540Sstevel@tonic-gate 		ASSERT(node->avl_child[0] == NULL &&
9550Sstevel@tonic-gate 		    node->avl_child[1] == NULL);
9560Sstevel@tonic-gate 	} else {
9570Sstevel@tonic-gate 		ASSERT(AVL_XBALANCE(node) <= 0);
9580Sstevel@tonic-gate 	}
9590Sstevel@tonic-gate 
9600Sstevel@tonic-gate done:
9610Sstevel@tonic-gate 	if (parent == NULL) {
9620Sstevel@tonic-gate 		*cookie = (void *)CHILDBIT;
9630Sstevel@tonic-gate 		ASSERT(node == tree->avl_root);
9640Sstevel@tonic-gate 	} else {
9650Sstevel@tonic-gate 		*cookie = (void *)((uintptr_t)parent | AVL_XCHILD(node));
9660Sstevel@tonic-gate 	}
9670Sstevel@tonic-gate 
9680Sstevel@tonic-gate 	return (AVL_NODE2DATA(node, off));
9690Sstevel@tonic-gate }
970