Browse Source

Fixed size underflow

Cameron Weinfurt 5 months ago
parent
commit
2e23ecc609
2 changed files with 102 additions and 86 deletions
  1. 1
    1
      main.c
  2. 101
    85
      tree_alloc.c

+ 1
- 1
main.c View File

@@ -129,7 +129,7 @@ int main() {
129 129
   };
130 130
   dummy.next = &dummy;
131 131
   dummy.prev = &dummy;
132
-  for (int ii = 0; ii < 100; ii++) {
132
+  for (int ii = 0; ii < 400; ii++) {
133 133
     act(&dummy, &arena);
134 134
   }
135 135
 	return 0;

+ 101
- 85
tree_alloc.c View File

@@ -7,6 +7,9 @@
7 7
 #ifdef DEBUG
8 8
 #include <stdio.h>
9 9
 
10
+#define IS_BLACK_NODE(n) (n == NULL || n->color == COLOR_BLACK)
11
+#define IS_RED_NODE(n) (n != NULL && n->color == COLOR_RED)
12
+
10 13
 int debug_tree_black_height(TreeAlloc *node) {
11 14
 	if (node == NULL) {
12 15
 		return 1;
@@ -14,22 +17,37 @@ int debug_tree_black_height(TreeAlloc *node) {
14 17
 	return ((node->color == COLOR_BLACK) ? 1 : 0) + debug_tree_black_height(node->left);
15 18
 }
16 19
 
20
+void debug_print_node(int indent, TreeAlloc *node, int bad) {
21
+	for (int ii = 0; ii < indent; ii++) 
22
+		printf("  ");
23
+
24
+	if (node->color == COLOR_RED) 
25
+		printf("\e[31m");
26
+	else if (bad) 
27
+		printf("\e[30m]");
28
+
29
+	if (bad)
30
+		printf("\e[43m");
31
+
32
+	printf("%p %lu\n", node, node->size);
33
+	printf("\e[37m");
34
+
35
+	if (bad) 
36
+		printf("\e[40m");
37
+
38
+}
39
+
17 40
 void debug_print_tree(int indent, void *p, int safe) {
18 41
 	TreeAlloc *node = (TreeAlloc*) p;
19 42
 	if (node != NULL) {
20 43
 		int bad = debug_tree_black_height(node->left) != debug_tree_black_height(node->right);
21
-		bad |= node->color == COLOR_RED && ((node->left != NULL && node->left->color == COLOR_RED) ||
22
-				(node->right != NULL && node->right->color == COLOR_RED) || (node->parent != NULL &&
23
-					node->parent->color == COLOR_RED));
24
-    bad &= !safe;
44
+		bad |= IS_RED_NODE(node) && (
45
+			 IS_RED_NODE(node->left) || 
46
+			 IS_RED_NODE(node->right) || 
47
+			 IS_RED_NODE(node->parent) );
48
+		bad &= !safe;
25 49
 		debug_print_tree(indent + 1, node->left, safe);
26
-		for (int ii = 0; ii < indent; ii++) { printf("  "); }
27
-		if (node->color == COLOR_RED) { printf("\e[31m"); }
28
-    else if (bad) { printf("\e[30m]"); }
29
-		if (bad) { printf("\e[43m"); }
30
-		printf("%p %lu\n", node, node->size);
31
-		printf("\e[37m");
32
-		if (bad) { printf("\e[40m"); }
50
+		debug_print_node(indent, node, bad);
33 51
 		debug_print_tree(indent + 1, node->right, safe);
34 52
 	}
35 53
 }
@@ -180,9 +198,6 @@ void rotate_right(TreeAlloc **root_ptr, TreeAlloc *ta) {
180 198
 	}
181 199
 }
182 200
 
183
-#define IS_BLACK_NODE(n) (n == NULL || n->color == COLOR_BLACK)
184
-#define IS_RED_NODE(n) (n != NULL && n->color == COLOR_RED)
185
-
186 201
 void repair_tree_after_insert(TreeAlloc **root_ptr, TreeAlloc *ta) {
187 202
 	TreeAlloc *parent = ta->parent;
188 203
 	if (ta == *root_ptr) {
@@ -249,24 +264,24 @@ void insert_right(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* after)
249 264
 #ifdef DEBUG
250 265
 	printf("=== PRE-INSERT-RIGHT ===\n");
251 266
 	printf("===== INSERTING =====\n");
252
-	debug_print_tree(0, to_insert, 0);
267
+	debug_print_node(0, to_insert, 0);
253 268
 	printf("===== CURRENT TREE =====\n");
254 269
 	debug_print_tree(0, *root_ptr, 0);
255 270
 	printf("===== END OF TREES =====\n");
256 271
 #endif
257
-  if (after->right != NULL) {
258
-    after = after->right;
259
-    while (after->left != NULL) {
260
-      after = after->left;
261
-    }
262
-    after->left = to_insert;
263
-    to_insert->parent = after;
264
-  } else {
265
-    after->right = to_insert;
266
-    to_insert->parent = after;
267
-  }
268
-  to_insert->color = COLOR_RED;
269
-  repair_tree_after_insert(root_ptr, to_insert);
272
+	if (after->right != NULL) {
273
+		after = after->right;
274
+		while (after->left != NULL) {
275
+			after = after->left;
276
+		}
277
+		after->left = to_insert;
278
+		to_insert->parent = after;
279
+	} else {
280
+		after->right = to_insert;
281
+		to_insert->parent = after;
282
+	}
283
+	to_insert->color = COLOR_RED;
284
+	repair_tree_after_insert(root_ptr, to_insert);
270 285
 #ifdef DEBUG
271 286
 	printf("== POST-INSERT-FIXUP ===\n");
272 287
 	printf("===== CURRENT TREE =====\n");
@@ -284,19 +299,19 @@ void insert_left(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* before)
284 299
 	debug_print_tree(0, *root_ptr, 0);
285 300
 	printf("===== END OF TREES =====\n");
286 301
 #endif
287
-  if (before->left != NULL) {
288
-    before = before->left;
289
-    while (before->right != NULL) {
290
-      before = before->right;
291
-    }
292
-    before->right = to_insert;
293
-    to_insert->parent = before;
294
-  } else {
295
-    before->left = to_insert;
296
-    to_insert->parent = before;
297
-  }
298
-  to_insert->color = COLOR_RED;
299
-  repair_tree_after_insert(root_ptr, to_insert);
302
+	if (before->left != NULL) {
303
+		before = before->left;
304
+		while (before->right != NULL) {
305
+			before = before->right;
306
+		}
307
+		before->right = to_insert;
308
+		to_insert->parent = before;
309
+	} else {
310
+		before->left = to_insert;
311
+		to_insert->parent = before;
312
+	}
313
+	to_insert->color = COLOR_RED;
314
+	repair_tree_after_insert(root_ptr, to_insert);
300 315
 #ifdef DEBUG
301 316
 	printf("== POST-INSERT-FIXUP ===\n");
302 317
 	printf("===== CURRENT TREE =====\n");
@@ -319,9 +334,9 @@ void replace_node(TreeAlloc **root_ptr, TreeAlloc *node, TreeAlloc *replace) {
319 334
 
320 335
 void repair_after_remove(TreeAlloc **root_ptr, TreeAlloc *parent, TreeAlloc *node) {
321 336
 #ifdef DEBUG
322
-  printf("delete fixup at %p -> %p\n", parent, node);
337
+	printf("delete fixup at %p -> %p\n", parent, node);
323 338
 #endif
324
-  // In theory, the last two conditions should be the same ...
339
+	// In theory, the last two conditions should be the same ...
325 340
 	if (IS_RED_NODE(node) || (node != NULL && node == *root_ptr)) {
326 341
 		node->color = COLOR_BLACK;
327 342
 	} else {
@@ -332,54 +347,54 @@ void repair_after_remove(TreeAlloc **root_ptr, TreeAlloc *parent, TreeAlloc *nod
332 347
 			} else {
333 348
 				rotate_right(root_ptr, parent);
334 349
 			}
335
-      // The rotate shouldn't touch the parent relationship of `node`
350
+			// The rotate shouldn't touch the parent relationship of `node`
336 351
 			parent->parent->color = COLOR_BLACK;
337
-      parent->color = COLOR_RED;
338
-      sibling = get_sibling(parent, node);
352
+			parent->color = COLOR_RED;
353
+			sibling = get_sibling(parent, node);
339 354
 		} 
340 355
 
341 356
 		if (IS_BLACK_NODE(sibling->left) && IS_BLACK_NODE(sibling->right)) {
342
-      if (node != NULL)
343
-        node->color = COLOR_BLACK;
357
+			if (node != NULL)
358
+				node->color = COLOR_BLACK;
344 359
 			sibling->color = COLOR_RED;
345 360
 			repair_after_remove(root_ptr, parent->parent, parent);
346 361
 		} else {
347
-      if (parent->left == node && IS_BLACK_NODE(sibling->right)) {
348
-        rotate_right(root_ptr, sibling);
349
-        sibling->color = COLOR_RED;
350
-        sibling = parent->right;
351
-        sibling->color = COLOR_BLACK;
352
-      }
353
-      if (parent->right == node && IS_BLACK_NODE(sibling->left)) {
354
-        rotate_left(root_ptr, sibling);
355
-        sibling->color = COLOR_RED;
356
-        sibling = parent->left;
357
-        sibling->color = COLOR_BLACK;
358
-      }
359
-      if (parent->left == node) {
360
-        rotate_left(root_ptr, parent);
361
-      } else {
362
-        rotate_right(root_ptr, parent);
363
-      }
364
-      if (node != NULL)
365
-        node->color = COLOR_BLACK;
366
-      TreeAlloc *uncle = get_sibling(parent->parent, parent);
367
-      if (uncle != NULL)
368
-        uncle->color = COLOR_BLACK;
369
-      char swap = parent->color;
370
-      parent->color = parent->parent->color;
371
-      parent->parent->color = swap;
362
+			if (parent->left == node && IS_BLACK_NODE(sibling->right)) {
363
+				rotate_right(root_ptr, sibling);
364
+				sibling->color = COLOR_RED;
365
+				sibling = parent->right;
366
+				sibling->color = COLOR_BLACK;
367
+			}
368
+			if (parent->right == node && IS_BLACK_NODE(sibling->left)) {
369
+				rotate_left(root_ptr, sibling);
370
+				sibling->color = COLOR_RED;
371
+				sibling = parent->left;
372
+				sibling->color = COLOR_BLACK;
373
+			}
374
+			if (parent->left == node) {
375
+				rotate_left(root_ptr, parent);
376
+			} else {
377
+				rotate_right(root_ptr, parent);
378
+			}
379
+			if (node != NULL)
380
+				node->color = COLOR_BLACK;
381
+			TreeAlloc *uncle = get_sibling(parent->parent, parent);
382
+			if (uncle != NULL)
383
+				uncle->color = COLOR_BLACK;
384
+			char swap = parent->color;
385
+			parent->color = parent->parent->color;
386
+			parent->parent->color = swap;
372 387
 		}
373 388
 	}
374 389
 }
375 390
 
376 391
 void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) {
377 392
 	char do_repair = 0;
378
-  char old_color;
393
+	char old_color;
379 394
 #ifdef DEBUG
380 395
 	printf("====== PRE-REMOVE ======\n");
381 396
 	printf("======= REMOVING =======\n");
382
-	debug_print_tree(0, to_remove, 0);
397
+	debug_print_node(0, to_remove, 0);
383 398
 	printf("===== CURRENT TREE =====\n");
384 399
 	debug_print_tree(0, *root_ptr, 0);
385 400
 	printf("===== END OF TREES =====\n");
@@ -388,23 +403,23 @@ void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) {
388 403
 	TreeAlloc *parent = to_remove->parent;
389 404
 	if (!to_remove->left) {
390 405
 #ifdef DEBUG
391
-    printf("code path 1l\n");
406
+		printf("code path 1l\n");
392 407
 #endif
393 408
 		replace = to_remove->right;
394
-    parent_of_replace = to_remove->parent;
409
+		parent_of_replace = to_remove->parent;
395 410
 		do_repair = to_remove->color == COLOR_BLACK;
396 411
 		replace_node(root_ptr, to_remove, replace);
397 412
 	} else if (!to_remove->right) {
398 413
 #ifdef DEBUG
399
-    printf("code path 1r\n");
414
+		printf("code path 1r\n");
400 415
 #endif
401 416
 		replace = to_remove->left;
402
-    parent_of_replace = to_remove->parent;
417
+		parent_of_replace = to_remove->parent;
403 418
 		do_repair = to_remove->color == COLOR_BLACK;
404 419
 		replace_node(root_ptr, to_remove, replace);
405 420
 	} else {
406 421
 #ifdef DEBUG
407
-    printf("code path 2\n");
422
+		printf("code path 2\n");
408 423
 #endif
409 424
 		TreeAlloc *tmp = succ(to_remove);
410 425
 		replace = tmp->right;
@@ -413,10 +428,10 @@ void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) {
413 428
 			replace_node(root_ptr, tmp, replace);
414 429
 			tmp->right = to_remove->right;
415 430
 			to_remove->right->parent = tmp;
416
-      parent_of_replace = tmp->parent;
431
+			parent_of_replace = tmp->parent;
417 432
 		} else {
418
-      parent_of_replace = tmp;
419
-    }
433
+			parent_of_replace = tmp;
434
+		}
420 435
 		replace_node(root_ptr, to_remove, tmp);
421 436
 		tmp->color = to_remove->color;
422 437
 		tmp->left = to_remove->left;
@@ -431,7 +446,7 @@ void remove_node(TreeAlloc **root_ptr, TreeAlloc *to_remove) {
431 446
 	printf("===== CURRENT TREE =====\n");
432 447
 	debug_print_tree(0, *root_ptr, 1);
433 448
 	printf("===== END OF TREES =====\n");
434
-  printf("considering fixing up %p -> %p\n", parent_of_replace, replace);
449
+	printf("considering fixing up %p -> %p\n", parent_of_replace, replace);
435 450
 #endif
436 451
 	if (replace && parent_of_replace == NULL) {
437 452
 		replace->color = COLOR_BLACK;
@@ -583,6 +598,7 @@ void *alloc(Arena *arena, uintptr_t size, uintptr_t align) {
583 598
 #ifdef DEBUG
584 599
 		printf("start: %p, end: %p, adjusted end: %p\n", region, ((void*) region) + size, true_end);
585 600
 		printf("size: %lu -> %lu\n", size, new_size);
601
+		printf("new_free_size: %lu\n", new_free_size);
586 602
 #endif
587 603
 		if (arena->root_treealloc == NULL) {
588 604
 			insert_singleton((TreeAlloc**) &arena->root_treealloc, region);
@@ -607,7 +623,7 @@ void *alloc(Arena *arena, uintptr_t size, uintptr_t align) {
607 623
 				insert_right(&arena->root_treealloc, region, insert_point);
608 624
 			}
609 625
 		}
610
-		if (new_free_size >= sizeof(FreeSpace)) {
626
+		if (region->size >= new_size + sizeof(FreeSpace)) {
611 627
 			// If there's enough free space after the allocation, use it!
612 628
 			region->size = new_size;  // Safe because the allocated region tree is not sorted by size.
613 629
 			FreeSpace *new_free = (FreeSpace*) ((void*) region + new_size);

Loading…
Cancel
Save