Browse Source

Hopefully fixed a few bugs

Thomas Johnson 5 months ago
parent
commit
a3ae7eb75c
2 changed files with 53 additions and 38 deletions
  1. 1
    1
      allocator_internal.h
  2. 52
    37
      tree_alloc.c

+ 1
- 1
allocator_internal.h View File

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

+ 52
- 37
tree_alloc.c View File

@@ -122,8 +122,7 @@ TreeAlloc *pred(TreeAlloc *el) {
122 122
 	return el->parent;
123 123
 }
124 124
 
125
-TreeAlloc *get_sibling(TreeAlloc *ta) {
126
-	TreeAlloc *p = ta->parent;
125
+TreeAlloc *get_sibling(TreeAlloc *p, TreeAlloc *ta) {
127 126
 	if (!p)
128 127
 		return NULL;
129 128
 	else if (p->left == ta)
@@ -190,7 +189,7 @@ void repair_tree_after_insert(TreeAlloc **root_ptr, TreeAlloc *ta) {
190 189
 	} else if (IS_BLACK_NODE(parent)) {
191 190
 		return;
192 191
 	} else {
193
-		TreeAlloc *uncle = get_sibling(parent);
192
+		TreeAlloc *uncle = get_sibling(parent->parent, parent);
194 193
 		TreeAlloc *grandparent = parent->parent;
195 194
 
196 195
 		if (IS_RED_NODE(uncle)) {
@@ -317,51 +316,65 @@ void replace_node(TreeAlloc **root_ptr, TreeAlloc *node, TreeAlloc *replace) {
317 316
 	if (replace) replace->parent = node->parent;
318 317
 }
319 318
 
320
-void repair_after_remove(TreeAlloc **root_ptr, TreeAlloc *node) {
321
-	if (IS_RED_NODE(node)) {
319
+void repair_after_remove(TreeAlloc **root_ptr, TreeAlloc *parent, TreeAlloc *node) {
320
+#ifdef DEBUG
321
+  printf("delete fixup at %p\n", node);
322
+#endif
323
+  // In theory, the last two conditions should be the same ...
324
+	if (IS_RED_NODE(node) || (node != NULL && node == *root_ptr)) {
322 325
 		node->color = COLOR_BLACK;
323 326
 	} else {
324
-		TreeAlloc *sibling = get_sibling(node);
327
+		TreeAlloc *sibling = get_sibling(parent, node);
325 328
 		if (IS_RED_NODE(sibling)) {
326 329
 			if (node->parent->left == node) {
327
-				rotate_left(root_ptr, node->parent);
330
+				rotate_left(root_ptr, parent);
328 331
 			} else {
329
-				rotate_right(root_ptr, node->parent);
332
+				rotate_right(root_ptr, parent);
330 333
 			}
331
-			node->parent->parent->color = node->parent->color = COLOR_BLACK;
334
+      // The rotate shouldn't touch the parent relationship of `node`
335
+			parent->parent->color = COLOR_BLACK;
336
+      parent->color = COLOR_RED;
337
+      sibling = get_sibling(parent, node);
332 338
 		} 
333 339
 
334 340
 		if (IS_BLACK_NODE(sibling->left) && IS_BLACK_NODE(sibling->right)) {
335
-			node->color = COLOR_BLACK;
341
+      if (node != NULL)
342
+        node->color = COLOR_BLACK;
336 343
 			sibling->color = COLOR_RED;
337
-			repair_after_remove(root_ptr, node->parent);
344
+			repair_after_remove(root_ptr, parent->parent, parent);
338 345
 		} else {
339
-			if (node->parent->left == node && IS_BLACK_NODE(sibling)) {
340
-				rotate_right(root_ptr, sibling);
341
-				sibling = get_sibling(node);
342
-				sibling->color = COLOR_RED;
343
-				sibling->right->color = COLOR_RED;
344
-
345
-				rotate_left(root_ptr, node->parent);
346
-				node->color = get_sibling(node->parent)->color = COLOR_BLACK;
347
-			} else if (node->parent->right == node && IS_BLACK_NODE(sibling)) {
348
-				rotate_left(root_ptr, sibling);
349
-				sibling = get_sibling(node);
350
-				sibling->color = COLOR_RED;
351
-				sibling->left->color = COLOR_RED;
352
-
353
-				rotate_right(root_ptr, sibling);
354
-				node->color = get_sibling(node->parent)->color = COLOR_BLACK;
355
-			}
356
-			node->parent->color ^= node->parent->parent->color;
357
-			node->parent->parent->color ^= node->parent->color;
358
-			node->parent->color ^= node->parent->parent->color;
346
+      if (parent->left == node && IS_BLACK_NODE(sibling->right)) {
347
+        rotate_right(root_ptr, sibling);
348
+        sibling->color = COLOR_RED;
349
+        sibling = parent->right;
350
+        sibling->color = COLOR_BLACK;
351
+      }
352
+      if (parent->right == node && IS_BLACK_NODE(sibling->left)) {
353
+        rotate_left(root_ptr, sibling);
354
+        sibling->color = COLOR_RED;
355
+        sibling = parent->left;
356
+        sibling->color = COLOR_BLACK;
357
+      }
358
+      if (parent->left == node) {
359
+        rotate_left(root_ptr, parent);
360
+      } else {
361
+        rotate_right(root_ptr, parent);
362
+      }
363
+      if (node != NULL)
364
+        node->color = COLOR_BLACK;
365
+      TreeAlloc *uncle = get_sibling(parent->parent, parent);
366
+      if (uncle != NULL)
367
+        uncle->color = COLOR_BLACK;
368
+      char swap = parent->color;
369
+      parent->color = parent->parent->color;
370
+      parent->parent->color = swap;
359 371
 		}
360 372
 	}
361 373
 }
362 374
 
363 375
 void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) {
364 376
 	char do_repair = 0;
377
+  char old_color;
365 378
 #ifdef DEBUG
366 379
 	printf("====== PRE-REMOVE ======\n");
367 380
 	printf("===== REMOVING =====\n");
@@ -370,20 +383,22 @@ void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) {
370 383
 	debug_print_tree(0, *root_ptr);
371 384
 	printf("===== END OF TREES =====\n");
372 385
 #endif
373
-	TreeAlloc *replace;
386
+	TreeAlloc *replace, *parent_of_replace;
374 387
 	TreeAlloc *parent = to_remove->parent;
375 388
 	if (!to_remove->left) {
376 389
 		replace = to_remove->right;
390
+    parent_of_replace = to_remove->parent;
377 391
 		do_repair = to_remove->color == COLOR_BLACK;
378 392
 		replace_node(root_ptr, to_remove, replace);
379 393
 	} else if (!to_remove->right) {
380 394
 		replace = to_remove->left;
395
+    parent_of_replace = to_remove->parent;
381 396
 		do_repair = to_remove->color == COLOR_BLACK;
382 397
 		replace_node(root_ptr, to_remove, replace);
383 398
 	} else {
384
-		TreeAlloc *tmp = to_remove->right;
385
-		while (tmp->left) tmp = tmp->left;
399
+		TreeAlloc *tmp = succ(to_remove);
386 400
 		replace = tmp->right;
401
+    parent_of_replace = tmp->parent;
387 402
 		do_repair = tmp->color == COLOR_BLACK;
388 403
 		if (tmp != to_remove->right) {
389 404
 			replace_node(root_ptr, tmp, replace);
@@ -399,10 +414,10 @@ void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) {
399 414
 	// Make sure that it doesn't have any tree pointers it shouldn't have.
400 415
 	to_remove->parent = to_remove->left = to_remove->right = NULL;
401 416
 
402
-	if (replace && replace->parent == NULL) {
417
+	if (replace && parent_of_replace == NULL) {
403 418
 		replace->color = COLOR_BLACK;
404
-	} else if (do_repair && replace) {
405
-		repair_after_remove(root_ptr, replace);
419
+	} else if (do_repair) {
420
+		repair_after_remove(root_ptr, parent_of_replace, replace);
406 421
 	}
407 422
 #ifdef DEBUG
408 423
 	printf("=== POST-REMOVE ===\n");

Loading…
Cancel
Save