|
|
@ -14,14 +14,15 @@ int debug_tree_black_height(TreeAlloc *node) { |
|
|
|
return ((node->color == COLOR_BLACK) ? 1 : 0) + debug_tree_black_height(node->left); |
|
|
|
} |
|
|
|
|
|
|
|
void debug_print_tree(int indent, void *p) { |
|
|
|
void debug_print_tree(int indent, void *p, int safe) { |
|
|
|
TreeAlloc *node = (TreeAlloc*) p; |
|
|
|
if (node != NULL) { |
|
|
|
int bad = debug_tree_black_height(node->left) != debug_tree_black_height(node->right); |
|
|
|
bad |= node->color == COLOR_RED && ((node->left != NULL && node->left->color == COLOR_RED) || |
|
|
|
(node->right != NULL && node->right->color == COLOR_RED) || (node->parent != NULL && |
|
|
|
node->parent->color == COLOR_RED)); |
|
|
|
debug_print_tree(indent + 1, node->left); |
|
|
|
bad &= !safe; |
|
|
|
debug_print_tree(indent + 1, node->left, safe); |
|
|
|
for (int ii = 0; ii < indent; ii++) { printf(" "); } |
|
|
|
if (node->color == COLOR_RED) { printf("\e[31m"); } |
|
|
|
else if (bad) { printf("\e[30m]"); } |
|
|
@ -29,7 +30,7 @@ void debug_print_tree(int indent, void *p) { |
|
|
|
printf("%p %lu\n", node, node->size); |
|
|
|
printf("\e[37m"); |
|
|
|
if (bad) { printf("\e[40m"); } |
|
|
|
debug_print_tree(indent + 1, node->right); |
|
|
|
debug_print_tree(indent + 1, node->right, safe); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -230,7 +231,7 @@ void insert_singleton(TreeAlloc **root_ptr, TreeAlloc *to_insert) { |
|
|
|
#ifdef DEBUG |
|
|
|
printf("= PRE-INSERT-SINGLETON =\n"); |
|
|
|
printf("===== CURRENT TREE =====\n"); |
|
|
|
debug_print_tree(0, *root_ptr); |
|
|
|
debug_print_tree(0, *root_ptr, 0); |
|
|
|
printf("===== END OF TREES =====\n"); |
|
|
|
#endif |
|
|
|
*root_ptr = to_insert; |
|
|
@ -239,7 +240,7 @@ void insert_singleton(TreeAlloc **root_ptr, TreeAlloc *to_insert) { |
|
|
|
#ifdef DEBUG |
|
|
|
printf("= POST-INSERT-SINGLETON =\n"); |
|
|
|
printf("===== CURRENT TREE =====\n"); |
|
|
|
debug_print_tree(0, *root_ptr); |
|
|
|
debug_print_tree(0, *root_ptr, 0); |
|
|
|
printf("===== END OF TREES =====\n"); |
|
|
|
#endif |
|
|
|
} |
|
|
@ -248,9 +249,9 @@ void insert_right(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* after) |
|
|
|
#ifdef DEBUG |
|
|
|
printf("=== PRE-INSERT-RIGHT ===\n"); |
|
|
|
printf("===== INSERTING =====\n"); |
|
|
|
debug_print_tree(0, to_insert); |
|
|
|
debug_print_tree(0, to_insert, 0); |
|
|
|
printf("===== CURRENT TREE =====\n"); |
|
|
|
debug_print_tree(0, *root_ptr); |
|
|
|
debug_print_tree(0, *root_ptr, 0); |
|
|
|
printf("===== END OF TREES =====\n"); |
|
|
|
#endif |
|
|
|
if (after->right != NULL) { |
|
|
@ -269,7 +270,7 @@ void insert_right(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* after) |
|
|
|
#ifdef DEBUG |
|
|
|
printf("== POST-INSERT-FIXUP ===\n"); |
|
|
|
printf("===== CURRENT TREE =====\n"); |
|
|
|
debug_print_tree(0, *root_ptr); |
|
|
|
debug_print_tree(0, *root_ptr, 0); |
|
|
|
printf("===== END OF TREES =====\n"); |
|
|
|
#endif |
|
|
|
} |
|
|
@ -278,9 +279,9 @@ void insert_left(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* before) |
|
|
|
#ifdef DEBUG |
|
|
|
printf("=== PRE-INSERT-LEFT ====\n"); |
|
|
|
printf("===== INSERTING =====\n"); |
|
|
|
debug_print_tree(0, to_insert); |
|
|
|
debug_print_tree(0, to_insert, 0); |
|
|
|
printf("===== CURRENT TREE =====\n"); |
|
|
|
debug_print_tree(0, *root_ptr); |
|
|
|
debug_print_tree(0, *root_ptr, 0); |
|
|
|
printf("===== END OF TREES =====\n"); |
|
|
|
#endif |
|
|
|
if (before->left != NULL) { |
|
|
@ -299,7 +300,7 @@ void insert_left(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* before) |
|
|
|
#ifdef DEBUG |
|
|
|
printf("== POST-INSERT-FIXUP ===\n"); |
|
|
|
printf("===== CURRENT TREE =====\n"); |
|
|
|
debug_print_tree(0, *root_ptr); |
|
|
|
debug_print_tree(0, *root_ptr, 0); |
|
|
|
printf("===== END OF TREES =====\n"); |
|
|
|
#endif |
|
|
|
} |
|
|
@ -318,7 +319,7 @@ void replace_node(TreeAlloc **root_ptr, TreeAlloc *node, TreeAlloc *replace) { |
|
|
|
|
|
|
|
void repair_after_remove(TreeAlloc **root_ptr, TreeAlloc *parent, TreeAlloc *node) { |
|
|
|
#ifdef DEBUG |
|
|
|
printf("delete fixup at %p\n", node); |
|
|
|
printf("delete fixup at %p -> %p\n", parent, node); |
|
|
|
#endif |
|
|
|
// In theory, the last two conditions should be the same ... |
|
|
|
if (IS_RED_NODE(node) || (node != NULL && node == *root_ptr)) { |
|
|
@ -326,7 +327,7 @@ void repair_after_remove(TreeAlloc **root_ptr, TreeAlloc *parent, TreeAlloc *nod |
|
|
|
} else { |
|
|
|
TreeAlloc *sibling = get_sibling(parent, node); |
|
|
|
if (IS_RED_NODE(sibling)) { |
|
|
|
if (node->parent->left == node) { |
|
|
|
if (parent->left == node) { |
|
|
|
rotate_left(root_ptr, parent); |
|
|
|
} else { |
|
|
|
rotate_right(root_ptr, parent); |
|
|
@ -377,34 +378,45 @@ void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) { |
|
|
|
char old_color; |
|
|
|
#ifdef DEBUG |
|
|
|
printf("====== PRE-REMOVE ======\n"); |
|
|
|
printf("===== REMOVING =====\n"); |
|
|
|
debug_print_tree(0, to_remove); |
|
|
|
printf("======= REMOVING =======\n"); |
|
|
|
debug_print_tree(0, to_remove, 0); |
|
|
|
printf("===== CURRENT TREE =====\n"); |
|
|
|
debug_print_tree(0, *root_ptr); |
|
|
|
debug_print_tree(0, *root_ptr, 0); |
|
|
|
printf("===== END OF TREES =====\n"); |
|
|
|
#endif |
|
|
|
TreeAlloc *replace, *parent_of_replace; |
|
|
|
TreeAlloc *parent = to_remove->parent; |
|
|
|
if (!to_remove->left) { |
|
|
|
#ifdef DEBUG |
|
|
|
printf("code path 1l\n"); |
|
|
|
#endif |
|
|
|
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) { |
|
|
|
#ifdef DEBUG |
|
|
|
printf("code path 1r\n"); |
|
|
|
#endif |
|
|
|
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 { |
|
|
|
#ifdef DEBUG |
|
|
|
printf("code path 2\n"); |
|
|
|
#endif |
|
|
|
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); |
|
|
|
tmp->right = to_remove->right; |
|
|
|
to_remove->right->parent = tmp; |
|
|
|
} |
|
|
|
parent_of_replace = tmp->parent; |
|
|
|
} else { |
|
|
|
parent_of_replace = tmp; |
|
|
|
} |
|
|
|
replace_node(root_ptr, to_remove, tmp); |
|
|
|
tmp->color = to_remove->color; |
|
|
|
tmp->left = to_remove->left; |
|
|
@ -414,6 +426,13 @@ 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; |
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
printf("==== PRE-REMOVE-FIXUP ===\n"); |
|
|
|
printf("===== CURRENT TREE =====\n"); |
|
|
|
debug_print_tree(0, *root_ptr, 1); |
|
|
|
printf("===== END OF TREES =====\n"); |
|
|
|
printf("considering fixing up %p -> %p\n", parent_of_replace, replace); |
|
|
|
#endif |
|
|
|
if (replace && parent_of_replace == NULL) { |
|
|
|
replace->color = COLOR_BLACK; |
|
|
|
} else if (parent_of_replace != NULL && do_repair) { |
|
|
@ -422,7 +441,7 @@ void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) { |
|
|
|
#ifdef DEBUG |
|
|
|
printf("=== POST-REMOVE ===\n"); |
|
|
|
printf("===== CURRENT TREE =====\n"); |
|
|
|
debug_print_tree(0, *root_ptr); |
|
|
|
debug_print_tree(0, *root_ptr, 0); |
|
|
|
printf("===== END OF TREES =====\n"); |
|
|
|
#endif |
|
|
|
} |
|
|
@ -455,9 +474,9 @@ int add_new_region(Arena *arena, uintptr_t size, uintptr_t padding, uintptr_t al |
|
|
|
#ifdef DEBUG |
|
|
|
printf("= POST-REGION-CREATION =\n"); |
|
|
|
printf("==== FREESPACE TREE ====\n"); |
|
|
|
debug_print_tree(0, arena->root_freespace); |
|
|
|
debug_print_tree(0, arena->root_freespace, 0); |
|
|
|
printf("==== TREEALLOC TREE ====\n"); |
|
|
|
debug_print_tree(0, arena->root_treealloc); |
|
|
|
debug_print_tree(0, arena->root_treealloc, 0); |
|
|
|
printf("===== END OF TREES =====\n"); |
|
|
|
#endif |
|
|
|
return 1; |
|
|
@ -467,9 +486,9 @@ void unalloc(Arena *arena, void *addr) { |
|
|
|
#ifdef DEBUG |
|
|
|
printf("==== UNALLOCATING ====\n"); |
|
|
|
printf("=== FREESPACE TREE ===\n"); |
|
|
|
debug_print_tree(0, arena->root_freespace); |
|
|
|
debug_print_tree(0, arena->root_freespace, 0); |
|
|
|
printf("=== TREEALLOC TREE ===\n"); |
|
|
|
debug_print_tree(0, arena->root_treealloc); |
|
|
|
debug_print_tree(0, arena->root_treealloc, 0); |
|
|
|
printf("==== END OF TREES ====\n"); |
|
|
|
#endif |
|
|
|
if (arena->root_treealloc == NULL) { |
|
|
@ -526,9 +545,9 @@ void *alloc(Arena *arena, uintptr_t size, uintptr_t align) { |
|
|
|
#ifdef DEBUG |
|
|
|
printf("==== ALLOCATING =====\n"); |
|
|
|
printf("=== FREESPACE TREE ===\n"); |
|
|
|
debug_print_tree(0, arena->root_freespace); |
|
|
|
debug_print_tree(0, arena->root_freespace, 0); |
|
|
|
printf("=== TREEALLOC TREE ===\n"); |
|
|
|
debug_print_tree(0, arena->root_treealloc); |
|
|
|
debug_print_tree(0, arena->root_treealloc, 0); |
|
|
|
printf("==== END OF TREES ====\n"); |
|
|
|
#endif |
|
|
|
if (arena->root_freespace == NULL) { |
|
|
|