/* $NetBSD: prop_rb.c,v 1.9 2008/06/17 21:29:47 thorpej Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Matt Thomas . * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include "prop_object_impl.h" #include "prop_rb_impl.h" #undef KASSERT #ifdef RBDEBUG #define KASSERT(x) _PROP_ASSERT(x) #else #define KASSERT(x) /* nothing */ #endif #ifndef __predict_false #define __predict_false(x) (x) #endif static void rb_tree_insert_rebalance(struct rb_tree *, struct rb_node *); static void rb_tree_removal_rebalance(struct rb_tree *, struct rb_node *, unsigned int); #ifdef RBDEBUG static const struct rb_node *rb_tree_iterate_const(const struct rb_tree *, const struct rb_node *, const unsigned int); static bool rb_tree_check_node(const struct rb_tree *, const struct rb_node *, const struct rb_node *, bool); #else #define rb_tree_check_node(a, b, c, d) true #endif #ifdef RBDEBUG #define RBT_COUNT_INCR(rbt) (rbt)->rbt_count++ #define RBT_COUNT_DECR(rbt) (rbt)->rbt_count-- #else #define RBT_COUNT_INCR(rbt) /* nothing */ #define RBT_COUNT_DECR(rbt) /* nothing */ #endif #define RBUNCONST(a) ((void *)(unsigned long)(const void *)(a)) #define RB_NODETOITEM(rbto, rbn) \ ((void *)((uintptr_t)(rbn) - (rbto)->rbto_node_offset)) #define RB_ITEMTONODE(rbto, rbn) \ ((rb_node_t *)((uintptr_t)(rbn) + (rbto)->rbto_node_offset)) #define RB_SENTINEL_NODE NULL void _prop_rb_tree_init(struct rb_tree *rbt, const rb_tree_ops_t *ops) { RB_TAILQ_INIT(&rbt->rbt_nodes); #ifdef RBDEBUG rbt->rbt_count = 0; #endif rbt->rbt_ops = ops; rbt->rbt_root = RB_SENTINEL_NODE; } void * _prop_rb_tree_find(struct rb_tree *rbt, const void *key) { const rb_tree_ops_t *rbto = rbt->rbt_ops; rbto_compare_key_fn compare_key = rbto->rbto_compare_key; struct rb_node *parent = rbt->rbt_root; while (!RB_SENTINEL_P(parent)) { void *pobj = RB_NODETOITEM(rbto, parent); const signed int diff = (*compare_key)(rbto->rbto_context, pobj, key); if (diff == 0) return pobj; parent = parent->rb_nodes[diff < 0]; } return NULL; } void * _prop_rb_tree_insert_node(struct rb_tree *rbt, void *object) { const rb_tree_ops_t *rbto = rbt->rbt_ops; rbto_compare_nodes_fn compare_nodes = rbto->rbto_compare_nodes; struct rb_node *parent, *tmp, *self = RB_ITEMTONODE(rbto, object); unsigned int position; bool rebalance; RBSTAT_INC(rbt->rbt_insertions); tmp = rbt->rbt_root; /* * This is a hack. Because rbt->rbt_root is just a struct rb_node *, * just like rb_node->rb_nodes[RB_DIR_LEFT], we can use this fact to * avoid a lot of tests for root and know that even at root, * updating RB_FATHER(rb_node)->rb_nodes[RB_POSITION(rb_node)] will * update rbt->rbt_root. */ parent = (struct rb_node *)(void *)&rbt->rbt_root; position = RB_DIR_LEFT; /* * Find out where to place this new leaf. */ while (!RB_SENTINEL_P(tmp)) { void *tobj = RB_NODETOITEM(rbto, tmp); const signed int diff = (*compare_nodes)(rbto->rbto_context, tobj, object); if (__predict_false(diff == 0)) { /* * Node already exists; return it. */ return tobj; } parent = tmp; position = (diff < 0); tmp = parent->rb_nodes[position]; } #ifdef RBDEBUG { struct rb_node *prev = NULL, *next = NULL; if (position == RB_DIR_RIGHT) prev = parent; else if (tmp != rbt->rbt_root) next = parent; /* * Verify our sequential position */ KASSERT(prev == NULL || !RB_SENTINEL_P(prev)); KASSERT(next == NULL || !RB_SENTINEL_P(next)); if (prev != NULL && next == NULL) next = TAILQ_NEXT(prev, rb_link); if (prev == NULL && next != NULL) prev = TAILQ_PREV(next, rb_node_qh, rb_link); KASSERT(prev == NULL || !RB_SENTINEL_P(prev)); KASSERT(next == NULL || !RB_SENTINEL_P(next)); KASSERT(prev == NULL || (*compare_nodes)(rbto->rbto_context, RB_NODETOITEM(rbto, prev), RB_NODETOITEM(rbto, self)) < 0); KASSERT(next == NULL || (*compare_nodes)(rbto->rbto_context, RB_NODETOITEM(rbto, self), RB_NODETOITEM(rbto, next)) < 0); } #endif /* * Initialize the node and insert as a leaf into the tree. */ RB_SET_FATHER(self, parent); RB_SET_POSITION(self, position); if (__predict_false(parent == (struct rb_node *)(void *)&rbt->rbt_root)) { RB_MARK_BLACK(self); /* root is always black */ #ifndef RBSMALL rbt->rbt_minmax[RB_DIR_LEFT] = self; rbt->rbt_minmax[RB_DIR_RIGHT] = self; #endif rebalance = false; } else { KASSERT(position == RB_DIR_LEFT || position == RB_DIR_RIGHT); #ifndef RBSMALL /* * Keep track of the minimum and maximum nodes. If our * parent is a minmax node and we on their min/max side, * we must be the new min/max node. */ if (parent == rbt->rbt_minmax[position]) rbt->rbt_minmax[position] = self; #endif /* !RBSMALL */ /* * All new nodes are colored red. We only need to rebalance * if our parent is also red. */ RB_MARK_RED(self); rebalance = RB_RED_P(parent); } KASSERT(RB_SENTINEL_P(parent->rb_nodes[position])); self->rb_left = parent->rb_nodes[position]; self->rb_right = parent->rb_nodes[position]; parent->rb_nodes[position] = self; KASSERT(RB_CHILDLESS_P(self)); /* * Insert the new node into a sorted list for easy sequential access */ RBSTAT_INC(rbt->rbt_count); #ifdef RBDEBUG if (RB_ROOT_P(rbt, self)) { RB_TAILQ_INSERT_HEAD(&rbt->rbt_nodes, self, rb_link); } else if (position == RB_DIR_LEFT) { KASSERT((*compare_nodes)(rbto->rbto_context, RB_NODETOITEM(rbto, self), RB_NODETOITEM(rbto, RB_FATHER(self))) < 0); RB_TAILQ_INSERT_BEFORE(RB_FATHER(self), self, rb_link); } else { KASSERT((*compare_nodes)(rbto->rbto_context, RB_NODETOITEM(rbto, RB_FATHER(self)), RB_NODETOITEM(rbto, self)) < 0); RB_TAILQ_INSERT_AFTER(&rbt->rbt_nodes, RB_FATHER(self), self, rb_link); } #endif KASSERT(rb_tree_check_node(rbt, self, NULL, !rebalance)); /* * Rebalance tree after insertion */ if (rebalance) { rb_tree_insert_rebalance(rbt, self); KASSERT(rb_tree_check_node(rbt, self, NULL, true)); } /* Succesfully inserted, return our node pointer. */ return object; } /* * Swap the location and colors of 'self' and its child @ which. The child * can not be a sentinel node. This is our rotation function. However, * since it preserves coloring, it great simplifies both insertion and * removal since rotation almost always involves the exchanging of colors * as a separate step. */ /*ARGSUSED*/ static void rb_tree_reparent_nodes(struct rb_tree *rbt, struct rb_node *old_father, const unsigned int which) { const unsigned int other = which ^ RB_DIR_OTHER; struct rb_node * const grandpa = RB_FATHER(old_father); struct rb_node * const old_child = old_father->rb_nodes[which]; struct rb_node * const new_father = old_child; struct rb_node * const new_child = old_father; KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT); KASSERT(!RB_SENTINEL_P(old_child)); KASSERT(RB_FATHER(old_child) == old_father); KASSERT(rb_tree_check_node(rbt, old_father, NULL, false)); KASSERT(rb_tree_check_node(rbt, old_child, NULL, false)); KASSERT(RB_ROOT_P(rbt, old_father) || rb_tree_check_node(rbt, grandpa, NULL, false)); /* * Exchange descendant linkages. */ grandpa->rb_nodes[RB_POSITION(old_father)] = new_father; new_child->rb_nodes[which] = old_child->rb_nodes[other]; new_father->rb_nodes[other] = new_child; /* * Update ancestor linkages */ RB_SET_FATHER(new_father, grandpa); RB_SET_FATHER(new_child, new_father); /* * Exchange properties between new_father and new_child. The only * change is that new_child's position is now on the other side. */ #if 0 { struct rb_node tmp; tmp.rb_info = 0; RB_COPY_PROPERTIES(&tmp, old_child); RB_COPY_PROPERTIES(new_father, old_father); RB_COPY_PROPERTIES(new_child, &tmp); } #else RB_SWAP_PROPERTIES(new_father, new_child); #endif RB_SET_POSITION(new_child, other); /* * Make sure to reparent the new child to ourself. */ if (!RB_SENTINEL_P(new_child->rb_nodes[which])) { RB_SET_FATHER(new_child->rb_nodes[which], new_child); RB_SET_POSITION(new_child->rb_nodes[which], which); } KASSERT(rb_tree_check_node(rbt, new_father, NULL, false)); KASSERT(rb_tree_check_node(rbt, new_child, NULL, false)); KASSERT(RB_ROOT_P(rbt, new_father) || rb_tree_check_node(rbt, grandpa, NULL, false)); } static void rb_tree_insert_rebalance(struct rb_tree *rbt, struct rb_node *self) { struct rb_node * father = RB_FATHER(self); struct rb_node * grandpa = RB_FATHER(father); struct rb_node * uncle; unsigned int which; unsigned int other; KASSERT(!RB_ROOT_P(rbt, self)); KASSERT(RB_RED_P(self)); KASSERT(RB_RED_P(father)); RBSTAT_INC(rbt->rbt_insertion_rebalance_calls); for (;;) { KASSERT(!RB_SENTINEL_P(self)); KASSERT(RB_RED_P(self)); KASSERT(RB_RED_P(father)); /* * We are red and our parent is red, therefore we must have a * grandfather and he must be black. */ grandpa = RB_FATHER(father); KASSERT(RB_BLACK_P(grandpa)); KASSERT(RB_DIR_RIGHT == 1 && RB_DIR_LEFT == 0); which = (father == grandpa->rb_right); other = which ^ RB_DIR_OTHER; uncle = grandpa->rb_nodes[other]; if (RB_BLACK_P(uncle)) break; RBSTAT_INC(rbt->rbt_insertion_rebalance_passes); /* * Case 1: our uncle is red * Simply invert the colors of our parent and * uncle and make our grandparent red. And * then solve the problem up at his level. */ RB_MARK_BLACK(uncle); RB_MARK_BLACK(father); if (__predict_false(RB_ROOT_P(rbt, grandpa))) { /* * If our grandpa is root, don't bother * setting him to red, just return. */ KASSERT(RB_BLACK_P(grandpa)); return; } RB_MARK_RED(grandpa); self = grandpa; father = RB_FATHER(self); KASSERT(RB_RED_P(self)); if (RB_BLACK_P(father)) { /* * If our greatgrandpa is black, we're done. */ KASSERT(RB_BLACK_P(rbt->rbt_root)); return; } } KASSERT(!RB_ROOT_P(rbt, self)); KASSERT(RB_RED_P(self)); KASSERT(RB_RED_P(father)); KASSERT(RB_BLACK_P(uncle)); KASSERT(RB_BLACK_P(grandpa)); /* * Case 2&3: our uncle is black. */ if (self == father->rb_nodes[other]) { /* * Case 2: we are on the same side as our uncle * Swap ourselves with our parent so this case * becomes case 3. Basically our parent becomes our * child. */ rb_tree_reparent_nodes(rbt, father, other); KASSERT(RB_FATHER(father) == self); KASSERT(self->rb_nodes[which] == father); KASSERT(RB_FATHER(self) == grandpa); self = father; father = RB_FATHER(self); } KASSERT(RB_RED_P(self) && RB_RED_P(father)); KASSERT(grandpa->rb_nodes[which] == father); /* * Case 3: we are opposite a child of a black uncle. * Swap our parent and grandparent. Since our grandfather * is black, our father will become black and our new sibling * (former grandparent) will become red. */ rb_tree_reparent_nodes(rbt, grandpa, which); KASSERT(RB_FATHER(self) == father); KASSERT(RB_FATHER(self)->rb_nodes[RB_POSITION(self) ^ RB_DIR_OTHER] == grandpa); KASSERT(RB_RED_P(self)); KASSERT(RB_BLACK_P(father)); KASSERT(RB_RED_P(grandpa)); /* * Final step: Set the root to black. */ RB_MARK_BLACK(rbt->rbt_root); } static void rb_tree_prune_node(struct rb_tree *rbt, struct rb_node *self, bool rebalance) { const unsigned int which = RB_POSITION(self); struct rb_node *father = RB_FATHER(self); #ifndef RBSMALL const bool was_root = RB_ROOT_P(rbt, self); #endif KASSERT(rebalance || (RB_ROOT_P(rbt, self) || RB_RED_P(self))); KASSERT(!rebalance || RB_BLACK_P(self)); KASSERT(RB_CHILDLESS_P(self)); KASSERT(rb_tree_check_node(rbt, self, NULL, false)); /* * Since we are childless, we know that self->rb_left is pointing * to the sentinel node. */ father->rb_nodes[which] = self->rb_left; /* * Remove ourselves from the node list, decrement the count, * and update min/max. */ RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link); RBSTAT_DEC(rbt->rbt_count); #ifndef RBSMALL if (__predict_false(rbt->rbt_minmax[RB_POSITION(self)] == self)) { rbt->rbt_minmax[RB_POSITION(self)] = father; /* * When removing the root, rbt->rbt_minmax[RB_DIR_LEFT] is * updated automatically, but we also need to update * rbt->rbt_minmax[RB_DIR_RIGHT]; */ if (__predict_false(was_root)) { rbt->rbt_minmax[RB_DIR_RIGHT] = father; } } RB_SET_FATHER(self, NULL); #endif /* * Rebalance if requested. */ if (rebalance) rb_tree_removal_rebalance(rbt, father, which); KASSERT(was_root || rb_tree_check_node(rbt, father, NULL, true)); } /* * When deleting an interior node */ static void rb_tree_swap_prune_and_rebalance(struct rb_tree *rbt, struct rb_node *self, struct rb_node *standin) { const unsigned int standin_which = RB_POSITION(standin); unsigned int standin_other = standin_which ^ RB_DIR_OTHER; struct rb_node *standin_son; struct rb_node *standin_father = RB_FATHER(standin); bool rebalance = RB_BLACK_P(standin); if (standin_father == self) { /* * As a child of self, any childen would be opposite of * our parent. */ KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_other])); standin_son = standin->rb_nodes[standin_which]; } else { /* * Since we aren't a child of self, any childen would be * on the same side as our parent. */ KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_which])); standin_son = standin->rb_nodes[standin_other]; } /* * the node we are removing must have two children. */ KASSERT(RB_TWOCHILDREN_P(self)); /* * If standin has a child, it must be red. */ KASSERT(RB_SENTINEL_P(standin_son) || RB_RED_P(standin_son)); /* * Verify things are sane. */ KASSERT(rb_tree_check_node(rbt, self, NULL, false)); KASSERT(rb_tree_check_node(rbt, standin, NULL, false)); if (__predict_false(RB_RED_P(standin_son))) { /* * We know we have a red child so if we flip it to black * we don't have to rebalance. */ KASSERT(rb_tree_check_node(rbt, standin_son, NULL, true)); RB_MARK_BLACK(standin_son); rebalance = false; if (standin_father == self) { KASSERT(RB_POSITION(standin_son) == standin_which); } else { KASSERT(RB_POSITION(standin_son) == standin_other); /* * Change the son's parentage to point to his grandpa. */ RB_SET_FATHER(standin_son, standin_father); RB_SET_POSITION(standin_son, standin_which); } } if (standin_father == self) { /* * If we are about to delete the standin's father, then when * we call rebalance, we need to use ourselves as our father. * Otherwise remember our original father. Also, sincef we are * our standin's father we only need to reparent the standin's * brother. * * | R --> S | * | Q S --> Q T | * | t --> | */ KASSERT(RB_SENTINEL_P(standin->rb_nodes[standin_other])); KASSERT(!RB_SENTINEL_P(self->rb_nodes[standin_other])); KASSERT(self->rb_nodes[standin_which] == standin); /* * Have our son/standin adopt his brother as his new son. */ standin_father = standin; } else { /* * | R --> S . | * | / \ | T --> / \ | / | * | ..... | S --> ..... | T | * * Sever standin's connection to his father. */ standin_father->rb_nodes[standin_which] = standin_son; /* * Adopt the far son. */ standin->rb_nodes[standin_other] = self->rb_nodes[standin_other]; RB_SET_FATHER(standin->rb_nodes[standin_other], standin); KASSERT(RB_POSITION(self->rb_nodes[standin_other]) == standin_other); /* * Use standin_other because we need to preserve standin_which * for the removal_rebalance. */ standin_other = standin_which; } /* * Move the only remaining son to our standin. If our standin is our * son, this will be the only son needed to be moved. */ KASSERT(standin->rb_nodes[standin_other] != self->rb_nodes[standin_other]); standin->rb_nodes[standin_other] = self->rb_nodes[standin_other]; RB_SET_FATHER(standin->rb_nodes[standin_other], standin); /* * Now copy the result of self to standin and then replace * self with standin in the tree. */ RB_COPY_PROPERTIES(standin, self); RB_SET_FATHER(standin, RB_FATHER(self)); RB_FATHER(standin)->rb_nodes[RB_POSITION(standin)] = standin; /* * Remove ourselves from the node list, decrement the count, * and update min/max. */ RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link); RBSTAT_DEC(rbt->rbt_count); #ifndef RBSMALL if (__predict_false(rbt->rbt_minmax[RB_POSITION(self)] == self)) rbt->rbt_minmax[RB_POSITION(self)] = RB_FATHER(self); RB_SET_FATHER(self, NULL); #endif KASSERT(rb_tree_check_node(rbt, standin, NULL, false)); KASSERT(RB_FATHER_SENTINEL_P(standin) || rb_tree_check_node(rbt, standin_father, NULL, false)); KASSERT(RB_LEFT_SENTINEL_P(standin) || rb_tree_check_node(rbt, standin->rb_left, NULL, false)); KASSERT(RB_RIGHT_SENTINEL_P(standin) || rb_tree_check_node(rbt, standin->rb_right, NULL, false)); if (!rebalance) return; rb_tree_removal_rebalance(rbt, standin_father, standin_which); KASSERT(rb_tree_check_node(rbt, standin, NULL, true)); } /* * We could do this by doing * rb_tree_node_swap(rbt, self, which); * rb_tree_prune_node(rbt, self, false); * * But it's more efficient to just evalate and recolor the child. */ static void rb_tree_prune_blackred_branch(struct rb_tree *rbt, struct rb_node *self, unsigned int which) { struct rb_node *father = RB_FATHER(self); struct rb_node *son = self->rb_nodes[which]; #ifndef RBSMALL const bool was_root = RB_ROOT_P(rbt, self); #endif KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT); KASSERT(RB_BLACK_P(self) && RB_RED_P(son)); KASSERT(!RB_TWOCHILDREN_P(son)); KASSERT(RB_CHILDLESS_P(son)); KASSERT(rb_tree_check_node(rbt, self, NULL, false)); KASSERT(rb_tree_check_node(rbt, son, NULL, false)); /* * Remove ourselves from the tree and give our former child our * properties (position, color, root). */ RB_COPY_PROPERTIES(son, self); father->rb_nodes[RB_POSITION(son)] = son; RB_SET_FATHER(son, father); /* * Remove ourselves from the node list, decrement the count, * and update minmax. */ RB_TAILQ_REMOVE(&rbt->rbt_nodes, self, rb_link); RBSTAT_DEC(rbt->rbt_count); #ifndef RBSMALL if (__predict_false(was_root)) { KASSERT(rbt->rbt_minmax[which] == son); rbt->rbt_minmax[which ^ RB_DIR_OTHER] = son; } else if (rbt->rbt_minmax[RB_POSITION(self)] == self) { rbt->rbt_minmax[RB_POSITION(self)] = son; } RB_SET_FATHER(self, NULL); #endif KASSERT(was_root || rb_tree_check_node(rbt, father, NULL, true)); KASSERT(rb_tree_check_node(rbt, son, NULL, true)); } void _prop_rb_tree_remove_node(struct rb_tree *rbt, void *object) { const rb_tree_ops_t *rbto = rbt->rbt_ops; struct rb_node *standin, *self = RB_ITEMTONODE(rbto, object); unsigned int which; KASSERT(!RB_SENTINEL_P(self)); RBSTAT_INC(rbt->rbt_removals); /* * In the following diagrams, we (the node to be removed) are S. Red * nodes are lowercase. T could be either red or black. * * Remember the major axiom of the red-black tree: the number of * black nodes from the root to each leaf is constant across all * leaves, only the number of red nodes varies. * * Thus removing a red leaf doesn't require any other changes to a * red-black tree. So if we must remove a node, attempt to rearrange * the tree so we can remove a red node. * * The simpliest case is a childless red node or a childless root node: * * | T --> T | or | R --> * | * | s --> * | */ if (RB_CHILDLESS_P(self)) { const bool rebalance = RB_BLACK_P(self) && !RB_ROOT_P(rbt, self); rb_tree_prune_node(rbt, self, rebalance); return; } KASSERT(!RB_CHILDLESS_P(self)); if (!RB_TWOCHILDREN_P(self)) { /* * The next simpliest case is the node we are deleting is * black and has one red child. * * | T --> T --> T | * | S --> R --> R | * | r --> s --> * | */ which = RB_LEFT_SENTINEL_P(self) ? RB_DIR_RIGHT : RB_DIR_LEFT; KASSERT(RB_BLACK_P(self)); KASSERT(RB_RED_P(self->rb_nodes[which])); KASSERT(RB_CHILDLESS_P(self->rb_nodes[which])); rb_tree_prune_blackred_branch(rbt, self, which); return; } KASSERT(RB_TWOCHILDREN_P(self)); /* * We invert these because we prefer to remove from the inside of * the tree. */ which = RB_POSITION(self) ^ RB_DIR_OTHER; /* * Let's find the node closes to us opposite of our parent * Now swap it with ourself, "prune" it, and rebalance, if needed. */ standin = RB_ITEMTONODE(rbto, _prop_rb_tree_iterate(rbt, object, which)); rb_tree_swap_prune_and_rebalance(rbt, self, standin); } static void rb_tree_removal_rebalance(struct rb_tree *rbt, struct rb_node *parent, unsigned int which) { KASSERT(!RB_SENTINEL_P(parent)); KASSERT(RB_SENTINEL_P(parent->rb_nodes[which])); KASSERT(which == RB_DIR_LEFT || which == RB_DIR_RIGHT); RBSTAT_INC(rbt->rbt_removal_rebalance_calls); while (RB_BLACK_P(parent->rb_nodes[which])) { unsigned int other = which ^ RB_DIR_OTHER; struct rb_node *brother = parent->rb_nodes[other]; RBSTAT_INC(rbt->rbt_removal_rebalance_passes); KASSERT(!RB_SENTINEL_P(brother)); /* * For cases 1, 2a, and 2b, our brother's children must * be black and our father must be black */ if (RB_BLACK_P(parent) && RB_BLACK_P(brother->rb_left) && RB_BLACK_P(brother->rb_right)) { if (RB_RED_P(brother)) { /* * Case 1: Our brother is red, swap its * position (and colors) with our parent. * This should now be case 2b (unless C or E * has a red child which is case 3; thus no * explicit branch to case 2b). * * B -> D * A d -> b E * C E -> A C */ KASSERT(RB_BLACK_P(parent)); rb_tree_reparent_nodes(rbt, parent, other); brother = parent->rb_nodes[other]; KASSERT(!RB_SENTINEL_P(brother)); KASSERT(RB_RED_P(parent)); KASSERT(RB_BLACK_P(brother)); KASSERT(rb_tree_check_node(rbt, brother, NULL, false)); KASSERT(rb_tree_check_node(rbt, parent, NULL, false)); } else { /* * Both our parent and brother are black. * Change our brother to red, advance up rank * and go through the loop again. * * B -> *B * *A D -> A d * C E -> C E */ RB_MARK_RED(brother); KASSERT(RB_BLACK_P(brother->rb_left)); KASSERT(RB_BLACK_P(brother->rb_right)); if (RB_ROOT_P(rbt, parent)) return; /* root == parent == black */ KASSERT(rb_tree_check_node(rbt, brother, NULL, false)); KASSERT(rb_tree_check_node(rbt, parent, NULL, false)); which = RB_POSITION(parent); parent = RB_FATHER(parent); continue; } } /* * Avoid an else here so that case 2a above can hit either * case 2b, 3, or 4. */ if (RB_RED_P(parent) && RB_BLACK_P(brother) && RB_BLACK_P(brother->rb_left) && RB_BLACK_P(brother->rb_right)) { KASSERT(RB_RED_P(parent)); KASSERT(RB_BLACK_P(brother)); KASSERT(RB_BLACK_P(brother->rb_left)); KASSERT(RB_BLACK_P(brother->rb_right)); /* * We are black, our father is red, our brother and * both nephews are black. Simply invert/exchange the * colors of our father and brother (to black and red * respectively). * * | f --> F | * | * B --> * b | * | N N --> N N | */ RB_MARK_BLACK(parent); RB_MARK_RED(brother); KASSERT(rb_tree_check_node(rbt, brother, NULL, true)); break; /* We're done! */ } else { /* * Our brother must be black and have at least one * red child (it may have two). */ KASSERT(RB_BLACK_P(brother)); KASSERT(RB_RED_P(brother->rb_nodes[which]) || RB_RED_P(brother->rb_nodes[other])); if (RB_BLACK_P(brother->rb_nodes[other])) { /* * Case 3: our brother is black, our near * nephew is red, and our far nephew is black. * Swap our brother with our near nephew. * This result in a tree that matches case 4. * (Our father could be red or black). * * | F --> F | * | x B --> x B | * | n --> n | */ KASSERT(RB_RED_P(brother->rb_nodes[which])); rb_tree_reparent_nodes(rbt, brother, which); KASSERT(RB_FATHER(brother) == parent->rb_nodes[other]); brother = parent->rb_nodes[other]; KASSERT(RB_RED_P(brother->rb_nodes[other])); } /* * Case 4: our brother is black and our far nephew * is red. Swap our father and brother locations and * change our far nephew to black. (these can be * done in either order so we change the color first). * The result is a valid red-black tree and is a * terminal case. (again we don't care about the * father's color) * * If the father is red, we will get a red-black-black * tree: * | f -> f --> b | * | B -> B --> F N | * | n -> N --> | * * If the father is black, we will get an all black * tree: * | F -> F --> B | * | B -> B --> F N | * | n -> N --> | * * If we had two red nephews, then after the swap, * our former father would have a red grandson. */ KASSERT(RB_BLACK_P(brother)); KASSERT(RB_RED_P(brother->rb_nodes[other])); RB_MARK_BLACK(brother->rb_nodes[other]); rb_tree_reparent_nodes(rbt, parent, other); break; /* We're done! */ } } KASSERT(rb_tree_check_node(rbt, parent, NULL, true)); } void * _prop_rb_tree_iterate(struct rb_tree *rbt, void *object, const unsigned int direction) { const rb_tree_ops_t *rbto = rbt->rbt_ops; const unsigned int other = direction ^ RB_DIR_OTHER; struct rb_node *self; KASSERT(direction == RB_DIR_LEFT || direction == RB_DIR_RIGHT); if (object == NULL) { #ifndef RBSMALL if (RB_SENTINEL_P(rbt->rbt_root)) return NULL; return RB_NODETOITEM(rbto, rbt->rbt_minmax[direction]); #else self = rbt->rbt_root; if (RB_SENTINEL_P(self)) return NULL; while (!RB_SENTINEL_P(self->rb_nodes[direction])) self = self->rb_nodes[direction]; return RB_NODETOITEM(rbto, self); #endif /* !RBSMALL */ } self = RB_ITEMTONODE(rbto, object); KASSERT(!RB_SENTINEL_P(self)); /* * We can't go any further in this direction. We proceed up in the * opposite direction until our parent is in direction we want to go. */ if (RB_SENTINEL_P(self->rb_nodes[direction])) { while (!RB_ROOT_P(rbt, self)) { if (other == RB_POSITION(self)) return RB_NODETOITEM(rbto, RB_FATHER(self)); self = RB_FATHER(self); } return NULL; } /* * Advance down one in current direction and go down as far as possible * in the opposite direction. */ self = self->rb_nodes[direction]; KASSERT(!RB_SENTINEL_P(self)); while (!RB_SENTINEL_P(self->rb_nodes[other])) self = self->rb_nodes[other]; return RB_NODETOITEM(rbto, self); } #ifdef RBDEBUG static const struct rb_node * rb_tree_iterate_const(const struct rb_tree *rbt, const struct rb_node *self, const unsigned int direction) { const unsigned int other = direction ^ RB_DIR_OTHER; KASSERT(direction == RB_DIR_LEFT || direction == RB_DIR_RIGHT); if (self == NULL) { #ifndef RBSMALL if (RB_SENTINEL_P(rbt->rbt_root)) return NULL; return rbt->rbt_minmax[direction]; #else self = rbt->rbt_root; if (RB_SENTINEL_P(self)) return NULL; while (!RB_SENTINEL_P(self->rb_nodes[direction])) self = self->rb_nodes[direction]; return self; #endif /* !RBSMALL */ } KASSERT(!RB_SENTINEL_P(self)); /* * We can't go any further in this direction. We proceed up in the * opposite direction until our parent is in direction we want to go. */ if (RB_SENTINEL_P(self->rb_nodes[direction])) { while (!RB_ROOT_P(rbt, self)) { if (other == RB_POSITION(self)) return RB_FATHER(self); self = RB_FATHER(self); } return NULL; } /* * Advance down one in current direction and go down as far as possible * in the opposite direction. */ self = self->rb_nodes[direction]; KASSERT(!RB_SENTINEL_P(self)); while (!RB_SENTINEL_P(self->rb_nodes[other])) self = self->rb_nodes[other]; return self; } static unsigned int rb_tree_count_black(const struct rb_node *self) { unsigned int left, right; if (RB_SENTINEL_P(self)) return 0; left = rb_tree_count_black(self->rb_left); right = rb_tree_count_black(self->rb_right); KASSERT(left == right); return left + RB_BLACK_P(self); } static bool rb_tree_check_node(const struct rb_tree *rbt, const struct rb_node *self, const struct rb_node *prev, bool red_check) { const rb_tree_ops_t *rbto = rbt->rbt_ops; rbto_compare_nodes_fn compare_nodes = rbto->rbto_compare_nodes; KASSERT(!RB_SENTINEL_P(self)); KASSERT(prev == NULL || (*compare_nodes)(rbto->rbto_context, RB_NODETOITEM(rbto, prev), RB_NODETOITEM(rbto, self)) < 0); /* * Verify our relationship to our parent. */ if (RB_ROOT_P(rbt, self)) { KASSERT(self == rbt->rbt_root); KASSERT(RB_POSITION(self) == RB_DIR_LEFT); KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_LEFT] == self); KASSERT(RB_FATHER(self) == (const struct rb_node *) &rbt->rbt_root); } else { int diff = (*compare_nodes)(rbto->rbto_context, RB_NODETOITEM(rbto, self), RB_NODETOITEM(rbto, RB_FATHER(self))); KASSERT(self != rbt->rbt_root); KASSERT(!RB_FATHER_SENTINEL_P(self)); if (RB_POSITION(self) == RB_DIR_LEFT) { KASSERT(diff < 0); KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_LEFT] == self); } else { KASSERT(diff > 0); KASSERT(RB_FATHER(self)->rb_nodes[RB_DIR_RIGHT] == self); } } /* * Verify our position in the linked list against the tree itself. */ { const struct rb_node *prev0 = rb_tree_iterate_const(rbt, self, RB_DIR_LEFT); const struct rb_node *next0 = rb_tree_iterate_const(rbt, self, RB_DIR_RIGHT); KASSERT(prev0 == TAILQ_PREV(self, rb_node_qh, rb_link)); KASSERT(next0 == TAILQ_NEXT(self, rb_link)); #ifndef RBSMALL KASSERT(prev0 != NULL || self == rbt->rbt_minmax[RB_DIR_LEFT]); KASSERT(next0 != NULL || self == rbt->rbt_minmax[RB_DIR_RIGHT]); #endif } /* * The root must be black. * There can never be two adjacent red nodes. */ if (red_check) { KASSERT(!RB_ROOT_P(rbt, self) || RB_BLACK_P(self)); (void) rb_tree_count_black(self); if (RB_RED_P(self)) { const struct rb_node *brother; KASSERT(!RB_ROOT_P(rbt, self)); brother = RB_FATHER(self)->rb_nodes[RB_POSITION(self) ^ RB_DIR_OTHER]; KASSERT(RB_BLACK_P(RB_FATHER(self))); /* * I'm red and have no children, then I must either * have no brother or my brother also be red and * also have no children. (black count == 0) */ KASSERT(!RB_CHILDLESS_P(self) || RB_SENTINEL_P(brother) || RB_RED_P(brother) || RB_CHILDLESS_P(brother)); /* * If I'm not childless, I must have two children * and they must be both be black. */ KASSERT(RB_CHILDLESS_P(self) || (RB_TWOCHILDREN_P(self) && RB_BLACK_P(self->rb_left) && RB_BLACK_P(self->rb_right))); /* * If I'm not childless, thus I have black children, * then my brother must either be black or have two * black children. */ KASSERT(RB_CHILDLESS_P(self) || RB_BLACK_P(brother) || (RB_TWOCHILDREN_P(brother) && RB_BLACK_P(brother->rb_left) && RB_BLACK_P(brother->rb_right))); } else { /* * If I'm black and have one child, that child must * be red and childless. */ KASSERT(RB_CHILDLESS_P(self) || RB_TWOCHILDREN_P(self) || (!RB_LEFT_SENTINEL_P(self) && RB_RIGHT_SENTINEL_P(self) && RB_RED_P(self->rb_left) && RB_CHILDLESS_P(self->rb_left)) || (!RB_RIGHT_SENTINEL_P(self) && RB_LEFT_SENTINEL_P(self) && RB_RED_P(self->rb_right) && RB_CHILDLESS_P(self->rb_right))); /* * If I'm a childless black node and my parent is * black, my 2nd closet relative away from my parent * is either red or has a red parent or red children. */ if (!RB_ROOT_P(rbt, self) && RB_CHILDLESS_P(self) && RB_BLACK_P(RB_FATHER(self))) { const unsigned int which = RB_POSITION(self); const unsigned int other = which ^ RB_DIR_OTHER; const struct rb_node *relative0, *relative; relative0 = rb_tree_iterate_const(rbt, self, other); KASSERT(relative0 != NULL); relative = rb_tree_iterate_const(rbt, relative0, other); KASSERT(relative != NULL); KASSERT(RB_SENTINEL_P(relative->rb_nodes[which])); #if 0 KASSERT(RB_RED_P(relative) || RB_RED_P(relative->rb_left) || RB_RED_P(relative->rb_right) || RB_RED_P(RB_FATHER(relative))); #endif } } /* * A grandparent's children must be real nodes and not * sentinels. First check out grandparent. */ KASSERT(RB_ROOT_P(rbt, self) || RB_ROOT_P(rbt, RB_FATHER(self)) || RB_TWOCHILDREN_P(RB_FATHER(RB_FATHER(self)))); /* * If we are have grandchildren on our left, then * we must have a child on our right. */ KASSERT(RB_LEFT_SENTINEL_P(self) || RB_CHILDLESS_P(self->rb_left) || !RB_RIGHT_SENTINEL_P(self)); /* * If we are have grandchildren on our right, then * we must have a child on our left. */ KASSERT(RB_RIGHT_SENTINEL_P(self) || RB_CHILDLESS_P(self->rb_right) || !RB_LEFT_SENTINEL_P(self)); /* * If we have a child on the left and it doesn't have two * children make sure we don't have great-great-grandchildren on * the right. */ KASSERT(RB_TWOCHILDREN_P(self->rb_left) || RB_CHILDLESS_P(self->rb_right) || RB_CHILDLESS_P(self->rb_right->rb_left) || RB_CHILDLESS_P(self->rb_right->rb_left->rb_left) || RB_CHILDLESS_P(self->rb_right->rb_left->rb_right) || RB_CHILDLESS_P(self->rb_right->rb_right) || RB_CHILDLESS_P(self->rb_right->rb_right->rb_left) || RB_CHILDLESS_P(self->rb_right->rb_right->rb_right)); /* * If we have a child on the right and it doesn't have two * children make sure we don't have great-great-grandchildren on * the left. */ KASSERT(RB_TWOCHILDREN_P(self->rb_right) || RB_CHILDLESS_P(self->rb_left) || RB_CHILDLESS_P(self->rb_left->rb_left) || RB_CHILDLESS_P(self->rb_left->rb_left->rb_left) || RB_CHILDLESS_P(self->rb_left->rb_left->rb_right) || RB_CHILDLESS_P(self->rb_left->rb_right) || RB_CHILDLESS_P(self->rb_left->rb_right->rb_left) || RB_CHILDLESS_P(self->rb_left->rb_right->rb_right)); /* * If we are fully interior node, then our predecessors and * successors must have no children in our direction. */ if (RB_TWOCHILDREN_P(self)) { const struct rb_node *prev0; const struct rb_node *next0; prev0 = rb_tree_iterate_const(rbt, self, RB_DIR_LEFT); KASSERT(prev0 != NULL); KASSERT(RB_RIGHT_SENTINEL_P(prev0)); next0 = rb_tree_iterate_const(rbt, self, RB_DIR_RIGHT); KASSERT(next0 != NULL); KASSERT(RB_LEFT_SENTINEL_P(next0)); } } return true; } void rb_tree_check(const struct rb_tree *rbt, bool red_check) { const struct rb_node *self; const struct rb_node *prev; #ifdef RBSTATS unsigned int count = 0; #endif KASSERT(rbt->rbt_root != NULL); KASSERT(RB_LEFT_P(rbt->rbt_root)); #if defined(RBSTATS) && !defined(RBSMALL) KASSERT(rbt->rbt_count > 1 || rbt->rbt_minmax[RB_DIR_LEFT] == rbt->rbt_minmax[RB_DIR_RIGHT]); #endif prev = NULL; TAILQ_FOREACH(self, &rbt->rbt_nodes, rb_link) { rb_tree_check_node(rbt, self, prev, false); #ifdef RBSTATS count++; #endif } #ifdef RBSTATS KASSERT(rbt->rbt_count == count); #endif if (red_check) { KASSERT(RB_BLACK_P(rbt->rbt_root)); KASSERT(RB_SENTINEL_P(rbt->rbt_root) || rb_tree_count_black(rbt->rbt_root)); /* * The root must be black. * There can never be two adjacent red nodes. */ TAILQ_FOREACH(self, &rbt->rbt_nodes, rb_link) { rb_tree_check_node(rbt, self, NULL, true); } } } #endif /* RBDEBUG */ #ifdef RBSTATS static void rb_tree_mark_depth(const struct rb_tree *rbt, const struct rb_node *self, size_t *depths, size_t depth) { if (RB_SENTINEL_P(self)) return; if (RB_TWOCHILDREN_P(self)) { rb_tree_mark_depth(rbt, self->rb_left, depths, depth + 1); rb_tree_mark_depth(rbt, self->rb_right, depths, depth + 1); return; } depths[depth]++; if (!RB_LEFT_SENTINEL_P(self)) { rb_tree_mark_depth(rbt, self->rb_left, depths, depth + 1); } if (!RB_RIGHT_SENTINEL_P(self)) { rb_tree_mark_depth(rbt, self->rb_right, depths, depth + 1); } } void rb_tree_depths(const struct rb_tree *rbt, size_t *depths) { rb_tree_mark_depth(rbt, rbt->rbt_root, depths, 1); } #endif /* RBSTATS */