|
|
@ -7,7 +7,9 @@ TreeAlloc *insert_node_at(void *address, uintptr_t padding, uintptr_t align, uin |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
// Search for the node whose allocated region contains an address. |
|
|
|
/* |
|
|
|
* Search for the node whose allocated region contains an address. |
|
|
|
*/ |
|
|
|
TreeAlloc *search_by_address(TreeAlloc *root, void *address) { |
|
|
|
TreeAlloc *head = root; |
|
|
|
while (1) { |
|
|
@ -31,9 +33,11 @@ static uintptr_t effective_size(TreeAlloc *head, uintptr_t padding, uintptr_t al |
|
|
|
return head->size - (align_after(head + padding, align) - (void*) head); |
|
|
|
} |
|
|
|
|
|
|
|
// This is the most optimistic estimate of size that we can use which also preserves the ordering over |
|
|
|
// the tree. I had planned to use effective_size before I realized that it would break the tree |
|
|
|
// ordering. |
|
|
|
/* |
|
|
|
* This is the most optimistic estimate of size that we can use which also preserves the ordering over |
|
|
|
* the tree. I had planned to use effective_size before I realized that it would break the tree |
|
|
|
* ordering. |
|
|
|
*/ |
|
|
|
static uintptr_t pessimistic_size(TreeAlloc *head, uintptr_t padding, uintptr_t align) { |
|
|
|
return head->size - padding - align + 1; |
|
|
|
} |
|
|
@ -58,6 +62,99 @@ TreeAlloc *search_by_size(TreeAlloc *root, uintptr_t padding, uintptr_t align, u |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
TreeAlloc *get_sibling(TreeAlloc *ta) { |
|
|
|
TreeAlloc *p = ta->parent; |
|
|
|
if (!p) |
|
|
|
return NULL; |
|
|
|
else if (p->left == ta) |
|
|
|
return p->right; |
|
|
|
else |
|
|
|
return p->left; |
|
|
|
} |
|
|
|
|
|
|
|
void rotate_left(TreeAlloc *ta) { |
|
|
|
TreeAlloc *parent, *tmp; |
|
|
|
|
|
|
|
parent = ta->parent; |
|
|
|
tmp = ta->right; |
|
|
|
if (!tmp) return; |
|
|
|
|
|
|
|
ta->right = tmp->left; |
|
|
|
tmp->left = ta; |
|
|
|
ta->parent = tmp; |
|
|
|
|
|
|
|
if (ta->right) ta->right->parent = ta; |
|
|
|
|
|
|
|
if (parent) { |
|
|
|
if (ta == parent->left) |
|
|
|
parent->left = tmp; |
|
|
|
else |
|
|
|
parent->right = tmp; |
|
|
|
} |
|
|
|
tmp->parent = parent; |
|
|
|
} |
|
|
|
|
|
|
|
void rotate_right(TreeAlloc *ta) { |
|
|
|
TreeAlloc *parent, *tmp; |
|
|
|
|
|
|
|
parent = ta->parent; |
|
|
|
tmp = ta->left; |
|
|
|
if (!tmp) return; |
|
|
|
|
|
|
|
ta->left = tmp->right; |
|
|
|
tmp->right = ta; |
|
|
|
ta->parent = tmp; |
|
|
|
|
|
|
|
if (ta->left) ta->left->parent = ta; |
|
|
|
|
|
|
|
if (parent) { |
|
|
|
if (ta == parent->left) |
|
|
|
parent->left = tmp; |
|
|
|
else |
|
|
|
parent->right = tmp; |
|
|
|
} |
|
|
|
tmp->parent = parent; |
|
|
|
} |
|
|
|
|
|
|
|
void repair_tree_after_insert(TreeAlloc *ta) { |
|
|
|
TreeAlloc *parent = ta->parent; |
|
|
|
|
|
|
|
if (parent == NULL) { |
|
|
|
ta->color = COLOR_BLACK; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
TreeAlloc *grandparent = parent->parent; |
|
|
|
TreeAlloc *uncle = get_sibling(parent); |
|
|
|
|
|
|
|
if (parent->color == COLOR_RED) { |
|
|
|
if (uncle != NULL && uncle->color == COLOR_RED) { |
|
|
|
parent->color = COLOR_BLACK; |
|
|
|
uncle->color = COLOR_BLACK; |
|
|
|
grandparent->color = COLOR_RED; |
|
|
|
repair_tree_after_insert(grandparent); |
|
|
|
} else { |
|
|
|
if (ta == parent->left && parent == grandparent->left) { |
|
|
|
rotate_left(parent); |
|
|
|
ta = ta->left; |
|
|
|
} else { |
|
|
|
rotate_right(parent); |
|
|
|
ta = ta->right; |
|
|
|
} |
|
|
|
|
|
|
|
parent = ta->parent; |
|
|
|
grandparent = parent->parent; |
|
|
|
if (ta == parent->left) { |
|
|
|
rotate_right(grandparent); |
|
|
|
} else { |
|
|
|
rotate_left(grandparent); |
|
|
|
} |
|
|
|
parent->color = COLOR_BLACK; |
|
|
|
grandparent->color = COLOR_RED; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// TODO: Rewrite for self-balancing tree. |
|
|
|
void remove_node(TreeAlloc** root_ptr, TreeAlloc* node) { |
|
|
|
TreeAlloc *replace = NULL; |
|
|
@ -84,14 +181,14 @@ void remove_node(TreeAlloc** root_ptr, TreeAlloc* node) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Inserts a node into an empty tree. |
|
|
|
// TODO: Rewrite for self-balancing tree. |
|
|
|
void insert_singleton(TreeAlloc **root_ptr, TreeAlloc *to_insert) { |
|
|
|
*root_ptr = to_insert; |
|
|
|
to_insert->parent = NULL; |
|
|
|
repair_tree_after_insert(to_insert); |
|
|
|
} |
|
|
|
|
|
|
|
// TODO: Rewrite for self-balancing tree. |
|
|
|
void insert_right(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* after) { |
|
|
|
if (after->right != NULL) { |
|
|
|
after->right->parent = to_insert; |
|
|
@ -99,9 +196,9 @@ void insert_right(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* after) |
|
|
|
} |
|
|
|
after->right = to_insert; |
|
|
|
to_insert->parent = after; |
|
|
|
repair_tree_after_insert(to_insert); |
|
|
|
} |
|
|
|
|
|
|
|
// TODO: Rewrite for self-balancing tree. |
|
|
|
void insert_left(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* before) { |
|
|
|
if (before->left != NULL) { |
|
|
|
before->left->parent = to_insert; |
|
|
@ -109,6 +206,7 @@ void insert_left(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* before) |
|
|
|
} |
|
|
|
before->left = to_insert; |
|
|
|
to_insert->parent = before; |
|
|
|
repair_tree_after_insert(to_insert); |
|
|
|
} |
|
|
|
|
|
|
|
void unalloc(Arena *arena, void *addr) { |
|
|
|