Browse Source

Added one of the allocation functions

tree_alloc
Thomas Johnson 1 year ago
parent
commit
e2b074bd64
  1. 1
      .gitignore
  2. 13
      allocator_internal.h
  3. 57
      tree_alloc.c

1
.gitignore

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

13
allocator_internal.h

@ -3,6 +3,8 @@
#include <stdint.h>
#define alignof(x) offsetof(struct { char pad; x member; }, member)
// No enum because these need to be 1 byte
const char RT_FREESPACE = 0;
const char RT_TREE_NODE = 1;
@ -62,8 +64,17 @@ typedef struct WatermarkAlloc {
void* align_after(void* address, uintptr_t align);
uintptr_t lcm(uintptr_t a, uintptr_t b);
uintptr_t gcd(uintptr_t a, uintptr_t b);
TreeAlloc *insert_node_at(void *address, uintptr_t padding, uintptr_t align, uintptr_t size);
TreeAlloc *search_by_address(TreeAlloc *root, void *address);
TreeAlloc *search_by_size(TreeAlloc *root, uintptr_t padding, uintptr_t align, uintptr_t size);
TreeAlloc *get_sibling(TreeAlloc *ta);
void rotate_left(TreeAlloc *ta);
void rotate_right(TreeAlloc *ta);
void repair_tree_after_insert(TreeAlloc *ta);
void remove_node(TreeAlloc** root_ptr, TreeAlloc* node);
void insert_singleton(TreeAlloc **root_ptr, TreeAlloc *to_insert);
void insert_right(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* after);
void insert_left(TreeAlloc** root_ptr, TreeAlloc* to_insert, TreeAlloc* before);
void unalloc(Arena *arena, void *addr);
void *alloc(Arena *arena, uintptr_t size, uintptr_t align);
#endif

57
tree_alloc.c

@ -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;
}
Loading…
Cancel
Save