|
|
@ -259,31 +259,58 @@ void unalloc(Arena *arena, void *addr) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void *alloc(Arena arena, uintptr_t size, uintptr_t align) { |
|
|
|
void *alloc(Arena *arena, uintptr_t size, uintptr_t align) { |
|
|
|
if (arena->root_freespace == NULL) { |
|
|
|
// TODO: handle out-of-memory |
|
|
|
} else { |
|
|
|
uintptr_t actual_align = lcm(alignof(WatermarkAlloc), align); |
|
|
|
TreeAlloc *insert_point = search_by_size(arena->root_freespace, sizeof(TreeAlloc), actual_align, size); |
|
|
|
if (insert_point == NULL) { |
|
|
|
uintptr_t actual_align = lcm(alignof(struct WatermarkAlloc), align); |
|
|
|
TreeAlloc *region = search_by_size((TreeAlloc*) arena->root_freespace, sizeof(TreeAlloc), actual_align, size); |
|
|
|
if (region == NULL) { |
|
|
|
// TODO: handle memory fragmentation (or OOM) |
|
|
|
} |
|
|
|
remove_node(&arena->root_freespace, insert_point); |
|
|
|
true_end = align_after(align_after(insert_point + sizeof(TreeAlloc), actual_align) + size, alignof(WatermarkAlloc)); |
|
|
|
// The size of the |
|
|
|
uintptr_t new_size = true_end - insert_point; |
|
|
|
uintptr_t new_free_size = insert_point.size - new_size; |
|
|
|
if (new_free_size < sizeof(FreeSpace)) { |
|
|
|
// TODO: Handle insufficient size for the new free region (by not having one) |
|
|
|
remove_node((TreeAlloc**) &arena->root_freespace, region); |
|
|
|
void *true_end = align_after(align_after(region + sizeof(TreeAlloc), actual_align) + size, alignof(WatermarkAlloc)); |
|
|
|
// The size of the new allocation (adjusted for region header and alignment |
|
|
|
uintptr_t new_size = true_end - (void*) region; |
|
|
|
// The size of the free space region following the new allocation |
|
|
|
uintptr_t new_free_size = region->size - new_size; |
|
|
|
region->right = NULL; |
|
|
|
region->left = NULL; |
|
|
|
region->type = RT_TREE_NODE; |
|
|
|
if (arena->root_treealloc == NULL) { |
|
|
|
insert_singleton((TreeAlloc**) &arena->root_treealloc, region); |
|
|
|
} else { |
|
|
|
TreeAlloc *insert_point = search_by_address((TreeAlloc*) arena->root_treealloc, region); |
|
|
|
insert_right(&arena->root_treealloc, region, insert_point); |
|
|
|
} |
|
|
|
if (arena->root_treealloc == NULL) { |
|
|
|
insert_singleton(&arena->root_treealloc, region); |
|
|
|
} else { |
|
|
|
// TODO: Add free region and allocation record |
|
|
|
TreeAlloc *insert_point = search_by_address((TreeAlloc*) arena->root_treealloc, region); |
|
|
|
insert_right(&arena->root_treealloc, region, insert_point); |
|
|
|
} |
|
|
|
if (new_free_size >= sizeof(FreeSpace)) { |
|
|
|
// If there's enough free space after the allocation, use it! |
|
|
|
region->size = new_size; // Safe because the allocated region tree is not sorted by size. |
|
|
|
FreeSpace *new_free = (FreeSpace*) ((void*) region + new_size); |
|
|
|
new_free->left = NULL; |
|
|
|
new_free->right = NULL; |
|
|
|
new_free->type = RT_FREESPACE; |
|
|
|
new_free->size = new_free_size; |
|
|
|
if (arena->root_freespace == NULL) { |
|
|
|
insert_singleton((TreeAlloc**) &arena->root_freespace, (TreeAlloc*) new_free); |
|
|
|
} else { |
|
|
|
FreeSpace *insert_point = (FreeSpace*) search_by_size((TreeAlloc*) arena->root_freespace, 0, 1, new_free_size); |
|
|
|
insert_left((TreeAlloc**) &arena->root_freespace, (TreeAlloc*) new_free, (TreeAlloc*) insert_point); |
|
|
|
} |
|
|
|
} |
|
|
|
return align_after(region + sizeof(TreeAlloc), actual_align); |
|
|
|
} |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
void *alloc_growable(Arena arena, uintptr_t size, uintptr_t align) { |
|
|
|
// TODO |
|
|
|
void *alloc_growable(Arena *arena, uintptr_t size, uintptr_t align) { |
|
|
|
// TODO: Basically the same as above, but put the allocated region in the center of the largest free |
|
|
|
// space. Due to alignment and whatnot, the code will be gory. |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|