The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/avl/avl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 738bd847b51da4eaaa7c3c966e5fe60e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.