xref: /freebsd-src/sys/contrib/openzfs/module/avl/avl.c (revision 2a58b312b62f908ec92311d1bd8536dbaeb8e55b)
1eda14cbcSMatt Macy /*
2eda14cbcSMatt Macy  * CDDL HEADER START
3eda14cbcSMatt Macy  *
4eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7eda14cbcSMatt Macy  *
8eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9271171e0SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
10eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11eda14cbcSMatt Macy  * and limitations under the License.
12eda14cbcSMatt Macy  *
13eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18eda14cbcSMatt Macy  *
19eda14cbcSMatt Macy  * CDDL HEADER END
20eda14cbcSMatt Macy  */
21eda14cbcSMatt Macy /*
22eda14cbcSMatt Macy  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23eda14cbcSMatt Macy  * Use is subject to license terms.
24eda14cbcSMatt Macy  */
25eda14cbcSMatt Macy 
26eda14cbcSMatt Macy /*
27eda14cbcSMatt Macy  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
28eda14cbcSMatt Macy  * Copyright (c) 2015 by Delphix. All rights reserved.
29eda14cbcSMatt Macy  */
30eda14cbcSMatt Macy 
31eda14cbcSMatt Macy /*
32eda14cbcSMatt Macy  * AVL - generic AVL tree implementation for kernel use
33eda14cbcSMatt Macy  *
34eda14cbcSMatt Macy  * A complete description of AVL trees can be found in many CS textbooks.
35eda14cbcSMatt Macy  *
36eda14cbcSMatt Macy  * Here is a very brief overview. An AVL tree is a binary search tree that is
37eda14cbcSMatt Macy  * almost perfectly balanced. By "almost" perfectly balanced, we mean that at
38eda14cbcSMatt Macy  * any given node, the left and right subtrees are allowed to differ in height
39eda14cbcSMatt Macy  * by at most 1 level.
40eda14cbcSMatt Macy  *
41eda14cbcSMatt Macy  * This relaxation from a perfectly balanced binary tree allows doing
42eda14cbcSMatt Macy  * insertion and deletion relatively efficiently. Searching the tree is
43eda14cbcSMatt Macy  * still a fast operation, roughly O(log(N)).
44eda14cbcSMatt Macy  *
45eda14cbcSMatt Macy  * The key to insertion and deletion is a set of tree manipulations called
46eda14cbcSMatt Macy  * rotations, which bring unbalanced subtrees back into the semi-balanced state.
47eda14cbcSMatt Macy  *
48eda14cbcSMatt Macy  * This implementation of AVL trees has the following peculiarities:
49eda14cbcSMatt Macy  *
50eda14cbcSMatt Macy  *	- The AVL specific data structures are physically embedded as fields
51eda14cbcSMatt Macy  *	  in the "using" data structures.  To maintain generality the code
52eda14cbcSMatt Macy  *	  must constantly translate between "avl_node_t *" and containing
53eda14cbcSMatt Macy  *	  data structure "void *"s by adding/subtracting the avl_offset.
54eda14cbcSMatt Macy  *
55eda14cbcSMatt Macy  *	- Since the AVL data is always embedded in other structures, there is
56eda14cbcSMatt Macy  *	  no locking or memory allocation in the AVL routines. This must be
57eda14cbcSMatt Macy  *	  provided for by the enclosing data structure's semantics. Typically,
58eda14cbcSMatt Macy  *	  avl_insert()/_add()/_remove()/avl_insert_here() require some kind of
59eda14cbcSMatt Macy  *	  exclusive write lock. Other operations require a read lock.
60eda14cbcSMatt Macy  *
61eda14cbcSMatt Macy  *      - The implementation uses iteration instead of explicit recursion,
62eda14cbcSMatt Macy  *	  since it is intended to run on limited size kernel stacks. Since
63eda14cbcSMatt Macy  *	  there is no recursion stack present to move "up" in the tree,
64eda14cbcSMatt Macy  *	  there is an explicit "parent" link in the avl_node_t.
65eda14cbcSMatt Macy  *
66eda14cbcSMatt Macy  *      - The left/right children pointers of a node are in an array.
67eda14cbcSMatt Macy  *	  In the code, variables (instead of constants) are used to represent
68eda14cbcSMatt Macy  *	  left and right indices.  The implementation is written as if it only
69eda14cbcSMatt Macy  *	  dealt with left handed manipulations.  By changing the value assigned
70eda14cbcSMatt Macy  *	  to "left", the code also works for right handed trees.  The
71eda14cbcSMatt Macy  *	  following variables/terms are frequently used:
72eda14cbcSMatt Macy  *
73eda14cbcSMatt Macy  *		int left;	// 0 when dealing with left children,
74eda14cbcSMatt Macy  *				// 1 for dealing with right children
75eda14cbcSMatt Macy  *
76eda14cbcSMatt Macy  *		int left_heavy;	// -1 when left subtree is taller at some node,
77eda14cbcSMatt Macy  *				// +1 when right subtree is taller
78eda14cbcSMatt Macy  *
79eda14cbcSMatt Macy  *		int right;	// will be the opposite of left (0 or 1)
80eda14cbcSMatt Macy  *		int right_heavy;// will be the opposite of left_heavy (-1 or 1)
81eda14cbcSMatt Macy  *
82eda14cbcSMatt Macy  *		int direction;  // 0 for "<" (ie. left child); 1 for ">" (right)
83eda14cbcSMatt Macy  *
84eda14cbcSMatt Macy  *	  Though it is a little more confusing to read the code, the approach
85eda14cbcSMatt Macy  *	  allows using half as much code (and hence cache footprint) for tree
86eda14cbcSMatt Macy  *	  manipulations and eliminates many conditional branches.
87eda14cbcSMatt Macy  *
88eda14cbcSMatt Macy  *	- The avl_index_t is an opaque "cookie" used to find nodes at or
89eda14cbcSMatt Macy  *	  adjacent to where a new value would be inserted in the tree. The value
90eda14cbcSMatt Macy  *	  is a modified "avl_node_t *".  The bottom bit (normally 0 for a
91eda14cbcSMatt Macy  *	  pointer) is set to indicate if that the new node has a value greater
92eda14cbcSMatt Macy  *	  than the value of the indicated "avl_node_t *".
93eda14cbcSMatt Macy  *
94eda14cbcSMatt Macy  * Note - in addition to userland (e.g. libavl and libutil) and the kernel
95eda14cbcSMatt Macy  * (e.g. genunix), avl.c is compiled into ld.so and kmdb's genunix module,
96eda14cbcSMatt Macy  * which each have their own compilation environments and subsequent
97eda14cbcSMatt Macy  * requirements. Each of these environments must be considered when adding
98eda14cbcSMatt Macy  * dependencies from avl.c.
99eac7052fSMatt Macy  *
100eac7052fSMatt Macy  * Link to Illumos.org for more information on avl function:
101eac7052fSMatt Macy  * [1] https://illumos.org/man/9f/avl
102eda14cbcSMatt Macy  */
103eda14cbcSMatt Macy 
104eda14cbcSMatt Macy #include <sys/types.h>
105eda14cbcSMatt Macy #include <sys/param.h>
106eda14cbcSMatt Macy #include <sys/debug.h>
107eda14cbcSMatt Macy #include <sys/avl.h>
108eda14cbcSMatt Macy #include <sys/cmn_err.h>
109eda14cbcSMatt Macy #include <sys/mod.h>
110eda14cbcSMatt Macy 
111*2a58b312SMartin Matuska #ifndef _KERNEL
112*2a58b312SMartin Matuska #include <string.h>
113*2a58b312SMartin Matuska #endif
114*2a58b312SMartin Matuska 
115eda14cbcSMatt Macy /*
116eda14cbcSMatt Macy  * Walk from one node to the previous valued node (ie. an infix walk
117eda14cbcSMatt Macy  * towards the left). At any given node we do one of 2 things:
118eda14cbcSMatt Macy  *
119eda14cbcSMatt Macy  * - If there is a left child, go to it, then to it's rightmost descendant.
120eda14cbcSMatt Macy  *
121eda14cbcSMatt Macy  * - otherwise we return through parent nodes until we've come from a right
122eda14cbcSMatt Macy  *   child.
123eda14cbcSMatt Macy  *
124eda14cbcSMatt Macy  * Return Value:
125eda14cbcSMatt Macy  * NULL - if at the end of the nodes
126eda14cbcSMatt Macy  * otherwise next node
127eda14cbcSMatt Macy  */
128eda14cbcSMatt Macy void *
avl_walk(avl_tree_t * tree,void * oldnode,int left)129eda14cbcSMatt Macy avl_walk(avl_tree_t *tree, void	*oldnode, int left)
130eda14cbcSMatt Macy {
131eda14cbcSMatt Macy 	size_t off = tree->avl_offset;
132eda14cbcSMatt Macy 	avl_node_t *node = AVL_DATA2NODE(oldnode, off);
133eda14cbcSMatt Macy 	int right = 1 - left;
134eda14cbcSMatt Macy 	int was_child;
135eda14cbcSMatt Macy 
136eda14cbcSMatt Macy 
137eda14cbcSMatt Macy 	/*
138eda14cbcSMatt Macy 	 * nowhere to walk to if tree is empty
139eda14cbcSMatt Macy 	 */
140eda14cbcSMatt Macy 	if (node == NULL)
141eda14cbcSMatt Macy 		return (NULL);
142eda14cbcSMatt Macy 
143eda14cbcSMatt Macy 	/*
144eda14cbcSMatt Macy 	 * Visit the previous valued node. There are two possibilities:
145eda14cbcSMatt Macy 	 *
146eda14cbcSMatt Macy 	 * If this node has a left child, go down one left, then all
147eda14cbcSMatt Macy 	 * the way right.
148eda14cbcSMatt Macy 	 */
149eda14cbcSMatt Macy 	if (node->avl_child[left] != NULL) {
150eda14cbcSMatt Macy 		for (node = node->avl_child[left];
151eda14cbcSMatt Macy 		    node->avl_child[right] != NULL;
152eda14cbcSMatt Macy 		    node = node->avl_child[right])
153eda14cbcSMatt Macy 			;
154eda14cbcSMatt Macy 	/*
155eda14cbcSMatt Macy 	 * Otherwise, return through left children as far as we can.
156eda14cbcSMatt Macy 	 */
157eda14cbcSMatt Macy 	} else {
158eda14cbcSMatt Macy 		for (;;) {
159eda14cbcSMatt Macy 			was_child = AVL_XCHILD(node);
160eda14cbcSMatt Macy 			node = AVL_XPARENT(node);
161eda14cbcSMatt Macy 			if (node == NULL)
162eda14cbcSMatt Macy 				return (NULL);
163eda14cbcSMatt Macy 			if (was_child == right)
164eda14cbcSMatt Macy 				break;
165eda14cbcSMatt Macy 		}
166eda14cbcSMatt Macy 	}
167eda14cbcSMatt Macy 
168eda14cbcSMatt Macy 	return (AVL_NODE2DATA(node, off));
169eda14cbcSMatt Macy }
170eda14cbcSMatt Macy 
171eda14cbcSMatt Macy /*
172eda14cbcSMatt Macy  * Return the lowest valued node in a tree or NULL.
173eda14cbcSMatt Macy  * (leftmost child from root of tree)
174eda14cbcSMatt Macy  */
175eda14cbcSMatt Macy void *
avl_first(avl_tree_t * tree)176eda14cbcSMatt Macy avl_first(avl_tree_t *tree)
177eda14cbcSMatt Macy {
178eda14cbcSMatt Macy 	avl_node_t *node;
179eda14cbcSMatt Macy 	avl_node_t *prev = NULL;
180eda14cbcSMatt Macy 	size_t off = tree->avl_offset;
181eda14cbcSMatt Macy 
182eda14cbcSMatt Macy 	for (node = tree->avl_root; node != NULL; node = node->avl_child[0])
183eda14cbcSMatt Macy 		prev = node;
184eda14cbcSMatt Macy 
185eda14cbcSMatt Macy 	if (prev != NULL)
186eda14cbcSMatt Macy 		return (AVL_NODE2DATA(prev, off));
187eda14cbcSMatt Macy 	return (NULL);
188eda14cbcSMatt Macy }
189eda14cbcSMatt Macy 
190eda14cbcSMatt Macy /*
191eda14cbcSMatt Macy  * Return the highest valued node in a tree or NULL.
192eda14cbcSMatt Macy  * (rightmost child from root of tree)
193eda14cbcSMatt Macy  */
194eda14cbcSMatt Macy void *
avl_last(avl_tree_t * tree)195eda14cbcSMatt Macy avl_last(avl_tree_t *tree)
196eda14cbcSMatt Macy {
197eda14cbcSMatt Macy 	avl_node_t *node;
198eda14cbcSMatt Macy 	avl_node_t *prev = NULL;
199eda14cbcSMatt Macy 	size_t off = tree->avl_offset;
200eda14cbcSMatt Macy 
201eda14cbcSMatt Macy 	for (node = tree->avl_root; node != NULL; node = node->avl_child[1])
202eda14cbcSMatt Macy 		prev = node;
203eda14cbcSMatt Macy 
204eda14cbcSMatt Macy 	if (prev != NULL)
205eda14cbcSMatt Macy 		return (AVL_NODE2DATA(prev, off));
206eda14cbcSMatt Macy 	return (NULL);
207eda14cbcSMatt Macy }
208eda14cbcSMatt Macy 
209eda14cbcSMatt Macy /*
210eda14cbcSMatt Macy  * Access the node immediately before or after an insertion point.
211eda14cbcSMatt Macy  *
212eda14cbcSMatt Macy  * "avl_index_t" is a (avl_node_t *) with the bottom bit indicating a child
213eda14cbcSMatt Macy  *
214eda14cbcSMatt Macy  * Return value:
215eda14cbcSMatt Macy  *	NULL: no node in the given direction
216eda14cbcSMatt Macy  *	"void *"  of the found tree node
217eda14cbcSMatt Macy  */
218eda14cbcSMatt Macy void *
avl_nearest(avl_tree_t * tree,avl_index_t where,int direction)219eda14cbcSMatt Macy avl_nearest(avl_tree_t *tree, avl_index_t where, int direction)
220eda14cbcSMatt Macy {
221eda14cbcSMatt Macy 	int child = AVL_INDEX2CHILD(where);
222eda14cbcSMatt Macy 	avl_node_t *node = AVL_INDEX2NODE(where);
223eda14cbcSMatt Macy 	void *data;
224eda14cbcSMatt Macy 	size_t off = tree->avl_offset;
225eda14cbcSMatt Macy 
226eda14cbcSMatt Macy 	if (node == NULL) {
227eda14cbcSMatt Macy 		ASSERT(tree->avl_root == NULL);
228eda14cbcSMatt Macy 		return (NULL);
229eda14cbcSMatt Macy 	}
230eda14cbcSMatt Macy 	data = AVL_NODE2DATA(node, off);
231eda14cbcSMatt Macy 	if (child != direction)
232eda14cbcSMatt Macy 		return (data);
233eda14cbcSMatt Macy 
234eda14cbcSMatt Macy 	return (avl_walk(tree, data, direction));
235eda14cbcSMatt Macy }
236eda14cbcSMatt Macy 
237eda14cbcSMatt Macy 
238eda14cbcSMatt Macy /*
239eda14cbcSMatt Macy  * Search for the node which contains "value".  The algorithm is a
240eda14cbcSMatt Macy  * simple binary tree search.
241eda14cbcSMatt Macy  *
242eda14cbcSMatt Macy  * return value:
243eda14cbcSMatt Macy  *	NULL: the value is not in the AVL tree
244eda14cbcSMatt Macy  *		*where (if not NULL)  is set to indicate the insertion point
245eda14cbcSMatt Macy  *	"void *"  of the found tree node
246eda14cbcSMatt Macy  */
247eda14cbcSMatt Macy void *
avl_find(avl_tree_t * tree,const void * value,avl_index_t * where)248eda14cbcSMatt Macy avl_find(avl_tree_t *tree, const void *value, avl_index_t *where)
249eda14cbcSMatt Macy {
250eda14cbcSMatt Macy 	avl_node_t *node;
251eda14cbcSMatt Macy 	avl_node_t *prev = NULL;
252eda14cbcSMatt Macy 	int child = 0;
253eda14cbcSMatt Macy 	int diff;
254eda14cbcSMatt Macy 	size_t off = tree->avl_offset;
255eda14cbcSMatt Macy 
256eda14cbcSMatt Macy 	for (node = tree->avl_root; node != NULL;
257eda14cbcSMatt Macy 	    node = node->avl_child[child]) {
258eda14cbcSMatt Macy 
259eda14cbcSMatt Macy 		prev = node;
260eda14cbcSMatt Macy 
261eda14cbcSMatt Macy 		diff = tree->avl_compar(value, AVL_NODE2DATA(node, off));
262eda14cbcSMatt Macy 		ASSERT(-1 <= diff && diff <= 1);
263eda14cbcSMatt Macy 		if (diff == 0) {
264eda14cbcSMatt Macy #ifdef ZFS_DEBUG
265eda14cbcSMatt Macy 			if (where != NULL)
266eda14cbcSMatt Macy 				*where = 0;
267eda14cbcSMatt Macy #endif
268eda14cbcSMatt Macy 			return (AVL_NODE2DATA(node, off));
269eda14cbcSMatt Macy 		}
2701f1e2261SMartin Matuska 		child = (diff > 0);
271eda14cbcSMatt Macy 	}
272eda14cbcSMatt Macy 
273eda14cbcSMatt Macy 	if (where != NULL)
274eda14cbcSMatt Macy 		*where = AVL_MKINDEX(prev, child);
275eda14cbcSMatt Macy 
276eda14cbcSMatt Macy 	return (NULL);
277eda14cbcSMatt Macy }
278eda14cbcSMatt Macy 
279eda14cbcSMatt Macy 
280eda14cbcSMatt Macy /*
281eda14cbcSMatt Macy  * Perform a rotation to restore balance at the subtree given by depth.
282eda14cbcSMatt Macy  *
283eda14cbcSMatt Macy  * This routine is used by both insertion and deletion. The return value
284eda14cbcSMatt Macy  * indicates:
285eda14cbcSMatt Macy  *	 0 : subtree did not change height
286eda14cbcSMatt Macy  *	!0 : subtree was reduced in height
287eda14cbcSMatt Macy  *
288eda14cbcSMatt Macy  * The code is written as if handling left rotations, right rotations are
289eda14cbcSMatt Macy  * symmetric and handled by swapping values of variables right/left[_heavy]
290eda14cbcSMatt Macy  *
291eda14cbcSMatt Macy  * On input balance is the "new" balance at "node". This value is either
292eda14cbcSMatt Macy  * -2 or +2.
293eda14cbcSMatt Macy  */
294eda14cbcSMatt Macy static int
avl_rotation(avl_tree_t * tree,avl_node_t * node,int balance)295eda14cbcSMatt Macy avl_rotation(avl_tree_t *tree, avl_node_t *node, int balance)
296eda14cbcSMatt Macy {
297eda14cbcSMatt Macy 	int left = !(balance < 0);	/* when balance = -2, left will be 0 */
298eda14cbcSMatt Macy 	int right = 1 - left;
299eda14cbcSMatt Macy 	int left_heavy = balance >> 1;
300eda14cbcSMatt Macy 	int right_heavy = -left_heavy;
301eda14cbcSMatt Macy 	avl_node_t *parent = AVL_XPARENT(node);
302eda14cbcSMatt Macy 	avl_node_t *child = node->avl_child[left];
303eda14cbcSMatt Macy 	avl_node_t *cright;
304eda14cbcSMatt Macy 	avl_node_t *gchild;
305eda14cbcSMatt Macy 	avl_node_t *gright;
306eda14cbcSMatt Macy 	avl_node_t *gleft;
307eda14cbcSMatt Macy 	int which_child = AVL_XCHILD(node);
308eda14cbcSMatt Macy 	int child_bal = AVL_XBALANCE(child);
309eda14cbcSMatt Macy 
310eda14cbcSMatt Macy 	/*
311eda14cbcSMatt Macy 	 * case 1 : node is overly left heavy, the left child is balanced or
312eda14cbcSMatt Macy 	 * also left heavy. This requires the following rotation.
313eda14cbcSMatt Macy 	 *
314eda14cbcSMatt Macy 	 *                   (node bal:-2)
315eda14cbcSMatt Macy 	 *                    /           \
316eda14cbcSMatt Macy 	 *                   /             \
317eda14cbcSMatt Macy 	 *              (child bal:0 or -1)
318eda14cbcSMatt Macy 	 *              /    \
319eda14cbcSMatt Macy 	 *             /      \
320eda14cbcSMatt Macy 	 *                     cright
321eda14cbcSMatt Macy 	 *
322eda14cbcSMatt Macy 	 * becomes:
323eda14cbcSMatt Macy 	 *
324eda14cbcSMatt Macy 	 *              (child bal:1 or 0)
325eda14cbcSMatt Macy 	 *              /        \
326eda14cbcSMatt Macy 	 *             /          \
327eda14cbcSMatt Macy 	 *                        (node bal:-1 or 0)
328eda14cbcSMatt Macy 	 *                         /     \
329eda14cbcSMatt Macy 	 *                        /       \
330eda14cbcSMatt Macy 	 *                     cright
331eda14cbcSMatt Macy 	 *
332eda14cbcSMatt Macy 	 * we detect this situation by noting that child's balance is not
333eda14cbcSMatt Macy 	 * right_heavy.
334eda14cbcSMatt Macy 	 */
335eda14cbcSMatt Macy 	if (child_bal != right_heavy) {
336eda14cbcSMatt Macy 
337eda14cbcSMatt Macy 		/*
338eda14cbcSMatt Macy 		 * compute new balance of nodes
339eda14cbcSMatt Macy 		 *
340eda14cbcSMatt Macy 		 * If child used to be left heavy (now balanced) we reduced
341eda14cbcSMatt Macy 		 * the height of this sub-tree -- used in "return...;" below
342eda14cbcSMatt Macy 		 */
343eda14cbcSMatt Macy 		child_bal += right_heavy; /* adjust towards right */
344eda14cbcSMatt Macy 
345eda14cbcSMatt Macy 		/*
346eda14cbcSMatt Macy 		 * move "cright" to be node's left child
347eda14cbcSMatt Macy 		 */
348eda14cbcSMatt Macy 		cright = child->avl_child[right];
349eda14cbcSMatt Macy 		node->avl_child[left] = cright;
350eda14cbcSMatt Macy 		if (cright != NULL) {
351eda14cbcSMatt Macy 			AVL_SETPARENT(cright, node);
352eda14cbcSMatt Macy 			AVL_SETCHILD(cright, left);
353eda14cbcSMatt Macy 		}
354eda14cbcSMatt Macy 
355eda14cbcSMatt Macy 		/*
356eda14cbcSMatt Macy 		 * move node to be child's right child
357eda14cbcSMatt Macy 		 */
358eda14cbcSMatt Macy 		child->avl_child[right] = node;
359eda14cbcSMatt Macy 		AVL_SETBALANCE(node, -child_bal);
360eda14cbcSMatt Macy 		AVL_SETCHILD(node, right);
361eda14cbcSMatt Macy 		AVL_SETPARENT(node, child);
362eda14cbcSMatt Macy 
363eda14cbcSMatt Macy 		/*
364eda14cbcSMatt Macy 		 * update the pointer into this subtree
365eda14cbcSMatt Macy 		 */
366eda14cbcSMatt Macy 		AVL_SETBALANCE(child, child_bal);
367eda14cbcSMatt Macy 		AVL_SETCHILD(child, which_child);
368eda14cbcSMatt Macy 		AVL_SETPARENT(child, parent);
369eda14cbcSMatt Macy 		if (parent != NULL)
370eda14cbcSMatt Macy 			parent->avl_child[which_child] = child;
371eda14cbcSMatt Macy 		else
372eda14cbcSMatt Macy 			tree->avl_root = child;
373eda14cbcSMatt Macy 
374eda14cbcSMatt Macy 		return (child_bal == 0);
375eda14cbcSMatt Macy 	}
376eda14cbcSMatt Macy 
377eda14cbcSMatt Macy 	/*
378eda14cbcSMatt Macy 	 * case 2 : When node is left heavy, but child is right heavy we use
379eda14cbcSMatt Macy 	 * a different rotation.
380eda14cbcSMatt Macy 	 *
381eda14cbcSMatt Macy 	 *                   (node b:-2)
382eda14cbcSMatt Macy 	 *                    /   \
383eda14cbcSMatt Macy 	 *                   /     \
384eda14cbcSMatt Macy 	 *                  /       \
385eda14cbcSMatt Macy 	 *             (child b:+1)
386eda14cbcSMatt Macy 	 *              /     \
387eda14cbcSMatt Macy 	 *             /       \
388eda14cbcSMatt Macy 	 *                   (gchild b: != 0)
389eda14cbcSMatt Macy 	 *                     /  \
390eda14cbcSMatt Macy 	 *                    /    \
391eda14cbcSMatt Macy 	 *                 gleft   gright
392eda14cbcSMatt Macy 	 *
393eda14cbcSMatt Macy 	 * becomes:
394eda14cbcSMatt Macy 	 *
395eda14cbcSMatt Macy 	 *              (gchild b:0)
396eda14cbcSMatt Macy 	 *              /       \
397eda14cbcSMatt Macy 	 *             /         \
398eda14cbcSMatt Macy 	 *            /           \
399eda14cbcSMatt Macy 	 *        (child b:?)   (node b:?)
400eda14cbcSMatt Macy 	 *         /  \          /   \
401eda14cbcSMatt Macy 	 *        /    \        /     \
402eda14cbcSMatt Macy 	 *            gleft   gright
403eda14cbcSMatt Macy 	 *
404eda14cbcSMatt Macy 	 * computing the new balances is more complicated. As an example:
405eda14cbcSMatt Macy 	 *	 if gchild was right_heavy, then child is now left heavy
406eda14cbcSMatt Macy 	 *		else it is balanced
407eda14cbcSMatt Macy 	 */
408eda14cbcSMatt Macy 	gchild = child->avl_child[right];
409eda14cbcSMatt Macy 	gleft = gchild->avl_child[left];
410eda14cbcSMatt Macy 	gright = gchild->avl_child[right];
411eda14cbcSMatt Macy 
412eda14cbcSMatt Macy 	/*
413eda14cbcSMatt Macy 	 * move gright to left child of node and
414eda14cbcSMatt Macy 	 *
415eda14cbcSMatt Macy 	 * move gleft to right child of node
416eda14cbcSMatt Macy 	 */
417eda14cbcSMatt Macy 	node->avl_child[left] = gright;
418eda14cbcSMatt Macy 	if (gright != NULL) {
419eda14cbcSMatt Macy 		AVL_SETPARENT(gright, node);
420eda14cbcSMatt Macy 		AVL_SETCHILD(gright, left);
421eda14cbcSMatt Macy 	}
422eda14cbcSMatt Macy 
423eda14cbcSMatt Macy 	child->avl_child[right] = gleft;
424eda14cbcSMatt Macy 	if (gleft != NULL) {
425eda14cbcSMatt Macy 		AVL_SETPARENT(gleft, child);
426eda14cbcSMatt Macy 		AVL_SETCHILD(gleft, right);
427eda14cbcSMatt Macy 	}
428eda14cbcSMatt Macy 
429eda14cbcSMatt Macy 	/*
430eda14cbcSMatt Macy 	 * move child to left child of gchild and
431eda14cbcSMatt Macy 	 *
432eda14cbcSMatt Macy 	 * move node to right child of gchild and
433eda14cbcSMatt Macy 	 *
434eda14cbcSMatt Macy 	 * fixup parent of all this to point to gchild
435eda14cbcSMatt Macy 	 */
436eda14cbcSMatt Macy 	balance = AVL_XBALANCE(gchild);
437eda14cbcSMatt Macy 	gchild->avl_child[left] = child;
438eda14cbcSMatt Macy 	AVL_SETBALANCE(child, (balance == right_heavy ? left_heavy : 0));
439eda14cbcSMatt Macy 	AVL_SETPARENT(child, gchild);
440eda14cbcSMatt Macy 	AVL_SETCHILD(child, left);
441eda14cbcSMatt Macy 
442eda14cbcSMatt Macy 	gchild->avl_child[right] = node;
443eda14cbcSMatt Macy 	AVL_SETBALANCE(node, (balance == left_heavy ? right_heavy : 0));
444eda14cbcSMatt Macy 	AVL_SETPARENT(node, gchild);
445eda14cbcSMatt Macy 	AVL_SETCHILD(node, right);
446eda14cbcSMatt Macy 
447eda14cbcSMatt Macy 	AVL_SETBALANCE(gchild, 0);
448eda14cbcSMatt Macy 	AVL_SETPARENT(gchild, parent);
449eda14cbcSMatt Macy 	AVL_SETCHILD(gchild, which_child);
450eda14cbcSMatt Macy 	if (parent != NULL)
451eda14cbcSMatt Macy 		parent->avl_child[which_child] = gchild;
452eda14cbcSMatt Macy 	else
453eda14cbcSMatt Macy 		tree->avl_root = gchild;
454eda14cbcSMatt Macy 
455eda14cbcSMatt Macy 	return (1);	/* the new tree is always shorter */
456eda14cbcSMatt Macy }
457eda14cbcSMatt Macy 
458eda14cbcSMatt Macy 
459eda14cbcSMatt Macy /*
460eda14cbcSMatt Macy  * Insert a new node into an AVL tree at the specified (from avl_find()) place.
461eda14cbcSMatt Macy  *
462eda14cbcSMatt Macy  * Newly inserted nodes are always leaf nodes in the tree, since avl_find()
463eda14cbcSMatt Macy  * searches out to the leaf positions.  The avl_index_t indicates the node
464eda14cbcSMatt Macy  * which will be the parent of the new node.
465eda14cbcSMatt Macy  *
466eda14cbcSMatt Macy  * After the node is inserted, a single rotation further up the tree may
467eda14cbcSMatt Macy  * be necessary to maintain an acceptable AVL balance.
468eda14cbcSMatt Macy  */
469eda14cbcSMatt Macy void
avl_insert(avl_tree_t * tree,void * new_data,avl_index_t where)470eda14cbcSMatt Macy avl_insert(avl_tree_t *tree, void *new_data, avl_index_t where)
471eda14cbcSMatt Macy {
472eda14cbcSMatt Macy 	avl_node_t *node;
473eda14cbcSMatt Macy 	avl_node_t *parent = AVL_INDEX2NODE(where);
474eda14cbcSMatt Macy 	int old_balance;
475eda14cbcSMatt Macy 	int new_balance;
476eda14cbcSMatt Macy 	int which_child = AVL_INDEX2CHILD(where);
477eda14cbcSMatt Macy 	size_t off = tree->avl_offset;
478eda14cbcSMatt Macy 
479eda14cbcSMatt Macy #ifdef _LP64
480eda14cbcSMatt Macy 	ASSERT(((uintptr_t)new_data & 0x7) == 0);
481eda14cbcSMatt Macy #endif
482eda14cbcSMatt Macy 
483eda14cbcSMatt Macy 	node = AVL_DATA2NODE(new_data, off);
484eda14cbcSMatt Macy 
485eda14cbcSMatt Macy 	/*
486eda14cbcSMatt Macy 	 * First, add the node to the tree at the indicated position.
487eda14cbcSMatt Macy 	 */
488eda14cbcSMatt Macy 	++tree->avl_numnodes;
489eda14cbcSMatt Macy 
490eda14cbcSMatt Macy 	node->avl_child[0] = NULL;
491eda14cbcSMatt Macy 	node->avl_child[1] = NULL;
492eda14cbcSMatt Macy 
493eda14cbcSMatt Macy 	AVL_SETCHILD(node, which_child);
494eda14cbcSMatt Macy 	AVL_SETBALANCE(node, 0);
495eda14cbcSMatt Macy 	AVL_SETPARENT(node, parent);
496eda14cbcSMatt Macy 	if (parent != NULL) {
497eda14cbcSMatt Macy 		ASSERT(parent->avl_child[which_child] == NULL);
498eda14cbcSMatt Macy 		parent->avl_child[which_child] = node;
499eda14cbcSMatt Macy 	} else {
500eda14cbcSMatt Macy 		ASSERT(tree->avl_root == NULL);
501eda14cbcSMatt Macy 		tree->avl_root = node;
502eda14cbcSMatt Macy 	}
503eda14cbcSMatt Macy 	/*
504eda14cbcSMatt Macy 	 * Now, back up the tree modifying the balance of all nodes above the
505eda14cbcSMatt Macy 	 * insertion point. If we get to a highly unbalanced ancestor, we
506eda14cbcSMatt Macy 	 * need to do a rotation.  If we back out of the tree we are done.
507eda14cbcSMatt Macy 	 * If we brought any subtree into perfect balance (0), we are also done.
508eda14cbcSMatt Macy 	 */
509eda14cbcSMatt Macy 	for (;;) {
510eda14cbcSMatt Macy 		node = parent;
511eda14cbcSMatt Macy 		if (node == NULL)
512eda14cbcSMatt Macy 			return;
513eda14cbcSMatt Macy 
514eda14cbcSMatt Macy 		/*
515eda14cbcSMatt Macy 		 * Compute the new balance
516eda14cbcSMatt Macy 		 */
517eda14cbcSMatt Macy 		old_balance = AVL_XBALANCE(node);
5181f1e2261SMartin Matuska 		new_balance = old_balance + (which_child ? 1 : -1);
519eda14cbcSMatt Macy 
520eda14cbcSMatt Macy 		/*
521eda14cbcSMatt Macy 		 * If we introduced equal balance, then we are done immediately
522eda14cbcSMatt Macy 		 */
523eda14cbcSMatt Macy 		if (new_balance == 0) {
524eda14cbcSMatt Macy 			AVL_SETBALANCE(node, 0);
525eda14cbcSMatt Macy 			return;
526eda14cbcSMatt Macy 		}
527eda14cbcSMatt Macy 
528eda14cbcSMatt Macy 		/*
529eda14cbcSMatt Macy 		 * If both old and new are not zero we went
530eda14cbcSMatt Macy 		 * from -1 to -2 balance, do a rotation.
531eda14cbcSMatt Macy 		 */
532eda14cbcSMatt Macy 		if (old_balance != 0)
533eda14cbcSMatt Macy 			break;
534eda14cbcSMatt Macy 
535eda14cbcSMatt Macy 		AVL_SETBALANCE(node, new_balance);
536eda14cbcSMatt Macy 		parent = AVL_XPARENT(node);
537eda14cbcSMatt Macy 		which_child = AVL_XCHILD(node);
538eda14cbcSMatt Macy 	}
539eda14cbcSMatt Macy 
540eda14cbcSMatt Macy 	/*
541eda14cbcSMatt Macy 	 * perform a rotation to fix the tree and return
542eda14cbcSMatt Macy 	 */
543eda14cbcSMatt Macy 	(void) avl_rotation(tree, node, new_balance);
544eda14cbcSMatt Macy }
545eda14cbcSMatt Macy 
546eda14cbcSMatt Macy /*
547eda14cbcSMatt Macy  * Insert "new_data" in "tree" in the given "direction" either after or
548eda14cbcSMatt Macy  * before (AVL_AFTER, AVL_BEFORE) the data "here".
549eda14cbcSMatt Macy  *
550eda14cbcSMatt Macy  * Insertions can only be done at empty leaf points in the tree, therefore
551eda14cbcSMatt Macy  * if the given child of the node is already present we move to either
552eda14cbcSMatt Macy  * the AVL_PREV or AVL_NEXT and reverse the insertion direction. Since
553eda14cbcSMatt Macy  * every other node in the tree is a leaf, this always works.
554eda14cbcSMatt Macy  *
555eda14cbcSMatt Macy  * To help developers using this interface, we assert that the new node
556eda14cbcSMatt Macy  * is correctly ordered at every step of the way in DEBUG kernels.
557eda14cbcSMatt Macy  */
558eda14cbcSMatt Macy void
avl_insert_here(avl_tree_t * tree,void * new_data,void * here,int direction)559eda14cbcSMatt Macy avl_insert_here(
560eda14cbcSMatt Macy 	avl_tree_t *tree,
561eda14cbcSMatt Macy 	void *new_data,
562eda14cbcSMatt Macy 	void *here,
563eda14cbcSMatt Macy 	int direction)
564eda14cbcSMatt Macy {
565eda14cbcSMatt Macy 	avl_node_t *node;
566eda14cbcSMatt Macy 	int child = direction;	/* rely on AVL_BEFORE == 0, AVL_AFTER == 1 */
567eda14cbcSMatt Macy #ifdef ZFS_DEBUG
568eda14cbcSMatt Macy 	int diff;
569eda14cbcSMatt Macy #endif
570eda14cbcSMatt Macy 
571eda14cbcSMatt Macy 	ASSERT(tree != NULL);
572eda14cbcSMatt Macy 	ASSERT(new_data != NULL);
573eda14cbcSMatt Macy 	ASSERT(here != NULL);
574eda14cbcSMatt Macy 	ASSERT(direction == AVL_BEFORE || direction == AVL_AFTER);
575eda14cbcSMatt Macy 
576eda14cbcSMatt Macy 	/*
577eda14cbcSMatt Macy 	 * If corresponding child of node is not NULL, go to the neighboring
578eda14cbcSMatt Macy 	 * node and reverse the insertion direction.
579eda14cbcSMatt Macy 	 */
580eda14cbcSMatt Macy 	node = AVL_DATA2NODE(here, tree->avl_offset);
581eda14cbcSMatt Macy 
582eda14cbcSMatt Macy #ifdef ZFS_DEBUG
583eda14cbcSMatt Macy 	diff = tree->avl_compar(new_data, here);
584eda14cbcSMatt Macy 	ASSERT(-1 <= diff && diff <= 1);
585eda14cbcSMatt Macy 	ASSERT(diff != 0);
586eda14cbcSMatt Macy 	ASSERT(diff > 0 ? child == 1 : child == 0);
587eda14cbcSMatt Macy #endif
588eda14cbcSMatt Macy 
589eda14cbcSMatt Macy 	if (node->avl_child[child] != NULL) {
590eda14cbcSMatt Macy 		node = node->avl_child[child];
591eda14cbcSMatt Macy 		child = 1 - child;
592eda14cbcSMatt Macy 		while (node->avl_child[child] != NULL) {
593eda14cbcSMatt Macy #ifdef ZFS_DEBUG
594eda14cbcSMatt Macy 			diff = tree->avl_compar(new_data,
595eda14cbcSMatt Macy 			    AVL_NODE2DATA(node, tree->avl_offset));
596eda14cbcSMatt Macy 			ASSERT(-1 <= diff && diff <= 1);
597eda14cbcSMatt Macy 			ASSERT(diff != 0);
598eda14cbcSMatt Macy 			ASSERT(diff > 0 ? child == 1 : child == 0);
599eda14cbcSMatt Macy #endif
600eda14cbcSMatt Macy 			node = node->avl_child[child];
601eda14cbcSMatt Macy 		}
602eda14cbcSMatt Macy #ifdef ZFS_DEBUG
603eda14cbcSMatt Macy 		diff = tree->avl_compar(new_data,
604eda14cbcSMatt Macy 		    AVL_NODE2DATA(node, tree->avl_offset));
605eda14cbcSMatt Macy 		ASSERT(-1 <= diff && diff <= 1);
606eda14cbcSMatt Macy 		ASSERT(diff != 0);
607eda14cbcSMatt Macy 		ASSERT(diff > 0 ? child == 1 : child == 0);
608eda14cbcSMatt Macy #endif
609eda14cbcSMatt Macy 	}
610eda14cbcSMatt Macy 	ASSERT(node->avl_child[child] == NULL);
611eda14cbcSMatt Macy 
612eda14cbcSMatt Macy 	avl_insert(tree, new_data, AVL_MKINDEX(node, child));
613eda14cbcSMatt Macy }
614eda14cbcSMatt Macy 
615eda14cbcSMatt Macy /*
616eda14cbcSMatt Macy  * Add a new node to an AVL tree.  Strictly enforce that no duplicates can
617eda14cbcSMatt Macy  * be added to the tree with a VERIFY which is enabled for non-DEBUG builds.
618eda14cbcSMatt Macy  */
619eda14cbcSMatt Macy void
avl_add(avl_tree_t * tree,void * new_node)620eda14cbcSMatt Macy avl_add(avl_tree_t *tree, void *new_node)
621eda14cbcSMatt Macy {
622eda14cbcSMatt Macy 	avl_index_t where = 0;
623eda14cbcSMatt Macy 
624eda14cbcSMatt Macy 	VERIFY(avl_find(tree, new_node, &where) == NULL);
625eda14cbcSMatt Macy 
626eda14cbcSMatt Macy 	avl_insert(tree, new_node, where);
627eda14cbcSMatt Macy }
628eda14cbcSMatt Macy 
629eda14cbcSMatt Macy /*
630eda14cbcSMatt Macy  * Delete a node from the AVL tree.  Deletion is similar to insertion, but
631eda14cbcSMatt Macy  * with 2 complications.
632eda14cbcSMatt Macy  *
633eda14cbcSMatt Macy  * First, we may be deleting an interior node. Consider the following subtree:
634eda14cbcSMatt Macy  *
635eda14cbcSMatt Macy  *     d           c            c
636eda14cbcSMatt Macy  *    / \         / \          / \
637eda14cbcSMatt Macy  *   b   e       b   e        b   e
638eda14cbcSMatt Macy  *  / \	        / \          /
639eda14cbcSMatt Macy  * a   c       a            a
640eda14cbcSMatt Macy  *
641eda14cbcSMatt Macy  * When we are deleting node (d), we find and bring up an adjacent valued leaf
642eda14cbcSMatt Macy  * node, say (c), to take the interior node's place. In the code this is
643eda14cbcSMatt Macy  * handled by temporarily swapping (d) and (c) in the tree and then using
644eda14cbcSMatt Macy  * common code to delete (d) from the leaf position.
645eda14cbcSMatt Macy  *
646eda14cbcSMatt Macy  * Secondly, an interior deletion from a deep tree may require more than one
647eda14cbcSMatt Macy  * rotation to fix the balance. This is handled by moving up the tree through
648eda14cbcSMatt Macy  * parents and applying rotations as needed. The return value from
649eda14cbcSMatt Macy  * avl_rotation() is used to detect when a subtree did not change overall
650eda14cbcSMatt Macy  * height due to a rotation.
651eda14cbcSMatt Macy  */
652eda14cbcSMatt Macy void
avl_remove(avl_tree_t * tree,void * data)653eda14cbcSMatt Macy avl_remove(avl_tree_t *tree, void *data)
654eda14cbcSMatt Macy {
655eda14cbcSMatt Macy 	avl_node_t *delete;
656eda14cbcSMatt Macy 	avl_node_t *parent;
657eda14cbcSMatt Macy 	avl_node_t *node;
658eda14cbcSMatt Macy 	avl_node_t tmp;
659eda14cbcSMatt Macy 	int old_balance;
660eda14cbcSMatt Macy 	int new_balance;
661eda14cbcSMatt Macy 	int left;
662eda14cbcSMatt Macy 	int right;
663eda14cbcSMatt Macy 	int which_child;
664eda14cbcSMatt Macy 	size_t off = tree->avl_offset;
665eda14cbcSMatt Macy 
666eda14cbcSMatt Macy 	delete = AVL_DATA2NODE(data, off);
667eda14cbcSMatt Macy 
668eda14cbcSMatt Macy 	/*
669eda14cbcSMatt Macy 	 * Deletion is easiest with a node that has at most 1 child.
670eda14cbcSMatt Macy 	 * We swap a node with 2 children with a sequentially valued
671eda14cbcSMatt Macy 	 * neighbor node. That node will have at most 1 child. Note this
672eda14cbcSMatt Macy 	 * has no effect on the ordering of the remaining nodes.
673eda14cbcSMatt Macy 	 *
674eda14cbcSMatt Macy 	 * As an optimization, we choose the greater neighbor if the tree
675eda14cbcSMatt Macy 	 * is right heavy, otherwise the left neighbor. This reduces the
676eda14cbcSMatt Macy 	 * number of rotations needed.
677eda14cbcSMatt Macy 	 */
678eda14cbcSMatt Macy 	if (delete->avl_child[0] != NULL && delete->avl_child[1] != NULL) {
679eda14cbcSMatt Macy 
680eda14cbcSMatt Macy 		/*
681eda14cbcSMatt Macy 		 * choose node to swap from whichever side is taller
682eda14cbcSMatt Macy 		 */
683eda14cbcSMatt Macy 		old_balance = AVL_XBALANCE(delete);
6841f1e2261SMartin Matuska 		left = (old_balance > 0);
685eda14cbcSMatt Macy 		right = 1 - left;
686eda14cbcSMatt Macy 
687eda14cbcSMatt Macy 		/*
688eda14cbcSMatt Macy 		 * get to the previous value'd node
689eda14cbcSMatt Macy 		 * (down 1 left, as far as possible right)
690eda14cbcSMatt Macy 		 */
691eda14cbcSMatt Macy 		for (node = delete->avl_child[left];
692eda14cbcSMatt Macy 		    node->avl_child[right] != NULL;
693eda14cbcSMatt Macy 		    node = node->avl_child[right])
694eda14cbcSMatt Macy 			;
695eda14cbcSMatt Macy 
696eda14cbcSMatt Macy 		/*
697eda14cbcSMatt Macy 		 * create a temp placeholder for 'node'
698eda14cbcSMatt Macy 		 * move 'node' to delete's spot in the tree
699eda14cbcSMatt Macy 		 */
700eda14cbcSMatt Macy 		tmp = *node;
701eda14cbcSMatt Macy 
702*2a58b312SMartin Matuska 		memcpy(node, delete, sizeof (*node));
703eda14cbcSMatt Macy 		if (node->avl_child[left] == node)
704eda14cbcSMatt Macy 			node->avl_child[left] = &tmp;
705eda14cbcSMatt Macy 
706eda14cbcSMatt Macy 		parent = AVL_XPARENT(node);
707eda14cbcSMatt Macy 		if (parent != NULL)
708eda14cbcSMatt Macy 			parent->avl_child[AVL_XCHILD(node)] = node;
709eda14cbcSMatt Macy 		else
710eda14cbcSMatt Macy 			tree->avl_root = node;
711eda14cbcSMatt Macy 		AVL_SETPARENT(node->avl_child[left], node);
712eda14cbcSMatt Macy 		AVL_SETPARENT(node->avl_child[right], node);
713eda14cbcSMatt Macy 
714eda14cbcSMatt Macy 		/*
715eda14cbcSMatt Macy 		 * Put tmp where node used to be (just temporary).
716eda14cbcSMatt Macy 		 * It always has a parent and at most 1 child.
717eda14cbcSMatt Macy 		 */
718eda14cbcSMatt Macy 		delete = &tmp;
719eda14cbcSMatt Macy 		parent = AVL_XPARENT(delete);
720eda14cbcSMatt Macy 		parent->avl_child[AVL_XCHILD(delete)] = delete;
721eda14cbcSMatt Macy 		which_child = (delete->avl_child[1] != 0);
722eda14cbcSMatt Macy 		if (delete->avl_child[which_child] != NULL)
723eda14cbcSMatt Macy 			AVL_SETPARENT(delete->avl_child[which_child], delete);
724eda14cbcSMatt Macy 	}
725eda14cbcSMatt Macy 
726eda14cbcSMatt Macy 
727eda14cbcSMatt Macy 	/*
728eda14cbcSMatt Macy 	 * Here we know "delete" is at least partially a leaf node. It can
729eda14cbcSMatt Macy 	 * be easily removed from the tree.
730eda14cbcSMatt Macy 	 */
731eda14cbcSMatt Macy 	ASSERT(tree->avl_numnodes > 0);
732eda14cbcSMatt Macy 	--tree->avl_numnodes;
733eda14cbcSMatt Macy 	parent = AVL_XPARENT(delete);
734eda14cbcSMatt Macy 	which_child = AVL_XCHILD(delete);
735eda14cbcSMatt Macy 	if (delete->avl_child[0] != NULL)
736eda14cbcSMatt Macy 		node = delete->avl_child[0];
737eda14cbcSMatt Macy 	else
738eda14cbcSMatt Macy 		node = delete->avl_child[1];
739eda14cbcSMatt Macy 
740eda14cbcSMatt Macy 	/*
741eda14cbcSMatt Macy 	 * Connect parent directly to node (leaving out delete).
742eda14cbcSMatt Macy 	 */
743eda14cbcSMatt Macy 	if (node != NULL) {
744eda14cbcSMatt Macy 		AVL_SETPARENT(node, parent);
745eda14cbcSMatt Macy 		AVL_SETCHILD(node, which_child);
746eda14cbcSMatt Macy 	}
747eda14cbcSMatt Macy 	if (parent == NULL) {
748eda14cbcSMatt Macy 		tree->avl_root = node;
749eda14cbcSMatt Macy 		return;
750eda14cbcSMatt Macy 	}
751eda14cbcSMatt Macy 	parent->avl_child[which_child] = node;
752eda14cbcSMatt Macy 
753eda14cbcSMatt Macy 
754eda14cbcSMatt Macy 	/*
755eda14cbcSMatt Macy 	 * Since the subtree is now shorter, begin adjusting parent balances
756eda14cbcSMatt Macy 	 * and performing any needed rotations.
757eda14cbcSMatt Macy 	 */
758eda14cbcSMatt Macy 	do {
759eda14cbcSMatt Macy 
760eda14cbcSMatt Macy 		/*
761eda14cbcSMatt Macy 		 * Move up the tree and adjust the balance
762eda14cbcSMatt Macy 		 *
763eda14cbcSMatt Macy 		 * Capture the parent and which_child values for the next
764eda14cbcSMatt Macy 		 * iteration before any rotations occur.
765eda14cbcSMatt Macy 		 */
766eda14cbcSMatt Macy 		node = parent;
767eda14cbcSMatt Macy 		old_balance = AVL_XBALANCE(node);
7681f1e2261SMartin Matuska 		new_balance = old_balance - (which_child ? 1 : -1);
769eda14cbcSMatt Macy 		parent = AVL_XPARENT(node);
770eda14cbcSMatt Macy 		which_child = AVL_XCHILD(node);
771eda14cbcSMatt Macy 
772eda14cbcSMatt Macy 		/*
773eda14cbcSMatt Macy 		 * If a node was in perfect balance but isn't anymore then
774eda14cbcSMatt Macy 		 * we can stop, since the height didn't change above this point
775eda14cbcSMatt Macy 		 * due to a deletion.
776eda14cbcSMatt Macy 		 */
777eda14cbcSMatt Macy 		if (old_balance == 0) {
778eda14cbcSMatt Macy 			AVL_SETBALANCE(node, new_balance);
779eda14cbcSMatt Macy 			break;
780eda14cbcSMatt Macy 		}
781eda14cbcSMatt Macy 
782eda14cbcSMatt Macy 		/*
783eda14cbcSMatt Macy 		 * If the new balance is zero, we don't need to rotate
784eda14cbcSMatt Macy 		 * else
785eda14cbcSMatt Macy 		 * need a rotation to fix the balance.
786eda14cbcSMatt Macy 		 * If the rotation doesn't change the height
787eda14cbcSMatt Macy 		 * of the sub-tree we have finished adjusting.
788eda14cbcSMatt Macy 		 */
789eda14cbcSMatt Macy 		if (new_balance == 0)
790eda14cbcSMatt Macy 			AVL_SETBALANCE(node, new_balance);
791eda14cbcSMatt Macy 		else if (!avl_rotation(tree, node, new_balance))
792eda14cbcSMatt Macy 			break;
793eda14cbcSMatt Macy 	} while (parent != NULL);
794eda14cbcSMatt Macy }
795eda14cbcSMatt Macy 
796eda14cbcSMatt Macy #define	AVL_REINSERT(tree, obj)		\
797eda14cbcSMatt Macy 	avl_remove((tree), (obj));	\
798eda14cbcSMatt Macy 	avl_add((tree), (obj))
799eda14cbcSMatt Macy 
800eda14cbcSMatt Macy boolean_t
avl_update_lt(avl_tree_t * t,void * obj)801eda14cbcSMatt Macy avl_update_lt(avl_tree_t *t, void *obj)
802eda14cbcSMatt Macy {
803eda14cbcSMatt Macy 	void *neighbor;
804eda14cbcSMatt Macy 
805eda14cbcSMatt Macy 	ASSERT(((neighbor = AVL_NEXT(t, obj)) == NULL) ||
806eda14cbcSMatt Macy 	    (t->avl_compar(obj, neighbor) <= 0));
807eda14cbcSMatt Macy 
808eda14cbcSMatt Macy 	neighbor = AVL_PREV(t, obj);
809eda14cbcSMatt Macy 	if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) < 0)) {
810eda14cbcSMatt Macy 		AVL_REINSERT(t, obj);
811eda14cbcSMatt Macy 		return (B_TRUE);
812eda14cbcSMatt Macy 	}
813eda14cbcSMatt Macy 
814eda14cbcSMatt Macy 	return (B_FALSE);
815eda14cbcSMatt Macy }
816eda14cbcSMatt Macy 
817eda14cbcSMatt Macy boolean_t
avl_update_gt(avl_tree_t * t,void * obj)818eda14cbcSMatt Macy avl_update_gt(avl_tree_t *t, void *obj)
819eda14cbcSMatt Macy {
820eda14cbcSMatt Macy 	void *neighbor;
821eda14cbcSMatt Macy 
822eda14cbcSMatt Macy 	ASSERT(((neighbor = AVL_PREV(t, obj)) == NULL) ||
823eda14cbcSMatt Macy 	    (t->avl_compar(obj, neighbor) >= 0));
824eda14cbcSMatt Macy 
825eda14cbcSMatt Macy 	neighbor = AVL_NEXT(t, obj);
826eda14cbcSMatt Macy 	if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) > 0)) {
827eda14cbcSMatt Macy 		AVL_REINSERT(t, obj);
828eda14cbcSMatt Macy 		return (B_TRUE);
829eda14cbcSMatt Macy 	}
830eda14cbcSMatt Macy 
831eda14cbcSMatt Macy 	return (B_FALSE);
832eda14cbcSMatt Macy }
833eda14cbcSMatt Macy 
834eda14cbcSMatt Macy boolean_t
avl_update(avl_tree_t * t,void * obj)835eda14cbcSMatt Macy avl_update(avl_tree_t *t, void *obj)
836eda14cbcSMatt Macy {
837eda14cbcSMatt Macy 	void *neighbor;
838eda14cbcSMatt Macy 
839eda14cbcSMatt Macy 	neighbor = AVL_PREV(t, obj);
840eda14cbcSMatt Macy 	if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) < 0)) {
841eda14cbcSMatt Macy 		AVL_REINSERT(t, obj);
842eda14cbcSMatt Macy 		return (B_TRUE);
843eda14cbcSMatt Macy 	}
844eda14cbcSMatt Macy 
845eda14cbcSMatt Macy 	neighbor = AVL_NEXT(t, obj);
846eda14cbcSMatt Macy 	if ((neighbor != NULL) && (t->avl_compar(obj, neighbor) > 0)) {
847eda14cbcSMatt Macy 		AVL_REINSERT(t, obj);
848eda14cbcSMatt Macy 		return (B_TRUE);
849eda14cbcSMatt Macy 	}
850eda14cbcSMatt Macy 
851eda14cbcSMatt Macy 	return (B_FALSE);
852eda14cbcSMatt Macy }
853eda14cbcSMatt Macy 
854eda14cbcSMatt Macy void
avl_swap(avl_tree_t * tree1,avl_tree_t * tree2)855eda14cbcSMatt Macy avl_swap(avl_tree_t *tree1, avl_tree_t *tree2)
856eda14cbcSMatt Macy {
857eda14cbcSMatt Macy 	avl_node_t *temp_node;
858eda14cbcSMatt Macy 	ulong_t temp_numnodes;
859eda14cbcSMatt Macy 
860eda14cbcSMatt Macy 	ASSERT3P(tree1->avl_compar, ==, tree2->avl_compar);
861eda14cbcSMatt Macy 	ASSERT3U(tree1->avl_offset, ==, tree2->avl_offset);
862eda14cbcSMatt Macy 
863eda14cbcSMatt Macy 	temp_node = tree1->avl_root;
864eda14cbcSMatt Macy 	temp_numnodes = tree1->avl_numnodes;
865eda14cbcSMatt Macy 	tree1->avl_root = tree2->avl_root;
866eda14cbcSMatt Macy 	tree1->avl_numnodes = tree2->avl_numnodes;
867eda14cbcSMatt Macy 	tree2->avl_root = temp_node;
868eda14cbcSMatt Macy 	tree2->avl_numnodes = temp_numnodes;
869eda14cbcSMatt Macy }
870eda14cbcSMatt Macy 
871eda14cbcSMatt Macy /*
872eda14cbcSMatt Macy  * initialize a new AVL tree
873eda14cbcSMatt Macy  */
874eda14cbcSMatt Macy void
avl_create(avl_tree_t * tree,int (* compar)(const void *,const void *),size_t size,size_t offset)875eda14cbcSMatt Macy avl_create(avl_tree_t *tree, int (*compar) (const void *, const void *),
876eda14cbcSMatt Macy     size_t size, size_t offset)
877eda14cbcSMatt Macy {
878eda14cbcSMatt Macy 	ASSERT(tree);
879eda14cbcSMatt Macy 	ASSERT(compar);
880eda14cbcSMatt Macy 	ASSERT(size > 0);
881eda14cbcSMatt Macy 	ASSERT(size >= offset + sizeof (avl_node_t));
882eda14cbcSMatt Macy #ifdef _LP64
883eda14cbcSMatt Macy 	ASSERT((offset & 0x7) == 0);
884eda14cbcSMatt Macy #endif
885eda14cbcSMatt Macy 
886eda14cbcSMatt Macy 	tree->avl_compar = compar;
887eda14cbcSMatt Macy 	tree->avl_root = NULL;
888eda14cbcSMatt Macy 	tree->avl_numnodes = 0;
889eda14cbcSMatt Macy 	tree->avl_offset = offset;
890eda14cbcSMatt Macy }
891eda14cbcSMatt Macy 
892eda14cbcSMatt Macy /*
893eda14cbcSMatt Macy  * Delete a tree.
894eda14cbcSMatt Macy  */
895eda14cbcSMatt Macy void
avl_destroy(avl_tree_t * tree)896eda14cbcSMatt Macy avl_destroy(avl_tree_t *tree)
897eda14cbcSMatt Macy {
898eda14cbcSMatt Macy 	ASSERT(tree);
899eda14cbcSMatt Macy 	ASSERT(tree->avl_numnodes == 0);
900eda14cbcSMatt Macy 	ASSERT(tree->avl_root == NULL);
901eda14cbcSMatt Macy }
902eda14cbcSMatt Macy 
903eda14cbcSMatt Macy 
904eda14cbcSMatt Macy /*
905eda14cbcSMatt Macy  * Return the number of nodes in an AVL tree.
906eda14cbcSMatt Macy  */
907eda14cbcSMatt Macy ulong_t
avl_numnodes(avl_tree_t * tree)908eda14cbcSMatt Macy avl_numnodes(avl_tree_t *tree)
909eda14cbcSMatt Macy {
910eda14cbcSMatt Macy 	ASSERT(tree);
911eda14cbcSMatt Macy 	return (tree->avl_numnodes);
912eda14cbcSMatt Macy }
913eda14cbcSMatt Macy 
914eda14cbcSMatt Macy boolean_t
avl_is_empty(avl_tree_t * tree)915eda14cbcSMatt Macy avl_is_empty(avl_tree_t *tree)
916eda14cbcSMatt Macy {
917eda14cbcSMatt Macy 	ASSERT(tree);
918eda14cbcSMatt Macy 	return (tree->avl_numnodes == 0);
919eda14cbcSMatt Macy }
920eda14cbcSMatt Macy 
921eda14cbcSMatt Macy #define	CHILDBIT	(1L)
922eda14cbcSMatt Macy 
923eda14cbcSMatt Macy /*
924eda14cbcSMatt Macy  * Post-order tree walk used to visit all tree nodes and destroy the tree
925eda14cbcSMatt Macy  * in post order. This is used for removing all the nodes from a tree without
926eda14cbcSMatt Macy  * paying any cost for rebalancing it.
927eda14cbcSMatt Macy  *
928eda14cbcSMatt Macy  * example:
929eda14cbcSMatt Macy  *
930eda14cbcSMatt Macy  *	void *cookie = NULL;
931eda14cbcSMatt Macy  *	my_data_t *node;
932eda14cbcSMatt Macy  *
933eda14cbcSMatt Macy  *	while ((node = avl_destroy_nodes(tree, &cookie)) != NULL)
934eda14cbcSMatt Macy  *		free(node);
935eda14cbcSMatt Macy  *	avl_destroy(tree);
936eda14cbcSMatt Macy  *
937eda14cbcSMatt Macy  * The cookie is really an avl_node_t to the current node's parent and
938eda14cbcSMatt Macy  * an indication of which child you looked at last.
939eda14cbcSMatt Macy  *
940eda14cbcSMatt Macy  * On input, a cookie value of CHILDBIT indicates the tree is done.
941eda14cbcSMatt Macy  */
942eda14cbcSMatt Macy void *
avl_destroy_nodes(avl_tree_t * tree,void ** cookie)943eda14cbcSMatt Macy avl_destroy_nodes(avl_tree_t *tree, void **cookie)
944eda14cbcSMatt Macy {
945eda14cbcSMatt Macy 	avl_node_t	*node;
946eda14cbcSMatt Macy 	avl_node_t	*parent;
947eda14cbcSMatt Macy 	int		child;
948eda14cbcSMatt Macy 	void		*first;
949eda14cbcSMatt Macy 	size_t		off = tree->avl_offset;
950eda14cbcSMatt Macy 
951eda14cbcSMatt Macy 	/*
952eda14cbcSMatt Macy 	 * Initial calls go to the first node or it's right descendant.
953eda14cbcSMatt Macy 	 */
954eda14cbcSMatt Macy 	if (*cookie == NULL) {
955eda14cbcSMatt Macy 		first = avl_first(tree);
956eda14cbcSMatt Macy 
957eda14cbcSMatt Macy 		/*
958eda14cbcSMatt Macy 		 * deal with an empty tree
959eda14cbcSMatt Macy 		 */
960eda14cbcSMatt Macy 		if (first == NULL) {
961eda14cbcSMatt Macy 			*cookie = (void *)CHILDBIT;
962eda14cbcSMatt Macy 			return (NULL);
963eda14cbcSMatt Macy 		}
964eda14cbcSMatt Macy 
965eda14cbcSMatt Macy 		node = AVL_DATA2NODE(first, off);
966eda14cbcSMatt Macy 		parent = AVL_XPARENT(node);
967eda14cbcSMatt Macy 		goto check_right_side;
968eda14cbcSMatt Macy 	}
969eda14cbcSMatt Macy 
970eda14cbcSMatt Macy 	/*
971eda14cbcSMatt Macy 	 * If there is no parent to return to we are done.
972eda14cbcSMatt Macy 	 */
973eda14cbcSMatt Macy 	parent = (avl_node_t *)((uintptr_t)(*cookie) & ~CHILDBIT);
974eda14cbcSMatt Macy 	if (parent == NULL) {
975eda14cbcSMatt Macy 		if (tree->avl_root != NULL) {
976eda14cbcSMatt Macy 			ASSERT(tree->avl_numnodes == 1);
977eda14cbcSMatt Macy 			tree->avl_root = NULL;
978eda14cbcSMatt Macy 			tree->avl_numnodes = 0;
979eda14cbcSMatt Macy 		}
980eda14cbcSMatt Macy 		return (NULL);
981eda14cbcSMatt Macy 	}
982eda14cbcSMatt Macy 
983eda14cbcSMatt Macy 	/*
984eda14cbcSMatt Macy 	 * Remove the child pointer we just visited from the parent and tree.
985eda14cbcSMatt Macy 	 */
986eda14cbcSMatt Macy 	child = (uintptr_t)(*cookie) & CHILDBIT;
987eda14cbcSMatt Macy 	parent->avl_child[child] = NULL;
988eda14cbcSMatt Macy 	ASSERT(tree->avl_numnodes > 1);
989eda14cbcSMatt Macy 	--tree->avl_numnodes;
990eda14cbcSMatt Macy 
991eda14cbcSMatt Macy 	/*
99216038816SMartin Matuska 	 * If we just removed a right child or there isn't one, go up to parent.
993eda14cbcSMatt Macy 	 */
994eda14cbcSMatt Macy 	if (child == 1 || parent->avl_child[1] == NULL) {
995eda14cbcSMatt Macy 		node = parent;
996eda14cbcSMatt Macy 		parent = AVL_XPARENT(parent);
997eda14cbcSMatt Macy 		goto done;
998eda14cbcSMatt Macy 	}
999eda14cbcSMatt Macy 
1000eda14cbcSMatt Macy 	/*
1001eda14cbcSMatt Macy 	 * Do parent's right child, then leftmost descendent.
1002eda14cbcSMatt Macy 	 */
1003eda14cbcSMatt Macy 	node = parent->avl_child[1];
1004eda14cbcSMatt Macy 	while (node->avl_child[0] != NULL) {
1005eda14cbcSMatt Macy 		parent = node;
1006eda14cbcSMatt Macy 		node = node->avl_child[0];
1007eda14cbcSMatt Macy 	}
1008eda14cbcSMatt Macy 
1009eda14cbcSMatt Macy 	/*
1010eda14cbcSMatt Macy 	 * If here, we moved to a left child. It may have one
1011eda14cbcSMatt Macy 	 * child on the right (when balance == +1).
1012eda14cbcSMatt Macy 	 */
1013eda14cbcSMatt Macy check_right_side:
1014eda14cbcSMatt Macy 	if (node->avl_child[1] != NULL) {
1015eda14cbcSMatt Macy 		ASSERT(AVL_XBALANCE(node) == 1);
1016eda14cbcSMatt Macy 		parent = node;
1017eda14cbcSMatt Macy 		node = node->avl_child[1];
1018eda14cbcSMatt Macy 		ASSERT(node->avl_child[0] == NULL &&
1019eda14cbcSMatt Macy 		    node->avl_child[1] == NULL);
1020eda14cbcSMatt Macy 	} else {
1021eda14cbcSMatt Macy 		ASSERT(AVL_XBALANCE(node) <= 0);
1022eda14cbcSMatt Macy 	}
1023eda14cbcSMatt Macy 
1024eda14cbcSMatt Macy done:
1025eda14cbcSMatt Macy 	if (parent == NULL) {
1026eda14cbcSMatt Macy 		*cookie = (void *)CHILDBIT;
1027eda14cbcSMatt Macy 		ASSERT(node == tree->avl_root);
1028eda14cbcSMatt Macy 	} else {
1029eda14cbcSMatt Macy 		*cookie = (void *)((uintptr_t)parent | AVL_XCHILD(node));
1030eda14cbcSMatt Macy 	}
1031eda14cbcSMatt Macy 
1032eda14cbcSMatt Macy 	return (AVL_NODE2DATA(node, off));
1033eda14cbcSMatt Macy }
1034eda14cbcSMatt Macy 
1035eda14cbcSMatt Macy EXPORT_SYMBOL(avl_create);
1036eda14cbcSMatt Macy EXPORT_SYMBOL(avl_find);
1037eda14cbcSMatt Macy EXPORT_SYMBOL(avl_insert);
1038eda14cbcSMatt Macy EXPORT_SYMBOL(avl_insert_here);
1039eda14cbcSMatt Macy EXPORT_SYMBOL(avl_walk);
1040eda14cbcSMatt Macy EXPORT_SYMBOL(avl_first);
1041eda14cbcSMatt Macy EXPORT_SYMBOL(avl_last);
1042eda14cbcSMatt Macy EXPORT_SYMBOL(avl_nearest);
1043eda14cbcSMatt Macy EXPORT_SYMBOL(avl_add);
1044eda14cbcSMatt Macy EXPORT_SYMBOL(avl_swap);
1045eda14cbcSMatt Macy EXPORT_SYMBOL(avl_is_empty);
1046eda14cbcSMatt Macy EXPORT_SYMBOL(avl_remove);
1047eda14cbcSMatt Macy EXPORT_SYMBOL(avl_numnodes);
1048eda14cbcSMatt Macy EXPORT_SYMBOL(avl_destroy_nodes);
1049eda14cbcSMatt Macy EXPORT_SYMBOL(avl_destroy);
1050eda14cbcSMatt Macy EXPORT_SYMBOL(avl_update_lt);
1051eda14cbcSMatt Macy EXPORT_SYMBOL(avl_update_gt);
1052eda14cbcSMatt Macy EXPORT_SYMBOL(avl_update);
1053