You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
5.2 KiB

  1. #include <stddef.h>
  2. #include "allocator_internal.h"
  3. TreeAlloc *insert_node_at(void *address, uintptr_t padding, uintptr_t align, uintptr_t size) {
  4. return NULL;
  5. }
  6. /*
  7. * Search for the node whose allocated region contains an address.
  8. */
  9. TreeAlloc *search_by_address(TreeAlloc *root, void *address) {
  10. TreeAlloc *head = root;
  11. while (1) {
  12. if (head > (TreeAlloc*) address) {
  13. if (head->left == NULL) {
  14. return NULL;
  15. } else {
  16. head = head->left;
  17. }
  18. } else {
  19. if (head->right == NULL || head->right > (TreeAlloc*) address) {
  20. return head;
  21. } else {
  22. head = head->right;
  23. }
  24. }
  25. }
  26. }
  27. static uintptr_t effective_size(TreeAlloc *head, uintptr_t padding, uintptr_t align) {
  28. return head->size - (align_after(head + padding, align) - (void*) head);
  29. }
  30. /*
  31. * This is the most optimistic estimate of size that we can use which also preserves the ordering over
  32. * the tree. I had planned to use effective_size before I realized that it would break the tree
  33. * ordering.
  34. */
  35. static uintptr_t pessimistic_size(TreeAlloc *head, uintptr_t padding, uintptr_t align) {
  36. return head->size - padding - align + 1;
  37. }
  38. TreeAlloc *search_by_size(TreeAlloc *root, uintptr_t padding, uintptr_t align, uintptr_t size) {
  39. TreeAlloc *head = root;
  40. while (1) {
  41. uintptr_t esize = pessimistic_size(head, padding, align);
  42. if (esize < size) {
  43. if (head->right == NULL) {
  44. return NULL;
  45. } else {
  46. head = head->right;
  47. }
  48. } else {
  49. if (head->left == NULL || pessimistic_size(head->left, padding, align) < size) {
  50. return head;
  51. } else {
  52. head = head->left;
  53. }
  54. }
  55. }
  56. }
  57. TreeAlloc *get_sibling(TreeAlloc *ta) {
  58. TreeAlloc *p = ta->parent;
  59. if (!p)
  60. return NULL;
  61. else if (p->left == ta)
  62. return p->right;
  63. else
  64. return p->left;
  65. }
  66. void rotate_left(TreeAlloc *ta) {
  67. TreeAlloc *parent, *tmp;
  68. parent = ta->parent;
  69. tmp = ta->right;
  70. if (!tmp) return;
  71. ta->right = tmp->left;
  72. tmp->left = ta;
  73. ta->parent = tmp;
  74. if (ta->right) ta->right->parent = ta;
  75. if (parent) {
  76. if (ta == parent->left)
  77. parent->left = tmp;
  78. else
  79. parent->right = tmp;
  80. }
  81. tmp->parent = parent;
  82. }
  83. void rotate_right(TreeAlloc *ta) {
  84. TreeAlloc *parent, *tmp;
  85. parent = ta->parent;
  86. tmp = ta->left;
  87. if (!tmp) return;
  88. ta->left = tmp->right;
  89. tmp->right = ta;
  90. ta->parent = tmp;
  91. if (ta->left) ta->left->parent = ta;
  92. if (parent) {
  93. if (ta == parent->left)
  94. parent->left = tmp;
  95. else
  96. parent->right = tmp;
  97. }
  98. tmp->parent = parent;
  99. }
  100. void repair_tree_after_insert(TreeAlloc *ta) {
  101. TreeAlloc *parent = ta->parent;
  102. if (parent == NULL) {
  103. ta->color = COLOR_BLACK;
  104. return;
  105. }
  106. TreeAlloc *grandparent = parent->parent;
  107. TreeAlloc *uncle = get_sibling(parent);
  108. if (parent->color == COLOR_RED) {
  109. if (uncle != NULL && uncle->color == COLOR_RED) {
  110. parent->color = COLOR_BLACK;
  111. uncle->color = COLOR_BLACK;
  112. grandparent = COLOR_RED;
  113. repair_tree(grandparent);
  114. } else {
  115. if (ta == parent->left && parent == grandparent->left) {
  116. rotate_left(parent);
  117. ta = ta->left;
  118. } else {
  119. rotate_right(parent);
  120. ta = ta->right;
  121. }
  122. parent = ta->parent;
  123. grandparent = parent->parent;
  124. if (ta == parent->left) {
  125. rotate_right(grandparent);
  126. } else {
  127. rotate_left(grandparent);
  128. }
  129. parent->color = COLOR_BLACK;
  130. grandparent->color = COLOR_RED;
  131. }
  132. }
  133. }
  134. // TODO: Rewrite for self-balancing tree.
  135. void remove_node(TreeAlloc** root_ptr, TreeAlloc* node) {
  136. TreeAlloc *replace = NULL;
  137. if (node->left == NULL) {
  138. replace = node->right;
  139. } else if (node->right != NULL) {
  140. replace = node->right;
  141. TreeAlloc *head = node->left;
  142. while (head->right != NULL) {
  143. head = head->right;
  144. }
  145. head->right = head->parent->right;
  146. head->right->parent = head;
  147. }
  148. if (node->parent == NULL) {
  149. replace->parent = NULL;
  150. *root_ptr = replace;
  151. } else {
  152. if (node == node->parent->left) {
  153. node->parent->left = replace;
  154. } else {
  155. node->parent->right = replace;
  156. }
  157. }
  158. }
  159. // Inserts a node into an empty tree.
  160. void insert_singleton(TreeAlloc **root_ptr, TreeAlloc *to_insert) {
  161. *root_ptr = to_insert;
  162. to_insert->parent = NULL;
  163. repair_tree_after_insert(to_insert);
  164. }
  165. void insert_right(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* after) {
  166. if (after->right != NULL) {
  167. after->right->parent = to_insert;
  168. to_insert->right = after->right;
  169. }
  170. after->right = to_insert;
  171. to_insert->parent = after;
  172. repair_tree_after_insert(to_insert);
  173. }
  174. void insert_left(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* before) {
  175. if (before->left != NULL) {
  176. before->left->parent = to_insert;
  177. to_insert->left = before->left;
  178. }
  179. before->left = to_insert;
  180. to_insert->parent = before;
  181. repair_tree_after_insert(to_insert);
  182. }
  183. void *unalloc(Arena *arena, void *addr) {
  184. if (arena->root_treealloc == NULL) {
  185. arena->error("attempt to unallocate when there are no allocations!");
  186. }
  187. TreeAlloc *node = search_by_address(arena->root_treealloc, addr);
  188. // TODO
  189. }
  190. void *alloc(Arena arena, uintptr_t size, uintptr_t align) {
  191. // TODO
  192. return NULL;
  193. }
  194. void *alloc_growable(Arena arena, uintptr_t size, uintptr_t align) {
  195. // TODO
  196. return NULL;
  197. }