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