Browse Source

Hopefully fixed a few bugs

tree_alloc
Thomas Johnson 1 year ago
parent
commit
a3ae7eb75c
  1. 2
      allocator_internal.h
  2. 89
      tree_alloc.c

2
allocator_internal.h

@ -66,7 +66,7 @@ uintptr_t lcm(uintptr_t a, uintptr_t b);
uintptr_t gcd(uintptr_t a, uintptr_t b);
TreeAlloc *search_by_address(TreeAlloc *root, void *address);
TreeAlloc *search_by_size(TreeAlloc *root, uintptr_t padding, uintptr_t align, uintptr_t size);
TreeAlloc *get_sibling(TreeAlloc *ta);
TreeAlloc *get_sibling(TreeAlloc *p, TreeAlloc *ta);
void rotate_left(TreeAlloc **root_ptr, TreeAlloc *ta);
void rotate_right(TreeAlloc **root_ptr, TreeAlloc *ta);
void repair_tree_after_insert(TreeAlloc **root_ptr, TreeAlloc *ta);

89
tree_alloc.c

@ -122,8 +122,7 @@ TreeAlloc *pred(TreeAlloc *el) {
return el->parent;
}
TreeAlloc *get_sibling(TreeAlloc *ta) {
TreeAlloc *p = ta->parent;
TreeAlloc *get_sibling(TreeAlloc *p, TreeAlloc *ta) {
if (!p)
return NULL;
else if (p->left == ta)
@ -190,7 +189,7 @@ void repair_tree_after_insert(TreeAlloc **root_ptr, TreeAlloc *ta) {
} else if (IS_BLACK_NODE(parent)) {
return;
} else {
TreeAlloc *uncle = get_sibling(parent);
TreeAlloc *uncle = get_sibling(parent->parent, parent);
TreeAlloc *grandparent = parent->parent;
if (IS_RED_NODE(uncle)) {
@ -317,51 +316,65 @@ void replace_node(TreeAlloc **root_ptr, TreeAlloc *node, TreeAlloc *replace) {
if (replace) replace->parent = node->parent;
}
void repair_after_remove(TreeAlloc **root_ptr, TreeAlloc *node) {
if (IS_RED_NODE(node)) {
void repair_after_remove(TreeAlloc **root_ptr, TreeAlloc *parent, TreeAlloc *node) {
#ifdef DEBUG
printf("delete fixup at %p\n", node);
#endif
// In theory, the last two conditions should be the same ...
if (IS_RED_NODE(node) || (node != NULL && node == *root_ptr)) {
node->color = COLOR_BLACK;
} else {
TreeAlloc *sibling = get_sibling(node);
TreeAlloc *sibling = get_sibling(parent, node);
if (IS_RED_NODE(sibling)) {
if (node->parent->left == node) {
rotate_left(root_ptr, node->parent);
rotate_left(root_ptr, parent);
} else {
rotate_right(root_ptr, node->parent);
rotate_right(root_ptr, parent);
}
node->parent->parent->color = node->parent->color = COLOR_BLACK;
// The rotate shouldn't touch the parent relationship of `node`
parent->parent->color = COLOR_BLACK;
parent->color = COLOR_RED;
sibling = get_sibling(parent, node);
}
if (IS_BLACK_NODE(sibling->left) && IS_BLACK_NODE(sibling->right)) {
node->color = COLOR_BLACK;
if (node != NULL)
node->color = COLOR_BLACK;
sibling->color = COLOR_RED;
repair_after_remove(root_ptr, node->parent);
repair_after_remove(root_ptr, parent->parent, parent);
} else {
if (node->parent->left == node && IS_BLACK_NODE(sibling)) {
rotate_right(root_ptr, sibling);
sibling = get_sibling(node);
sibling->color = COLOR_RED;
sibling->right->color = COLOR_RED;
rotate_left(root_ptr, node->parent);
node->color = get_sibling(node->parent)->color = COLOR_BLACK;
} else if (node->parent->right == node && IS_BLACK_NODE(sibling)) {
rotate_left(root_ptr, sibling);
sibling = get_sibling(node);
sibling->color = COLOR_RED;
sibling->left->color = COLOR_RED;
rotate_right(root_ptr, sibling);
node->color = get_sibling(node->parent)->color = COLOR_BLACK;
}
node->parent->color ^= node->parent->parent->color;
node->parent->parent->color ^= node->parent->color;
node->parent->color ^= node->parent->parent->color;
if (parent->left == node && IS_BLACK_NODE(sibling->right)) {
rotate_right(root_ptr, sibling);
sibling->color = COLOR_RED;
sibling = parent->right;
sibling->color = COLOR_BLACK;
}
if (parent->right == node && IS_BLACK_NODE(sibling->left)) {
rotate_left(root_ptr, sibling);
sibling->color = COLOR_RED;
sibling = parent->left;
sibling->color = COLOR_BLACK;
}
if (parent->left == node) {
rotate_left(root_ptr, parent);
} else {
rotate_right(root_ptr, parent);
}
if (node != NULL)
node->color = COLOR_BLACK;
TreeAlloc *uncle = get_sibling(parent->parent, parent);
if (uncle != NULL)
uncle->color = COLOR_BLACK;
char swap = parent->color;
parent->color = parent->parent->color;
parent->parent->color = swap;
}
}
}
void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) {
char do_repair = 0;
char old_color;
#ifdef DEBUG
printf("====== PRE-REMOVE ======\n");
printf("===== REMOVING =====\n");
@ -370,20 +383,22 @@ void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) {
debug_print_tree(0, *root_ptr);
printf("===== END OF TREES =====\n");
#endif
TreeAlloc *replace;
TreeAlloc *replace, *parent_of_replace;
TreeAlloc *parent = to_remove->parent;
if (!to_remove->left) {
replace = to_remove->right;
parent_of_replace = to_remove->parent;
do_repair = to_remove->color == COLOR_BLACK;
replace_node(root_ptr, to_remove, replace);
} else if (!to_remove->right) {
replace = to_remove->left;
parent_of_replace = to_remove->parent;
do_repair = to_remove->color == COLOR_BLACK;
replace_node(root_ptr, to_remove, replace);
} else {
TreeAlloc *tmp = to_remove->right;
while (tmp->left) tmp = tmp->left;
TreeAlloc *tmp = succ(to_remove);
replace = tmp->right;
parent_of_replace = tmp->parent;
do_repair = tmp->color == COLOR_BLACK;
if (tmp != to_remove->right) {
replace_node(root_ptr, tmp, replace);
@ -399,10 +414,10 @@ void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) {
// Make sure that it doesn't have any tree pointers it shouldn't have.
to_remove->parent = to_remove->left = to_remove->right = NULL;
if (replace && replace->parent == NULL) {
if (replace && parent_of_replace == NULL) {
replace->color = COLOR_BLACK;
} else if (do_repair && replace) {
repair_after_remove(root_ptr, replace);
} else if (do_repair) {
repair_after_remove(root_ptr, parent_of_replace, replace);
}
#ifdef DEBUG
printf("=== POST-REMOVE ===\n");

Loading…
Cancel
Save