Browse Source

Added one of the allocation functions

Thomas Johnson 6 months ago
parent
commit
e2b074bd64
3 changed files with 55 additions and 16 deletions
  1. 1
    0
      .gitignore
  2. 12
    1
      allocator_internal.h
  3. 42
    15
      tree_alloc.c

+ 1
- 0
.gitignore View File

@@ -1 +1,2 @@
1 1
 *.o
2
+the_alloc

+ 12
- 1
allocator_internal.h View File

@@ -3,6 +3,8 @@
3 3
 
4 4
 #include <stdint.h>
5 5
 
6
+#define alignof(x) offsetof(struct { char pad; x member; }, member)
7
+
6 8
 // No enum because these need to be 1 byte
7 9
 const char RT_FREESPACE = 0;
8 10
 const char RT_TREE_NODE = 1;
@@ -62,8 +64,17 @@ typedef struct WatermarkAlloc {
62 64
 void* align_after(void* address, uintptr_t align);
63 65
 uintptr_t lcm(uintptr_t a, uintptr_t b);
64 66
 uintptr_t gcd(uintptr_t a, uintptr_t b);
65
-TreeAlloc *insert_node_at(void *address, uintptr_t padding, uintptr_t align, uintptr_t size);
66 67
 TreeAlloc *search_by_address(TreeAlloc *root, void *address);
67 68
 TreeAlloc *search_by_size(TreeAlloc *root, uintptr_t padding, uintptr_t align, uintptr_t size);
69
+TreeAlloc *get_sibling(TreeAlloc *ta);
70
+void rotate_left(TreeAlloc *ta);
71
+void rotate_right(TreeAlloc *ta);
72
+void repair_tree_after_insert(TreeAlloc *ta);
73
+void remove_node(TreeAlloc** root_ptr, TreeAlloc* node);
74
+void insert_singleton(TreeAlloc **root_ptr, TreeAlloc *to_insert);
75
+void insert_right(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* after);
76
+void insert_left(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* before);
77
+void unalloc(Arena *arena, void *addr);
78
+void *alloc(Arena *arena, uintptr_t size, uintptr_t align);
68 79
 
69 80
 #endif

+ 42
- 15
tree_alloc.c View File

@@ -259,31 +259,58 @@ void unalloc(Arena *arena, void *addr) {
259 259
   }
260 260
 }
261 261
 
262
-void *alloc(Arena arena, uintptr_t size, uintptr_t align) {
262
+void *alloc(Arena *arena, uintptr_t size, uintptr_t align) {
263 263
   if (arena->root_freespace == NULL) {
264 264
     // TODO: handle out-of-memory
265 265
   } else {
266
-    uintptr_t actual_align = lcm(alignof(WatermarkAlloc), align);
267
-    TreeAlloc *insert_point = search_by_size(arena->root_freespace, sizeof(TreeAlloc), actual_align, size);
268
-    if (insert_point == NULL) {
266
+    uintptr_t actual_align = lcm(alignof(struct WatermarkAlloc), align);
267
+    TreeAlloc *region = search_by_size((TreeAlloc*) arena->root_freespace, sizeof(TreeAlloc), actual_align, size);
268
+    if (region == NULL) {
269 269
       // TODO: handle memory fragmentation (or OOM)
270 270
     }
271
-    remove_node(&arena->root_freespace, insert_point);
272
-    true_end = align_after(align_after(insert_point + sizeof(TreeAlloc), actual_align) + size, alignof(WatermarkAlloc));
273
-    // The size of the 
274
-    uintptr_t new_size = true_end - insert_point;
275
-    uintptr_t new_free_size = insert_point.size - new_size;
276
-    if (new_free_size < sizeof(FreeSpace)) {
277
-      // TODO: Handle insufficient size for the new free region (by not having one)
271
+    remove_node((TreeAlloc**) &arena->root_freespace, region);
272
+    void *true_end = align_after(align_after(region + sizeof(TreeAlloc), actual_align) + size, alignof(WatermarkAlloc));
273
+    // The size of the new allocation (adjusted for region header and alignment
274
+    uintptr_t new_size = true_end - (void*) region;
275
+    // The size of the free space region following the new allocation
276
+    uintptr_t new_free_size = region->size - new_size;
277
+    region->right = NULL;
278
+    region->left = NULL;
279
+    region->type = RT_TREE_NODE;
280
+    if (arena->root_treealloc == NULL) {
281
+      insert_singleton((TreeAlloc**) &arena->root_treealloc, region);
282
+    } else {
283
+      TreeAlloc *insert_point = search_by_address((TreeAlloc*) arena->root_treealloc, region);
284
+      insert_right(&arena->root_treealloc, region, insert_point);
285
+    }
286
+    if (arena->root_treealloc == NULL) {
287
+      insert_singleton(&arena->root_treealloc, region);
278 288
     } else {
279
-      // TODO: Add free region and allocation record
289
+      TreeAlloc *insert_point = search_by_address((TreeAlloc*) arena->root_treealloc, region);
290
+      insert_right(&arena->root_treealloc, region, insert_point);
280 291
     }
292
+    if (new_free_size >= sizeof(FreeSpace)) {
293
+      // If there's enough free space after the allocation, use it!
294
+      region->size = new_size;  // Safe because the allocated region tree is not sorted by size.
295
+      FreeSpace *new_free = (FreeSpace*) ((void*) region + new_size);
296
+      new_free->left = NULL;
297
+      new_free->right = NULL;
298
+      new_free->type = RT_FREESPACE;
299
+      new_free->size = new_free_size;
300
+      if (arena->root_freespace == NULL) {
301
+        insert_singleton((TreeAlloc**) &arena->root_freespace, (TreeAlloc*) new_free);
302
+      } else {
303
+        FreeSpace *insert_point = (FreeSpace*) search_by_size((TreeAlloc*) arena->root_freespace, 0, 1, new_free_size);
304
+        insert_left((TreeAlloc**) &arena->root_freespace, (TreeAlloc*) new_free, (TreeAlloc*) insert_point);
305
+      }
306
+    }
307
+    return align_after(region + sizeof(TreeAlloc), actual_align);
281 308
   }
282
-  return NULL;
283 309
 }
284 310
 
285
-void *alloc_growable(Arena arena, uintptr_t size, uintptr_t align) {
286
-  // TODO
311
+void *alloc_growable(Arena *arena, uintptr_t size, uintptr_t align) {
312
+  // TODO: Basically the same as above, but put the allocated region in the center of the largest free
313
+  // space. Due to alignment and whatnot, the code will be gory.
287 314
   return NULL;
288 315
 }
289 316
 

Loading…
Cancel
Save