summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kern/rbtree.c47
-rw-r--r--kern/rbtree.h20
-rw-r--r--kern/rbtree_i.h6
3 files changed, 60 insertions, 13 deletions
diff --git a/kern/rbtree.c b/kern/rbtree.c
index adce033..95873b9 100644
--- a/kern/rbtree.c
+++ b/kern/rbtree.c
@@ -26,7 +26,7 @@
/*
* Return the index of a node in the children array of its parent.
*
- * The parent parameter must not be null, and must be the parent of the
+ * The parent parameter must not be NULL, and must be the parent of the
* given node.
*/
static inline int
@@ -175,7 +175,7 @@ void
rbtree_insert_rebalance(struct rbtree *tree, struct rbtree_node *parent,
int index, struct rbtree_node *node)
{
- struct rbtree_node *grand_parent, *uncle, *tmp;
+ struct rbtree_node *grand_parent, *uncle;
int left, right;
assert(rbtree_node_check_alignment(parent));
@@ -226,9 +226,7 @@ rbtree_insert_rebalance(struct rbtree *tree, struct rbtree_node *parent,
*/
if (parent->children[right] == node) {
rbtree_rotate(tree, parent, left);
- tmp = node;
- node = parent;
- parent = tmp;
+ parent = node;
}
/*
@@ -244,6 +242,40 @@ rbtree_insert_rebalance(struct rbtree *tree, struct rbtree_node *parent,
assert(rbtree_node_is_black(tree->root));
}
+void *
+rbtree_replace_slot(struct rbtree *tree, rbtree_slot_t slot,
+ struct rbtree_node *node)
+{
+ struct rbtree_node *parent, *prev;
+ int index;
+
+ parent = rbtree_slot_parent(slot);
+
+ if (!parent) {
+ prev = tree->root;
+ tree->root = node;
+ } else {
+ index = rbtree_slot_index(slot);
+ assert(rbtree_check_index(index));
+ prev = parent->children[index];
+ parent->children[index] = node;
+ }
+
+ assert(prev);
+ *node = *prev;
+
+ for (size_t i = 0; i < ARRAY_SIZE(node->children); i++) {
+ if (!node->children[i]) {
+ continue;
+ }
+
+
+ rbtree_node_set_parent(node->children[i], node);
+ }
+
+ return prev;
+}
+
void
rbtree_remove(struct rbtree *tree, struct rbtree_node *node)
{
@@ -321,7 +353,7 @@ rbtree_remove(struct rbtree *tree, struct rbtree_node *node)
/*
* The node has been removed, update the colors. The child pointer can
- * be null, in which case it is considered a black leaf.
+ * be NULL, in which case it is considered a black leaf.
*/
update_color:
if (color == RBTREE_COLOR_RED) {
@@ -354,6 +386,8 @@ update_color:
brother = parent->children[right];
}
+ assert(brother != NULL);
+
/*
* Brother has no red child. Recolor and repeat at parent.
*/
@@ -383,6 +417,7 @@ update_color:
* (we already know brother is black), set brother's right child black,
* rotate left at parent and leave.
*/
+ assert(brother->children[right] != NULL);
rbtree_node_set_color(brother, rbtree_node_color(parent));
rbtree_node_set_black(parent);
rbtree_node_set_black(brother->children[right]);
diff --git a/kern/rbtree.h b/kern/rbtree.h
index 3de240b..e805bd9 100644
--- a/kern/rbtree.h
+++ b/kern/rbtree.h
@@ -48,6 +48,11 @@ struct rbtree;
*/
typedef uintptr_t rbtree_slot_t;
+/*
+ * Static tree initializer.
+ */
+#define RBTREE_INITIALIZER { NULL }
+
#include <kern/rbtree_i.h>
/*
@@ -209,7 +214,7 @@ MACRO_END
*
* This macro essentially acts as rbtree_lookup() but in addition to a node,
* it also returns a slot, which identifies an insertion point in the tree.
- * If the returned node is null, the slot can be used by rbtree_insert_slot()
+ * If the returned node is NULL, the slot can be used by rbtree_insert_slot()
* to insert without the overhead of an additional lookup.
*
* The constraints that apply to the key parameter are the same as for
@@ -247,7 +252,7 @@ MACRO_END
* obtain the insertion point with a standard lookup. The insertion point
* is obtained by calling rbtree_lookup_slot(). In addition, the new node
* must not compare equal to an existing node in the tree (i.e. the slot
- * must denote a null node).
+ * must denote a NULL node).
*/
static inline void
rbtree_insert_slot(struct rbtree *tree, rbtree_slot_t slot,
@@ -262,11 +267,18 @@ rbtree_insert_slot(struct rbtree *tree, rbtree_slot_t slot,
}
/*
+ * Replace a node at an insertion point in a tree.
+ *
+ * The given node must compare strictly equal to the previous node,
+ * which is returned on completion.
+ */
+void * rbtree_replace_slot(struct rbtree *tree, rbtree_slot_t slot,
+ struct rbtree_node *node);
+
+/*
* Remove a node from a tree.
*
* After completion, the node is stale.
- *
- * TODO rbtree_replace.
*/
void rbtree_remove(struct rbtree *tree, struct rbtree_node *node);
diff --git a/kern/rbtree_i.h b/kern/rbtree_i.h
index 944148e..973899b 100644
--- a/kern/rbtree_i.h
+++ b/kern/rbtree_i.h
@@ -54,7 +54,7 @@ struct rbtree {
* Masks applied on the parent member of a node to obtain either the
* color or the parent address.
*/
-#define RBTREE_COLOR_MASK ((uintptr_t)1)
+#define RBTREE_COLOR_MASK ((uintptr_t)0x1)
#define RBTREE_PARENT_MASK (~(uintptr_t)0x3)
/*
@@ -67,7 +67,7 @@ struct rbtree {
* Masks applied on slots to obtain either the child index or the parent
* address.
*/
-#define RBTREE_SLOT_INDEX_MASK ((uintptr_t)0x1)
+#define RBTREE_SLOT_INDEX_MASK 0x1UL
#define RBTREE_SLOT_PARENT_MASK (~RBTREE_SLOT_INDEX_MASK)
/*
@@ -142,7 +142,7 @@ rbtree_slot_index(rbtree_slot_t slot)
* Insert a node in a tree, rebalancing it if necessary.
*
* The index parameter is the index in the children array of the parent where
- * the new node is to be inserted. It is ignored if the parent is null.
+ * the new node is to be inserted. It is ignored if the parent is NULL.
*
* This function is intended to be used by the rbtree_insert() macro only.
*/