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
52010Ssommerfe * Common Development and Distribution License (the "License").
62010Ssommerfe * 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*10922SJeff.Bonwick@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * AVL - generic AVL tree implementation for kernel use
280Sstevel@tonic-gate *
290Sstevel@tonic-gate * A complete description of AVL trees can be found in many CS textbooks.
300Sstevel@tonic-gate *
310Sstevel@tonic-gate * Here is a very brief overview. An AVL tree is a binary search tree that is
320Sstevel@tonic-gate * almost perfectly balanced. By "almost" perfectly balanced, we mean that at
330Sstevel@tonic-gate * any given node, the left and right subtrees are allowed to differ in height
340Sstevel@tonic-gate * by at most 1 level.
350Sstevel@tonic-gate *
360Sstevel@tonic-gate * This relaxation from a perfectly balanced binary tree allows doing
370Sstevel@tonic-gate * insertion and deletion relatively efficiently. Searching the tree is
380Sstevel@tonic-gate * still a fast operation, roughly O(log(N)).
390Sstevel@tonic-gate *
400Sstevel@tonic-gate * The key to insertion and deletion is a set of tree maniuplations called
410Sstevel@tonic-gate * rotations, which bring unbalanced subtrees back into the semi-balanced state.
420Sstevel@tonic-gate *
430Sstevel@tonic-gate * This implementation of AVL trees has the following peculiarities:
440Sstevel@tonic-gate *
450Sstevel@tonic-gate * - The AVL specific data structures are physically embedded as fields
460Sstevel@tonic-gate * in the "using" data structures. To maintain generality the code
470Sstevel@tonic-gate * must constantly translate between "avl_node_t *" and containing
480Sstevel@tonic-gate * data structure "void *"s by adding/subracting the avl_offset.
490Sstevel@tonic-gate *
500Sstevel@tonic-gate * - Since the AVL data is always embedded in other structures, there is
510Sstevel@tonic-gate * no locking or memory allocation in the AVL routines. This must be
520Sstevel@tonic-gate * provided for by the enclosing data structure's semantics. Typically,
53789Sahrens * avl_insert()/_add()/_remove()/avl_insert_here() require some kind of
540Sstevel@tonic-gate * exclusive write lock. Other operations require a read lock.
550Sstevel@tonic-gate *
560Sstevel@tonic-gate * - The implementation uses iteration instead of explicit recursion,
570Sstevel@tonic-gate * since it is intended to run on limited size kernel stacks. Since
580Sstevel@tonic-gate * there is no recursion stack present to move "up" in the tree,
590Sstevel@tonic-gate * there is an explicit "parent" link in the avl_node_t.
600Sstevel@tonic-gate *
610Sstevel@tonic-gate * - The left/right children pointers of a node are in an array.
620Sstevel@tonic-gate * In the code, variables (instead of constants) are used to represent
630Sstevel@tonic-gate * left and right indices. The implementation is written as if it only
640Sstevel@tonic-gate * dealt with left handed manipulations. By changing the value assigned
650Sstevel@tonic-gate * to "left", the code also works for right handed trees. The
660Sstevel@tonic-gate * following variables/terms are frequently used:
670Sstevel@tonic-gate *
680Sstevel@tonic-gate * int left; // 0 when dealing with left children,
690Sstevel@tonic-gate * // 1 for dealing with right children
700Sstevel@tonic-gate *
710Sstevel@tonic-gate * int left_heavy; // -1 when left subtree is taller at some node,
720Sstevel@tonic-gate * // +1 when right subtree is taller
730Sstevel@tonic-gate *
740Sstevel@tonic-gate * int right; // will be the opposite of left (0 or 1)
750Sstevel@tonic-gate * int right_heavy;// will be the opposite of left_heavy (-1 or 1)
760Sstevel@tonic-gate *
770Sstevel@tonic-gate * int direction; // 0 for "<" (ie. left child); 1 for ">" (right)
780Sstevel@tonic-gate *
790Sstevel@tonic-gate * Though it is a little more confusing to read the code, the approach
800Sstevel@tonic-gate * allows using half as much code (and hence cache footprint) for tree
810Sstevel@tonic-gate * manipulations and eliminates many conditional branches.
820Sstevel@tonic-gate *
830Sstevel@tonic-gate * - The avl_index_t is an opaque "cookie" used to find nodes at or
840Sstevel@tonic-gate * adjacent to where a new value would be inserted in the tree. The value
850Sstevel@tonic-gate * is a modified "avl_node_t *". The bottom bit (normally 0 for a
860Sstevel@tonic-gate * pointer) is set to indicate if that the new node has a value greater
870Sstevel@tonic-gate * than the value of the indicated "avl_node_t *".
880Sstevel@tonic-gate */
890Sstevel@tonic-gate
900Sstevel@tonic-gate #include <sys/types.h>
910Sstevel@tonic-gate #include <sys/param.h>
920Sstevel@tonic-gate #include <sys/debug.h>
930Sstevel@tonic-gate #include <sys/avl.h>
94789Sahrens #include <sys/cmn_err.h>
950Sstevel@tonic-gate
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate * Small arrays to translate between balance (or diff) values and child indeces.
980Sstevel@tonic-gate *
990Sstevel@tonic-gate * Code that deals with binary tree data structures will randomly use
1000Sstevel@tonic-gate * left and right children when examining a tree. C "if()" statements
1010Sstevel@tonic-gate * which evaluate randomly suffer from very poor hardware branch prediction.
1020Sstevel@tonic-gate * In this code we avoid some of the branch mispredictions by using the
1030Sstevel@tonic-gate * following translation arrays. They replace random branches with an
1040Sstevel@tonic-gate * additional memory reference. Since the translation arrays are both very
1050Sstevel@tonic-gate * small the data should remain efficiently in cache.
1060Sstevel@tonic-gate */
1070Sstevel@tonic-gate static const int avl_child2balance[2] = {-1, 1};
1080Sstevel@tonic-gate static const int avl_balance2child[] = {0, 0, 1};
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate * Walk from one node to the previous valued node (ie. an infix walk
1130Sstevel@tonic-gate * towards the left). At any given node we do one of 2 things:
1140Sstevel@tonic-gate *
1150Sstevel@tonic-gate * - If there is a left child, go to it, then to it's rightmost descendant.
1160Sstevel@tonic-gate *
1170Sstevel@tonic-gate * - otherwise we return thru parent nodes until we've come from a right child.
1180Sstevel@tonic-gate *
1190Sstevel@tonic-gate * Return Value:
1200Sstevel@tonic-gate * NULL - if at the end of the nodes
1210Sstevel@tonic-gate * otherwise next node
1220Sstevel@tonic-gate */
1230Sstevel@tonic-gate void *
avl_walk(avl_tree_t * tree,void * oldnode,int left)1240Sstevel@tonic-gate avl_walk(avl_tree_t *tree, void *oldnode, int left)
1250Sstevel@tonic-gate {
1260Sstevel@tonic-gate size_t off = tree->avl_offset;
1270Sstevel@tonic-gate avl_node_t *node = AVL_DATA2NODE(oldnode, off);
1280Sstevel@tonic-gate int right = 1 - left;
1290Sstevel@tonic-gate int was_child;
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate /*
1330Sstevel@tonic-gate * nowhere to walk to if tree is empty
1340Sstevel@tonic-gate */
1350Sstevel@tonic-gate if (node == NULL)
1360Sstevel@tonic-gate return (NULL);
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate /*
1390Sstevel@tonic-gate * Visit the previous valued node. There are two possibilities:
1400Sstevel@tonic-gate *
1410Sstevel@tonic-gate * If this node has a left child, go down one left, then all
1420Sstevel@tonic-gate * the way right.
1430Sstevel@tonic-gate */
1440Sstevel@tonic-gate if (node->avl_child[left] != NULL) {
1450Sstevel@tonic-gate for (node = node->avl_child[left];
1460Sstevel@tonic-gate node->avl_child[right] != NULL;
1470Sstevel@tonic-gate node = node->avl_child[right])
1480Sstevel@tonic-gate ;
1490Sstevel@tonic-gate /*
1500Sstevel@tonic-gate * Otherwise, return thru left children as far as we can.
1510Sstevel@tonic-gate */
1520Sstevel@tonic-gate } else {
1530Sstevel@tonic-gate for (;;) {
1540Sstevel@tonic-gate was_child = AVL_XCHILD(node);
1550Sstevel@tonic-gate node = AVL_XPARENT(node);
1560Sstevel@tonic-gate if (node == NULL)
1570Sstevel@tonic-gate return (NULL);
1580Sstevel@tonic-gate if (was_child == right)
1590Sstevel@tonic-gate break;
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate return (AVL_NODE2DATA(node, off));
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate /*
1670Sstevel@tonic-gate * Return the lowest valued node in a tree or NULL.
1680Sstevel@tonic-gate * (leftmost child from root of tree)
1690Sstevel@tonic-gate */
1700Sstevel@tonic-gate void *
avl_first(avl_tree_t * tree)1710Sstevel@tonic-gate avl_first(avl_tree_t *tree)
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate avl_node_t *node;
1740Sstevel@tonic-gate avl_node_t *prev = NULL;
1750Sstevel@tonic-gate size_t off = tree->avl_offset;
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate for (node = tree->avl_root; node != NULL; node = node->avl_child[0])
1780Sstevel@tonic-gate prev = node;
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate if (prev != NULL)
1810Sstevel@tonic-gate return (AVL_NODE2DATA(prev, off));
1820Sstevel@tonic-gate return (NULL);
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate /*
1860Sstevel@tonic-gate * Return the highest valued node in a tree or NULL.
1870Sstevel@tonic-gate * (rightmost child from root of tree)
1880Sstevel@tonic-gate */
1890Sstevel@tonic-gate void *
avl_last(avl_tree_t * tree)1900Sstevel@tonic-gate avl_last(avl_tree_t *tree)
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate avl_node_t *node;
1930Sstevel@tonic-gate avl_node_t *prev = NULL;
1940Sstevel@tonic-gate size_t off = tree->avl_offset;
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate for (node = tree->avl_root; node != NULL; node = node->avl_child[1])
1970Sstevel@tonic-gate prev = node;
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate if (prev != NULL)
2000Sstevel@tonic-gate return (AVL_NODE2DATA(prev, off));
2010Sstevel@tonic-gate return (NULL);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate /*
2050Sstevel@tonic-gate * Access the node immediately before or after an insertion point.
2060Sstevel@tonic-gate *
2070Sstevel@tonic-gate * "avl_index_t" is a (avl_node_t *) with the bottom bit indicating a child
2080Sstevel@tonic-gate *
2090Sstevel@tonic-gate * Return value:
2100Sstevel@tonic-gate * NULL: no node in the given direction
2110Sstevel@tonic-gate * "void *" of the found tree node
2120Sstevel@tonic-gate */
2130Sstevel@tonic-gate void *
avl_nearest(avl_tree_t * tree,avl_index_t where,int direction)2140Sstevel@tonic-gate avl_nearest(avl_tree_t *tree, avl_index_t where, int direction)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate int child = AVL_INDEX2CHILD(where);
2170Sstevel@tonic-gate avl_node_t *node = AVL_INDEX2NODE(where);
2180Sstevel@tonic-gate void *data;
2190Sstevel@tonic-gate size_t off = tree->avl_offset;
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate if (node == NULL) {
2220Sstevel@tonic-gate ASSERT(tree->avl_root == NULL);
2230Sstevel@tonic-gate return (NULL);
2240Sstevel@tonic-gate }
2250Sstevel@tonic-gate data = AVL_NODE2DATA(node, off);
2260Sstevel@tonic-gate if (child != direction)
2270Sstevel@tonic-gate return (data);
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate return (avl_walk(tree, data, direction));
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate /*
2340Sstevel@tonic-gate * Search for the node which contains "value". The algorithm is a
2350Sstevel@tonic-gate * simple binary tree search.
2360Sstevel@tonic-gate *
2370Sstevel@tonic-gate * return value:
2380Sstevel@tonic-gate * NULL: the value is not in the AVL tree
2390Sstevel@tonic-gate * *where (if not NULL) is set to indicate the insertion point
2400Sstevel@tonic-gate * "void *" of the found tree node
2410Sstevel@tonic-gate */
2420Sstevel@tonic-gate void *
avl_find(avl_tree_t * tree,const void * value,avl_index_t * where)243*10922SJeff.Bonwick@Sun.COM avl_find(avl_tree_t *tree, const void *value, avl_index_t *where)
2440Sstevel@tonic-gate {
2450Sstevel@tonic-gate avl_node_t *node;
2460Sstevel@tonic-gate avl_node_t *prev = NULL;
2470Sstevel@tonic-gate int child = 0;
2480Sstevel@tonic-gate int diff;
2490Sstevel@tonic-gate size_t off = tree->avl_offset;
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate for (node = tree->avl_root; node != NULL;
2520Sstevel@tonic-gate node = node->avl_child[child]) {
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate prev = node;
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate diff = tree->avl_compar(value, AVL_NODE2DATA(node, off));
2570Sstevel@tonic-gate ASSERT(-1 <= diff && diff <= 1);
2580Sstevel@tonic-gate if (diff == 0) {
2590Sstevel@tonic-gate #ifdef DEBUG
2600Sstevel@tonic-gate if (where != NULL)
2612856Snd150628 *where = 0;
2620Sstevel@tonic-gate #endif
2630Sstevel@tonic-gate return (AVL_NODE2DATA(node, off));
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate child = avl_balance2child[1 + diff];
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate if (where != NULL)
2700Sstevel@tonic-gate *where = AVL_MKINDEX(prev, child);
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate return (NULL);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate * Perform a rotation to restore balance at the subtree given by depth.
2780Sstevel@tonic-gate *
2790Sstevel@tonic-gate * This routine is used by both insertion and deletion. The return value
2800Sstevel@tonic-gate * indicates:
2810Sstevel@tonic-gate * 0 : subtree did not change height
2820Sstevel@tonic-gate * !0 : subtree was reduced in height
2830Sstevel@tonic-gate *
2840Sstevel@tonic-gate * The code is written as if handling left rotations, right rotations are
2850Sstevel@tonic-gate * symmetric and handled by swapping values of variables right/left[_heavy]
2860Sstevel@tonic-gate *
2870Sstevel@tonic-gate * On input balance is the "new" balance at "node". This value is either
2880Sstevel@tonic-gate * -2 or +2.
2890Sstevel@tonic-gate */
2900Sstevel@tonic-gate static int
avl_rotation(avl_tree_t * tree,avl_node_t * node,int balance)2910Sstevel@tonic-gate avl_rotation(avl_tree_t *tree, avl_node_t *node, int balance)
2920Sstevel@tonic-gate {
2930Sstevel@tonic-gate int left = !(balance < 0); /* when balance = -2, left will be 0 */
2940Sstevel@tonic-gate int right = 1 - left;
2950Sstevel@tonic-gate int left_heavy = balance >> 1;
2960Sstevel@tonic-gate int right_heavy = -left_heavy;
2970Sstevel@tonic-gate avl_node_t *parent = AVL_XPARENT(node);
2980Sstevel@tonic-gate avl_node_t *child = node->avl_child[left];
2990Sstevel@tonic-gate avl_node_t *cright;
3000Sstevel@tonic-gate avl_node_t *gchild;
3010Sstevel@tonic-gate avl_node_t *gright;
3020Sstevel@tonic-gate avl_node_t *gleft;
3030Sstevel@tonic-gate int which_child = AVL_XCHILD(node);
3040Sstevel@tonic-gate int child_bal = AVL_XBALANCE(child);
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate /* BEGIN CSTYLED */
3070Sstevel@tonic-gate /*
3080Sstevel@tonic-gate * case 1 : node is overly left heavy, the left child is balanced or
3090Sstevel@tonic-gate * also left heavy. This requires the following rotation.
3100Sstevel@tonic-gate *
3110Sstevel@tonic-gate * (node bal:-2)
3120Sstevel@tonic-gate * / \
3130Sstevel@tonic-gate * / \
3140Sstevel@tonic-gate * (child bal:0 or -1)
3150Sstevel@tonic-gate * / \
3160Sstevel@tonic-gate * / \
3170Sstevel@tonic-gate * cright
3180Sstevel@tonic-gate *
3190Sstevel@tonic-gate * becomes:
3200Sstevel@tonic-gate *
3210Sstevel@tonic-gate * (child bal:1 or 0)
3220Sstevel@tonic-gate * / \
3230Sstevel@tonic-gate * / \
3240Sstevel@tonic-gate * (node bal:-1 or 0)
3250Sstevel@tonic-gate * / \
3260Sstevel@tonic-gate * / \
3270Sstevel@tonic-gate * cright
3280Sstevel@tonic-gate *
3290Sstevel@tonic-gate * we detect this situation by noting that child's balance is not
3300Sstevel@tonic-gate * right_heavy.
3310Sstevel@tonic-gate */
3320Sstevel@tonic-gate /* END CSTYLED */
3330Sstevel@tonic-gate if (child_bal != right_heavy) {
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate /*
3360Sstevel@tonic-gate * compute new balance of nodes
3370Sstevel@tonic-gate *
3380Sstevel@tonic-gate * If child used to be left heavy (now balanced) we reduced
3390Sstevel@tonic-gate * the height of this sub-tree -- used in "return...;" below
3400Sstevel@tonic-gate */
3410Sstevel@tonic-gate child_bal += right_heavy; /* adjust towards right */
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate /*
3440Sstevel@tonic-gate * move "cright" to be node's left child
3450Sstevel@tonic-gate */
3460Sstevel@tonic-gate cright = child->avl_child[right];
3470Sstevel@tonic-gate node->avl_child[left] = cright;
3480Sstevel@tonic-gate if (cright != NULL) {
3490Sstevel@tonic-gate AVL_SETPARENT(cright, node);
3500Sstevel@tonic-gate AVL_SETCHILD(cright, left);
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate /*
3540Sstevel@tonic-gate * move node to be child's right child
3550Sstevel@tonic-gate */
3560Sstevel@tonic-gate child->avl_child[right] = node;
3570Sstevel@tonic-gate AVL_SETBALANCE(node, -child_bal);
3580Sstevel@tonic-gate AVL_SETCHILD(node, right);
3590Sstevel@tonic-gate AVL_SETPARENT(node, child);
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate /*
3620Sstevel@tonic-gate * update the pointer into this subtree
3630Sstevel@tonic-gate */
3640Sstevel@tonic-gate AVL_SETBALANCE(child, child_bal);
3650Sstevel@tonic-gate AVL_SETCHILD(child, which_child);
3660Sstevel@tonic-gate AVL_SETPARENT(child, parent);
3670Sstevel@tonic-gate if (parent != NULL)
3680Sstevel@tonic-gate parent->avl_child[which_child] = child;
3690Sstevel@tonic-gate else
3700Sstevel@tonic-gate tree->avl_root = child;
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate return (child_bal == 0);
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate /* BEGIN CSTYLED */
3760Sstevel@tonic-gate /*
3770Sstevel@tonic-gate * case 2 : When node is left heavy, but child is right heavy we use
3780Sstevel@tonic-gate * a different rotation.
3790Sstevel@tonic-gate *
3800Sstevel@tonic-gate * (node b:-2)
3810Sstevel@tonic-gate * / \
3820Sstevel@tonic-gate * / \
3830Sstevel@tonic-gate * / \
3840Sstevel@tonic-gate * (child b:+1)
3850Sstevel@tonic-gate * / \
3860Sstevel@tonic-gate * / \
3870Sstevel@tonic-gate * (gchild b: != 0)
3880Sstevel@tonic-gate * / \
3890Sstevel@tonic-gate * / \
3900Sstevel@tonic-gate * gleft gright
3910Sstevel@tonic-gate *
3920Sstevel@tonic-gate * becomes:
3930Sstevel@tonic-gate *
3940Sstevel@tonic-gate * (gchild b:0)
3950Sstevel@tonic-gate * / \
3960Sstevel@tonic-gate * / \
3970Sstevel@tonic-gate * / \
3980Sstevel@tonic-gate * (child b:?) (node b:?)
3990Sstevel@tonic-gate * / \ / \
4000Sstevel@tonic-gate * / \ / \
4010Sstevel@tonic-gate * gleft gright
4020Sstevel@tonic-gate *
4030Sstevel@tonic-gate * computing the new balances is more complicated. As an example:
4040Sstevel@tonic-gate * if gchild was right_heavy, then child is now left heavy
4050Sstevel@tonic-gate * else it is balanced
4060Sstevel@tonic-gate */
4070Sstevel@tonic-gate /* END CSTYLED */
4080Sstevel@tonic-gate gchild = child->avl_child[right];
4090Sstevel@tonic-gate gleft = gchild->avl_child[left];
4100Sstevel@tonic-gate gright = gchild->avl_child[right];
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate /*
4130Sstevel@tonic-gate * move gright to left child of node and
4140Sstevel@tonic-gate *
4150Sstevel@tonic-gate * move gleft to right child of node
4160Sstevel@tonic-gate */
4170Sstevel@tonic-gate node->avl_child[left] = gright;
4180Sstevel@tonic-gate if (gright != NULL) {
4190Sstevel@tonic-gate AVL_SETPARENT(gright, node);
4200Sstevel@tonic-gate AVL_SETCHILD(gright, left);
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate child->avl_child[right] = gleft;
4240Sstevel@tonic-gate if (gleft != NULL) {
4250Sstevel@tonic-gate AVL_SETPARENT(gleft, child);
4260Sstevel@tonic-gate AVL_SETCHILD(gleft, right);
4270Sstevel@tonic-gate }
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate /*
4300Sstevel@tonic-gate * move child to left child of gchild and
4310Sstevel@tonic-gate *
4320Sstevel@tonic-gate * move node to right child of gchild and
4330Sstevel@tonic-gate *
4340Sstevel@tonic-gate * fixup parent of all this to point to gchild
4350Sstevel@tonic-gate */
4360Sstevel@tonic-gate balance = AVL_XBALANCE(gchild);
4370Sstevel@tonic-gate gchild->avl_child[left] = child;
4380Sstevel@tonic-gate AVL_SETBALANCE(child, (balance == right_heavy ? left_heavy : 0));
4390Sstevel@tonic-gate AVL_SETPARENT(child, gchild);
4400Sstevel@tonic-gate AVL_SETCHILD(child, left);
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate gchild->avl_child[right] = node;
4430Sstevel@tonic-gate AVL_SETBALANCE(node, (balance == left_heavy ? right_heavy : 0));
4440Sstevel@tonic-gate AVL_SETPARENT(node, gchild);
4450Sstevel@tonic-gate AVL_SETCHILD(node, right);
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate AVL_SETBALANCE(gchild, 0);
4480Sstevel@tonic-gate AVL_SETPARENT(gchild, parent);
4490Sstevel@tonic-gate AVL_SETCHILD(gchild, which_child);
4500Sstevel@tonic-gate if (parent != NULL)
4510Sstevel@tonic-gate parent->avl_child[which_child] = gchild;
4520Sstevel@tonic-gate else
4530Sstevel@tonic-gate tree->avl_root = gchild;
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate return (1); /* the new tree is always shorter */
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate /*
4600Sstevel@tonic-gate * Insert a new node into an AVL tree at the specified (from avl_find()) place.
4610Sstevel@tonic-gate *
4620Sstevel@tonic-gate * Newly inserted nodes are always leaf nodes in the tree, since avl_find()
4630Sstevel@tonic-gate * searches out to the leaf positions. The avl_index_t indicates the node
4640Sstevel@tonic-gate * which will be the parent of the new node.
4650Sstevel@tonic-gate *
4660Sstevel@tonic-gate * After the node is inserted, a single rotation further up the tree may
4670Sstevel@tonic-gate * be necessary to maintain an acceptable AVL balance.
4680Sstevel@tonic-gate */
4690Sstevel@tonic-gate void
avl_insert(avl_tree_t * tree,void * new_data,avl_index_t where)4700Sstevel@tonic-gate avl_insert(avl_tree_t *tree, void *new_data, avl_index_t where)
4710Sstevel@tonic-gate {
4720Sstevel@tonic-gate avl_node_t *node;
4730Sstevel@tonic-gate avl_node_t *parent = AVL_INDEX2NODE(where);
4740Sstevel@tonic-gate int old_balance;
4750Sstevel@tonic-gate int new_balance;
4760Sstevel@tonic-gate int which_child = AVL_INDEX2CHILD(where);
4770Sstevel@tonic-gate size_t off = tree->avl_offset;
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate ASSERT(tree);
4800Sstevel@tonic-gate #ifdef _LP64
4810Sstevel@tonic-gate ASSERT(((uintptr_t)new_data & 0x7) == 0);
4820Sstevel@tonic-gate #endif
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate node = AVL_DATA2NODE(new_data, off);
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate /*
4870Sstevel@tonic-gate * First, add the node to the tree at the indicated position.
4880Sstevel@tonic-gate */
4890Sstevel@tonic-gate ++tree->avl_numnodes;
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate node->avl_child[0] = NULL;
4920Sstevel@tonic-gate node->avl_child[1] = NULL;
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate AVL_SETCHILD(node, which_child);
4950Sstevel@tonic-gate AVL_SETBALANCE(node, 0);
4960Sstevel@tonic-gate AVL_SETPARENT(node, parent);
4970Sstevel@tonic-gate if (parent != NULL) {
4980Sstevel@tonic-gate ASSERT(parent->avl_child[which_child] == NULL);
4990Sstevel@tonic-gate parent->avl_child[which_child] = node;
5000Sstevel@tonic-gate } else {
5010Sstevel@tonic-gate ASSERT(tree->avl_root == NULL);
5020Sstevel@tonic-gate tree->avl_root = node;
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate /*
5050Sstevel@tonic-gate * Now, back up the tree modifying the balance of all nodes above the
5060Sstevel@tonic-gate * insertion point. If we get to a highly unbalanced ancestor, we
5070Sstevel@tonic-gate * need to do a rotation. If we back out of the tree we are done.
5080Sstevel@tonic-gate * If we brought any subtree into perfect balance (0), we are also done.
5090Sstevel@tonic-gate */
5100Sstevel@tonic-gate for (;;) {
5110Sstevel@tonic-gate node = parent;
5120Sstevel@tonic-gate if (node == NULL)
5130Sstevel@tonic-gate return;
5140Sstevel@tonic-gate
5150Sstevel@tonic-gate /*
5160Sstevel@tonic-gate * Compute the new balance
5170Sstevel@tonic-gate */
5180Sstevel@tonic-gate old_balance = AVL_XBALANCE(node);
5190Sstevel@tonic-gate new_balance = old_balance + avl_child2balance[which_child];
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate /*
5220Sstevel@tonic-gate * If we introduced equal balance, then we are done immediately
5230Sstevel@tonic-gate */
5240Sstevel@tonic-gate if (new_balance == 0) {
5250Sstevel@tonic-gate AVL_SETBALANCE(node, 0);
5260Sstevel@tonic-gate return;
5270Sstevel@tonic-gate }
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate /*
5300Sstevel@tonic-gate * If both old and new are not zero we went
5310Sstevel@tonic-gate * from -1 to -2 balance, do a rotation.
5320Sstevel@tonic-gate */
5330Sstevel@tonic-gate if (old_balance != 0)
5340Sstevel@tonic-gate break;
5350Sstevel@tonic-gate
5360Sstevel@tonic-gate AVL_SETBALANCE(node, new_balance);
5370Sstevel@tonic-gate parent = AVL_XPARENT(node);
5380Sstevel@tonic-gate which_child = AVL_XCHILD(node);
5390Sstevel@tonic-gate }
5400Sstevel@tonic-gate
5410Sstevel@tonic-gate /*
5420Sstevel@tonic-gate * perform a rotation to fix the tree and return
5430Sstevel@tonic-gate */
5440Sstevel@tonic-gate (void) avl_rotation(tree, node, new_balance);
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate /*
5480Sstevel@tonic-gate * Insert "new_data" in "tree" in the given "direction" either after or
5490Sstevel@tonic-gate * before (AVL_AFTER, AVL_BEFORE) the data "here".
5500Sstevel@tonic-gate *
5510Sstevel@tonic-gate * Insertions can only be done at empty leaf points in the tree, therefore
5520Sstevel@tonic-gate * if the given child of the node is already present we move to either
5530Sstevel@tonic-gate * the AVL_PREV or AVL_NEXT and reverse the insertion direction. Since
5540Sstevel@tonic-gate * every other node in the tree is a leaf, this always works.
5550Sstevel@tonic-gate *
5560Sstevel@tonic-gate * To help developers using this interface, we assert that the new node
5570Sstevel@tonic-gate * is correctly ordered at every step of the way in DEBUG kernels.
5580Sstevel@tonic-gate */
5590Sstevel@tonic-gate void
avl_insert_here(avl_tree_t * tree,void * new_data,void * here,int direction)5600Sstevel@tonic-gate avl_insert_here(
5610Sstevel@tonic-gate avl_tree_t *tree,
5620Sstevel@tonic-gate void *new_data,
5630Sstevel@tonic-gate void *here,
5640Sstevel@tonic-gate int direction)
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate avl_node_t *node;
5670Sstevel@tonic-gate int child = direction; /* rely on AVL_BEFORE == 0, AVL_AFTER == 1 */
5682010Ssommerfe #ifdef DEBUG
5692010Ssommerfe int diff;
5702010Ssommerfe #endif
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate ASSERT(tree != NULL);
5730Sstevel@tonic-gate ASSERT(new_data != NULL);
5740Sstevel@tonic-gate ASSERT(here != NULL);
5750Sstevel@tonic-gate ASSERT(direction == AVL_BEFORE || direction == AVL_AFTER);
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate /*
5780Sstevel@tonic-gate * If corresponding child of node is not NULL, go to the neighboring
5790Sstevel@tonic-gate * node and reverse the insertion direction.
5800Sstevel@tonic-gate */
5810Sstevel@tonic-gate node = AVL_DATA2NODE(here, tree->avl_offset);
5822010Ssommerfe
5832010Ssommerfe #ifdef DEBUG
5842010Ssommerfe diff = tree->avl_compar(new_data, here);
5852010Ssommerfe ASSERT(-1 <= diff && diff <= 1);
5862010Ssommerfe ASSERT(diff != 0);
5872010Ssommerfe ASSERT(diff > 0 ? child == 1 : child == 0);
5882010Ssommerfe #endif
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate if (node->avl_child[child] != NULL) {
5910Sstevel@tonic-gate node = node->avl_child[child];
5920Sstevel@tonic-gate child = 1 - child;
5930Sstevel@tonic-gate while (node->avl_child[child] != NULL) {
5942010Ssommerfe #ifdef DEBUG
5952010Ssommerfe diff = tree->avl_compar(new_data,
5962010Ssommerfe AVL_NODE2DATA(node, tree->avl_offset));
5972010Ssommerfe ASSERT(-1 <= diff && diff <= 1);
5982010Ssommerfe ASSERT(diff != 0);
5992010Ssommerfe ASSERT(diff > 0 ? child == 1 : child == 0);
6002010Ssommerfe #endif
6010Sstevel@tonic-gate node = node->avl_child[child];
6020Sstevel@tonic-gate }
6032010Ssommerfe #ifdef DEBUG
6042010Ssommerfe diff = tree->avl_compar(new_data,
6052010Ssommerfe AVL_NODE2DATA(node, tree->avl_offset));
6062010Ssommerfe ASSERT(-1 <= diff && diff <= 1);
6072010Ssommerfe ASSERT(diff != 0);
6082010Ssommerfe ASSERT(diff > 0 ? child == 1 : child == 0);
6092010Ssommerfe #endif
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate ASSERT(node->avl_child[child] == NULL);
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate avl_insert(tree, new_data, AVL_MKINDEX(node, child));
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate
6160Sstevel@tonic-gate /*
617789Sahrens * Add a new node to an AVL tree.
618789Sahrens */
619789Sahrens void
avl_add(avl_tree_t * tree,void * new_node)620789Sahrens avl_add(avl_tree_t *tree, void *new_node)
621789Sahrens {
622789Sahrens avl_index_t where;
623789Sahrens
624789Sahrens /*
625789Sahrens * This is unfortunate. We want to call panic() here, even for
626789Sahrens * non-DEBUG kernels. In userland, however, we can't depend on anything
627789Sahrens * in libc or else the rtld build process gets confused. So, all we can
628789Sahrens * do in userland is resort to a normal ASSERT().
629789Sahrens */
630789Sahrens if (avl_find(tree, new_node, &where) != NULL)
631789Sahrens #ifdef _KERNEL
632789Sahrens panic("avl_find() succeeded inside avl_add()");
633789Sahrens #else
634789Sahrens ASSERT(0);
635789Sahrens #endif
636789Sahrens avl_insert(tree, new_node, where);
637789Sahrens }
638789Sahrens
639789Sahrens /*
6400Sstevel@tonic-gate * Delete a node from the AVL tree. Deletion is similar to insertion, but
6410Sstevel@tonic-gate * with 2 complications.
6420Sstevel@tonic-gate *
6430Sstevel@tonic-gate * First, we may be deleting an interior node. Consider the following subtree:
6440Sstevel@tonic-gate *
6450Sstevel@tonic-gate * d c c
6460Sstevel@tonic-gate * / \ / \ / \
6470Sstevel@tonic-gate * b e b e b e
6480Sstevel@tonic-gate * / \ / \ /
6490Sstevel@tonic-gate * a c a a
6500Sstevel@tonic-gate *
6510Sstevel@tonic-gate * When we are deleting node (d), we find and bring up an adjacent valued leaf
6520Sstevel@tonic-gate * node, say (c), to take the interior node's place. In the code this is
6530Sstevel@tonic-gate * handled by temporarily swapping (d) and (c) in the tree and then using
6540Sstevel@tonic-gate * common code to delete (d) from the leaf position.
6550Sstevel@tonic-gate *
6560Sstevel@tonic-gate * Secondly, an interior deletion from a deep tree may require more than one
6570Sstevel@tonic-gate * rotation to fix the balance. This is handled by moving up the tree through
6580Sstevel@tonic-gate * parents and applying rotations as needed. The return value from
6590Sstevel@tonic-gate * avl_rotation() is used to detect when a subtree did not change overall
6600Sstevel@tonic-gate * height due to a rotation.
6610Sstevel@tonic-gate */
6620Sstevel@tonic-gate void
avl_remove(avl_tree_t * tree,void * data)6630Sstevel@tonic-gate avl_remove(avl_tree_t *tree, void *data)
6640Sstevel@tonic-gate {
6650Sstevel@tonic-gate avl_node_t *delete;
6660Sstevel@tonic-gate avl_node_t *parent;
6670Sstevel@tonic-gate avl_node_t *node;
6680Sstevel@tonic-gate avl_node_t tmp;
6690Sstevel@tonic-gate int old_balance;
6700Sstevel@tonic-gate int new_balance;
6710Sstevel@tonic-gate int left;
6720Sstevel@tonic-gate int right;
6730Sstevel@tonic-gate int which_child;
6740Sstevel@tonic-gate size_t off = tree->avl_offset;
6750Sstevel@tonic-gate
6760Sstevel@tonic-gate ASSERT(tree);
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate delete = AVL_DATA2NODE(data, off);
6790Sstevel@tonic-gate
6800Sstevel@tonic-gate /*
6810Sstevel@tonic-gate * Deletion is easiest with a node that has at most 1 child.
6820Sstevel@tonic-gate * We swap a node with 2 children with a sequentially valued
6830Sstevel@tonic-gate * neighbor node. That node will have at most 1 child. Note this
6840Sstevel@tonic-gate * has no effect on the ordering of the remaining nodes.
6850Sstevel@tonic-gate *
6860Sstevel@tonic-gate * As an optimization, we choose the greater neighbor if the tree
6870Sstevel@tonic-gate * is right heavy, otherwise the left neighbor. This reduces the
6880Sstevel@tonic-gate * number of rotations needed.
6890Sstevel@tonic-gate */
6900Sstevel@tonic-gate if (delete->avl_child[0] != NULL && delete->avl_child[1] != NULL) {
6910Sstevel@tonic-gate
6920Sstevel@tonic-gate /*
6930Sstevel@tonic-gate * choose node to swap from whichever side is taller
6940Sstevel@tonic-gate */
6950Sstevel@tonic-gate old_balance = AVL_XBALANCE(delete);
6960Sstevel@tonic-gate left = avl_balance2child[old_balance + 1];
6970Sstevel@tonic-gate right = 1 - left;
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate /*
7000Sstevel@tonic-gate * get to the previous value'd node
7010Sstevel@tonic-gate * (down 1 left, as far as possible right)
7020Sstevel@tonic-gate */
7030Sstevel@tonic-gate for (node = delete->avl_child[left];
7040Sstevel@tonic-gate node->avl_child[right] != NULL;
7050Sstevel@tonic-gate node = node->avl_child[right])
7060Sstevel@tonic-gate ;
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate /*
7090Sstevel@tonic-gate * create a temp placeholder for 'node'
7100Sstevel@tonic-gate * move 'node' to delete's spot in the tree
7110Sstevel@tonic-gate */
7120Sstevel@tonic-gate tmp = *node;
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate *node = *delete;
7150Sstevel@tonic-gate if (node->avl_child[left] == node)
7160Sstevel@tonic-gate node->avl_child[left] = &tmp;
7170Sstevel@tonic-gate
7180Sstevel@tonic-gate parent = AVL_XPARENT(node);
7190Sstevel@tonic-gate if (parent != NULL)
7200Sstevel@tonic-gate parent->avl_child[AVL_XCHILD(node)] = node;
7210Sstevel@tonic-gate else
7220Sstevel@tonic-gate tree->avl_root = node;
7230Sstevel@tonic-gate AVL_SETPARENT(node->avl_child[left], node);
7240Sstevel@tonic-gate AVL_SETPARENT(node->avl_child[right], node);
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate /*
7270Sstevel@tonic-gate * Put tmp where node used to be (just temporary).
7280Sstevel@tonic-gate * It always has a parent and at most 1 child.
7290Sstevel@tonic-gate */
7300Sstevel@tonic-gate delete = &tmp;
7310Sstevel@tonic-gate parent = AVL_XPARENT(delete);
7320Sstevel@tonic-gate parent->avl_child[AVL_XCHILD(delete)] = delete;
7330Sstevel@tonic-gate which_child = (delete->avl_child[1] != 0);
7340Sstevel@tonic-gate if (delete->avl_child[which_child] != NULL)
7350Sstevel@tonic-gate AVL_SETPARENT(delete->avl_child[which_child], delete);
7360Sstevel@tonic-gate }
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate
7390Sstevel@tonic-gate /*
7400Sstevel@tonic-gate * Here we know "delete" is at least partially a leaf node. It can
7410Sstevel@tonic-gate * be easily removed from the tree.
7420Sstevel@tonic-gate */
7432010Ssommerfe ASSERT(tree->avl_numnodes > 0);
7440Sstevel@tonic-gate --tree->avl_numnodes;
7450Sstevel@tonic-gate parent = AVL_XPARENT(delete);
7460Sstevel@tonic-gate which_child = AVL_XCHILD(delete);
7470Sstevel@tonic-gate if (delete->avl_child[0] != NULL)
7480Sstevel@tonic-gate node = delete->avl_child[0];
7490Sstevel@tonic-gate else
7500Sstevel@tonic-gate node = delete->avl_child[1];
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate /*
7530Sstevel@tonic-gate * Connect parent directly to node (leaving out delete).
7540Sstevel@tonic-gate */
7550Sstevel@tonic-gate if (node != NULL) {
7560Sstevel@tonic-gate AVL_SETPARENT(node, parent);
7570Sstevel@tonic-gate AVL_SETCHILD(node, which_child);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate if (parent == NULL) {
7600Sstevel@tonic-gate tree->avl_root = node;
7610Sstevel@tonic-gate return;
7620Sstevel@tonic-gate }
7630Sstevel@tonic-gate parent->avl_child[which_child] = node;
7640Sstevel@tonic-gate
7650Sstevel@tonic-gate
7660Sstevel@tonic-gate /*
7670Sstevel@tonic-gate * Since the subtree is now shorter, begin adjusting parent balances
7680Sstevel@tonic-gate * and performing any needed rotations.
7690Sstevel@tonic-gate */
7700Sstevel@tonic-gate do {
7710Sstevel@tonic-gate
7720Sstevel@tonic-gate /*
7730Sstevel@tonic-gate * Move up the tree and adjust the balance
7740Sstevel@tonic-gate *
7750Sstevel@tonic-gate * Capture the parent and which_child values for the next
7760Sstevel@tonic-gate * iteration before any rotations occur.
7770Sstevel@tonic-gate */
7780Sstevel@tonic-gate node = parent;
7790Sstevel@tonic-gate old_balance = AVL_XBALANCE(node);
7800Sstevel@tonic-gate new_balance = old_balance - avl_child2balance[which_child];
7810Sstevel@tonic-gate parent = AVL_XPARENT(node);
7820Sstevel@tonic-gate which_child = AVL_XCHILD(node);
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate /*
7850Sstevel@tonic-gate * If a node was in perfect balance but isn't anymore then
7860Sstevel@tonic-gate * we can stop, since the height didn't change above this point
7870Sstevel@tonic-gate * due to a deletion.
7880Sstevel@tonic-gate */
7890Sstevel@tonic-gate if (old_balance == 0) {
7900Sstevel@tonic-gate AVL_SETBALANCE(node, new_balance);
7910Sstevel@tonic-gate break;
7920Sstevel@tonic-gate }
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate /*
7950Sstevel@tonic-gate * If the new balance is zero, we don't need to rotate
7960Sstevel@tonic-gate * else
7970Sstevel@tonic-gate * need a rotation to fix the balance.
7980Sstevel@tonic-gate * If the rotation doesn't change the height
7990Sstevel@tonic-gate * of the sub-tree we have finished adjusting.
8000Sstevel@tonic-gate */
8010Sstevel@tonic-gate if (new_balance == 0)
8020Sstevel@tonic-gate AVL_SETBALANCE(node, new_balance);
8030Sstevel@tonic-gate else if (!avl_rotation(tree, node, new_balance))
8040Sstevel@tonic-gate break;
8050Sstevel@tonic-gate } while (parent != NULL);
8060Sstevel@tonic-gate }
8070Sstevel@tonic-gate
8086712Stomee #define AVL_REINSERT(tree, obj) \
8096712Stomee avl_remove((tree), (obj)); \
8106712Stomee avl_add((tree), (obj))
8116712Stomee
8126712Stomee boolean_t
avl_update_lt(avl_tree_t * t,void * obj)8136712Stomee avl_update_lt(avl_tree_t *t, void *obj)
8146712Stomee {
8156712Stomee void *neighbor;
8166712Stomee
8176712Stomee ASSERT(((neighbor = AVL_NEXT(t, obj)) == NULL) ||
8186712Stomee (t->avl_compar(obj, neighbor) <= 0));
8196712Stomee
8206712Stomee neighbor = AVL_PREV(t, obj);
8216712Stomee if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) < 0)) {
8226712Stomee AVL_REINSERT(t, obj);
8236712Stomee return (B_TRUE);
8246712Stomee }
8256712Stomee
8266712Stomee return (B_FALSE);
8276712Stomee }
8286712Stomee
8296712Stomee boolean_t
avl_update_gt(avl_tree_t * t,void * obj)8306712Stomee avl_update_gt(avl_tree_t *t, void *obj)
8316712Stomee {
8326712Stomee void *neighbor;
8336712Stomee
8346712Stomee ASSERT(((neighbor = AVL_PREV(t, obj)) == NULL) ||
8356712Stomee (t->avl_compar(obj, neighbor) >= 0));
8366712Stomee
8376712Stomee neighbor = AVL_NEXT(t, obj);
8386712Stomee if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) > 0)) {
8396712Stomee AVL_REINSERT(t, obj);
8406712Stomee return (B_TRUE);
8416712Stomee }
8426712Stomee
8436712Stomee return (B_FALSE);
8446712Stomee }
8456712Stomee
8466712Stomee boolean_t
avl_update(avl_tree_t * t,void * obj)8476712Stomee avl_update(avl_tree_t *t, void *obj)
8486712Stomee {
8496712Stomee void *neighbor;
8506712Stomee
8516712Stomee neighbor = AVL_PREV(t, obj);
8526712Stomee if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) < 0)) {
8536712Stomee AVL_REINSERT(t, obj);
8546712Stomee return (B_TRUE);
8556712Stomee }
8566712Stomee
8576712Stomee neighbor = AVL_NEXT(t, obj);
8586712Stomee if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) > 0)) {
8596712Stomee AVL_REINSERT(t, obj);
8606712Stomee return (B_TRUE);
8616712Stomee }
8626712Stomee
8636712Stomee return (B_FALSE);
8646712Stomee }
8656712Stomee
8660Sstevel@tonic-gate /*
8670Sstevel@tonic-gate * initialize a new AVL tree
8680Sstevel@tonic-gate */
8690Sstevel@tonic-gate void
avl_create(avl_tree_t * tree,int (* compar)(const void *,const void *),size_t size,size_t offset)8700Sstevel@tonic-gate avl_create(avl_tree_t *tree, int (*compar) (const void *, const void *),
8710Sstevel@tonic-gate size_t size, size_t offset)
8720Sstevel@tonic-gate {
8730Sstevel@tonic-gate ASSERT(tree);
8740Sstevel@tonic-gate ASSERT(compar);
8750Sstevel@tonic-gate ASSERT(size > 0);
8760Sstevel@tonic-gate ASSERT(size >= offset + sizeof (avl_node_t));
8770Sstevel@tonic-gate #ifdef _LP64
8780Sstevel@tonic-gate ASSERT((offset & 0x7) == 0);
8790Sstevel@tonic-gate #endif
8800Sstevel@tonic-gate
8810Sstevel@tonic-gate tree->avl_compar = compar;
8820Sstevel@tonic-gate tree->avl_root = NULL;
8830Sstevel@tonic-gate tree->avl_numnodes = 0;
8840Sstevel@tonic-gate tree->avl_size = size;
8850Sstevel@tonic-gate tree->avl_offset = offset;
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate
8880Sstevel@tonic-gate /*
8890Sstevel@tonic-gate * Delete a tree.
8900Sstevel@tonic-gate */
8910Sstevel@tonic-gate /* ARGSUSED */
8920Sstevel@tonic-gate void
avl_destroy(avl_tree_t * tree)8930Sstevel@tonic-gate avl_destroy(avl_tree_t *tree)
8940Sstevel@tonic-gate {
8950Sstevel@tonic-gate ASSERT(tree);
8960Sstevel@tonic-gate ASSERT(tree->avl_numnodes == 0);
8970Sstevel@tonic-gate ASSERT(tree->avl_root == NULL);
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate /*
9020Sstevel@tonic-gate * Return the number of nodes in an AVL tree.
9030Sstevel@tonic-gate */
9040Sstevel@tonic-gate ulong_t
avl_numnodes(avl_tree_t * tree)9050Sstevel@tonic-gate avl_numnodes(avl_tree_t *tree)
9060Sstevel@tonic-gate {
9070Sstevel@tonic-gate ASSERT(tree);
9080Sstevel@tonic-gate return (tree->avl_numnodes);
9090Sstevel@tonic-gate }
9100Sstevel@tonic-gate
9116712Stomee boolean_t
avl_is_empty(avl_tree_t * tree)9126712Stomee avl_is_empty(avl_tree_t *tree)
9136712Stomee {
9146712Stomee ASSERT(tree);
9156712Stomee return (tree->avl_numnodes == 0);
9166712Stomee }
9170Sstevel@tonic-gate
9180Sstevel@tonic-gate #define CHILDBIT (1L)
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate /*
9210Sstevel@tonic-gate * Post-order tree walk used to visit all tree nodes and destroy the tree
9220Sstevel@tonic-gate * in post order. This is used for destroying a tree w/o paying any cost
9230Sstevel@tonic-gate * for rebalancing it.
9240Sstevel@tonic-gate *
9250Sstevel@tonic-gate * example:
9260Sstevel@tonic-gate *
9270Sstevel@tonic-gate * void *cookie = NULL;
9280Sstevel@tonic-gate * my_data_t *node;
9290Sstevel@tonic-gate *
9300Sstevel@tonic-gate * while ((node = avl_destroy_nodes(tree, &cookie)) != NULL)
9310Sstevel@tonic-gate * free(node);
9320Sstevel@tonic-gate * avl_destroy(tree);
9330Sstevel@tonic-gate *
9340Sstevel@tonic-gate * The cookie is really an avl_node_t to the current node's parent and
9350Sstevel@tonic-gate * an indication of which child you looked at last.
9360Sstevel@tonic-gate *
9370Sstevel@tonic-gate * On input, a cookie value of CHILDBIT indicates the tree is done.
9380Sstevel@tonic-gate */
9390Sstevel@tonic-gate void *
avl_destroy_nodes(avl_tree_t * tree,void ** cookie)9400Sstevel@tonic-gate avl_destroy_nodes(avl_tree_t *tree, void **cookie)
9410Sstevel@tonic-gate {
9420Sstevel@tonic-gate avl_node_t *node;
9430Sstevel@tonic-gate avl_node_t *parent;
9440Sstevel@tonic-gate int child;
9450Sstevel@tonic-gate void *first;
9460Sstevel@tonic-gate size_t off = tree->avl_offset;
9470Sstevel@tonic-gate
9480Sstevel@tonic-gate /*
9490Sstevel@tonic-gate * Initial calls go to the first node or it's right descendant.
9500Sstevel@tonic-gate */
9510Sstevel@tonic-gate if (*cookie == NULL) {
9520Sstevel@tonic-gate first = avl_first(tree);
9530Sstevel@tonic-gate
9540Sstevel@tonic-gate /*
9550Sstevel@tonic-gate * deal with an empty tree
9560Sstevel@tonic-gate */
9570Sstevel@tonic-gate if (first == NULL) {
9580Sstevel@tonic-gate *cookie = (void *)CHILDBIT;
9590Sstevel@tonic-gate return (NULL);
9600Sstevel@tonic-gate }
9610Sstevel@tonic-gate
9620Sstevel@tonic-gate node = AVL_DATA2NODE(first, off);
9630Sstevel@tonic-gate parent = AVL_XPARENT(node);
9640Sstevel@tonic-gate goto check_right_side;
9650Sstevel@tonic-gate }
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate /*
9680Sstevel@tonic-gate * If there is no parent to return to we are done.
9690Sstevel@tonic-gate */
9700Sstevel@tonic-gate parent = (avl_node_t *)((uintptr_t)(*cookie) & ~CHILDBIT);
9710Sstevel@tonic-gate if (parent == NULL) {
9720Sstevel@tonic-gate if (tree->avl_root != NULL) {
9730Sstevel@tonic-gate ASSERT(tree->avl_numnodes == 1);
9740Sstevel@tonic-gate tree->avl_root = NULL;
9750Sstevel@tonic-gate tree->avl_numnodes = 0;
9760Sstevel@tonic-gate }
9770Sstevel@tonic-gate return (NULL);
9780Sstevel@tonic-gate }
9790Sstevel@tonic-gate
9800Sstevel@tonic-gate /*
9810Sstevel@tonic-gate * Remove the child pointer we just visited from the parent and tree.
9820Sstevel@tonic-gate */
9830Sstevel@tonic-gate child = (uintptr_t)(*cookie) & CHILDBIT;
9840Sstevel@tonic-gate parent->avl_child[child] = NULL;
9850Sstevel@tonic-gate ASSERT(tree->avl_numnodes > 1);
9860Sstevel@tonic-gate --tree->avl_numnodes;
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate /*
9890Sstevel@tonic-gate * If we just did a right child or there isn't one, go up to parent.
9900Sstevel@tonic-gate */
9910Sstevel@tonic-gate if (child == 1 || parent->avl_child[1] == NULL) {
9920Sstevel@tonic-gate node = parent;
9930Sstevel@tonic-gate parent = AVL_XPARENT(parent);
9940Sstevel@tonic-gate goto done;
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate /*
9980Sstevel@tonic-gate * Do parent's right child, then leftmost descendent.
9990Sstevel@tonic-gate */
10000Sstevel@tonic-gate node = parent->avl_child[1];
10010Sstevel@tonic-gate while (node->avl_child[0] != NULL) {
10020Sstevel@tonic-gate parent = node;
10030Sstevel@tonic-gate node = node->avl_child[0];
10040Sstevel@tonic-gate }
10050Sstevel@tonic-gate
10060Sstevel@tonic-gate /*
10070Sstevel@tonic-gate * If here, we moved to a left child. It may have one
10080Sstevel@tonic-gate * child on the right (when balance == +1).
10090Sstevel@tonic-gate */
10100Sstevel@tonic-gate check_right_side:
10110Sstevel@tonic-gate if (node->avl_child[1] != NULL) {
10120Sstevel@tonic-gate ASSERT(AVL_XBALANCE(node) == 1);
10130Sstevel@tonic-gate parent = node;
10140Sstevel@tonic-gate node = node->avl_child[1];
10150Sstevel@tonic-gate ASSERT(node->avl_child[0] == NULL &&
10160Sstevel@tonic-gate node->avl_child[1] == NULL);
10170Sstevel@tonic-gate } else {
10180Sstevel@tonic-gate ASSERT(AVL_XBALANCE(node) <= 0);
10190Sstevel@tonic-gate }
10200Sstevel@tonic-gate
10210Sstevel@tonic-gate done:
10220Sstevel@tonic-gate if (parent == NULL) {
10230Sstevel@tonic-gate *cookie = (void *)CHILDBIT;
10240Sstevel@tonic-gate ASSERT(node == tree->avl_root);
10250Sstevel@tonic-gate } else {
10260Sstevel@tonic-gate *cookie = (void *)((uintptr_t)parent | AVL_XCHILD(node));
10270Sstevel@tonic-gate }
10280Sstevel@tonic-gate
10290Sstevel@tonic-gate return (AVL_NODE2DATA(node, off));
10300Sstevel@tonic-gate }
1031