Browse Source

Tied tree allocator into waterfall allocator

watermark_alloc
Cameron Weinfurt 2 years ago
parent
commit
ba4a82fbf2
  1. 2
      Makefile
  2. 3
      alloc_api.h
  3. 17
      allocator_internal.h
  4. 1
      main.c
  5. 23
      tree_alloc.c
  6. 2
      util.c
  7. 70
      watermark_alloc.c

2
Makefile

@ -21,7 +21,7 @@ clean:
main.o: main.c alloc_api.h
$(CC) $(CFLAGS) -c main.c -o main.o
watermark_alloc.o: watermark_alloc.c allocator_interal.h
watermark_alloc.o: watermark_alloc.c allocator_internal.h
$(CC) $(CFLAGS) -c watermark_alloc.c -o watermark_alloc.o
tree_alloc.o: tree_alloc.c allocator_internal.h

3
alloc_api.h

@ -4,10 +4,11 @@
struct Arena {
void *root_freespace;
void *root_treealloc;
void *head_watermark;
void *(*get_new_region)(uintptr_t);
void (*error)(char*);
};
void unalloc(struct Arena *arena, void *addr);
void *alloc(struct Arena *arena, uintptr_t size, uintptr_t align);
void *alloc_fixed(struct Arena *arena, uintptr_t size, uintptr_t align);

17
allocator_internal.h

@ -4,18 +4,19 @@
#include <stdint.h>
// No enum because these need to be 1 byte
const char RT_FREESPACE = 0;
const char RT_TREE_NODE = 1;
const char RT_WATERMARK = 2;
#define RT_FREESPACE 0
#define RT_TREE_NODE 1
#define RT_WATERMARK 2
const char COLOR_RED = 0;
const char COLOR_BLACK = 1;
#define COLOR_RED 0
#define COLOR_BLACK 1
const uintptr_t MIN_NEW_MEM_SIZE = 4096;
#define MIN_NEW_MEM_SIZE 4096
typedef struct Arena {
struct FreeSpace *root_freespace;
struct TreeAlloc *root_treealloc;
struct WatermarkAlloc *head_watermark;
void *(*get_new_region)(uintptr_t);
void (*error)(char*);
} Arena;
@ -57,7 +58,7 @@ typedef struct WatermarkAlloc {
uintptr_t size;
struct TreeAlloc *before;
struct TreeAlloc *after;
int num_allocs;
unsigned int num_allocs;
void *next_alloc;
} WatermarkAlloc;
@ -76,5 +77,7 @@ 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);
void *alloc_fixed(struct Arena *arena, uintptr_t size, uintptr_t align);
#endif

1
main.c

@ -21,6 +21,7 @@ void error(char *msg) {
int main() {
printf("Hello, World!\n");
struct Arena arena = {
NULL,
NULL,
NULL,
get_new_region,

23
tree_alloc.c

@ -339,10 +339,19 @@ void unalloc(Arena *arena, void *addr) {
arena->error("attempt to free memory outside any allocations!");
return;
}
// Handle the watermark allocator in this region
// Handle the watermark allocator in this region. If there are no more
// allocations stored inside of it, then the node can be freed by
// continuing into the code below after the watermark list has been
// cleaned up. Otherwise, the deallocation is already done.
if (node->type == RT_WATERMARK) {
// TODO: handle watermark deallocation
return;
WatermarkAlloc *wma = (WatermarkAlloc *) node;
wma->num_allocs -= 1;
if (wma->num_allocs > 0)
return;
if (wma->before)
wma->before->after = wma->after;
if (wma->after)
wma->after->before = wma->before;
}
// Get rid of it
remove_node(&arena->root_treealloc, node);
@ -395,16 +404,16 @@ void *alloc(Arena *arena, uintptr_t size, uintptr_t align) {
}
return alloc(arena, size, align);
} else {
TreeAlloc *region = search_by_size((TreeAlloc*) arena->root_freespace, sizeof(TreeAlloc), actual_align, size);
TreeAlloc *region = search_by_size((TreeAlloc*) arena->root_freespace, sizeof(WatermarkAlloc), actual_align, size);
if (region == NULL) {
// Handle insufficient freespace or fragmentation.
if (!add_new_region(arena, size, sizeof(TreeAlloc), actual_align)) {
if (!add_new_region(arena, size, sizeof(WatermarkAlloc), actual_align)) {
return NULL;
}
return alloc(arena, size, align);
}
remove_node((TreeAlloc**) &arena->root_freespace, region);
void *true_end = align_after(align_after(((void*) region) + sizeof(TreeAlloc), actual_align) + size, alignof(WatermarkAlloc));
void *true_end = align_after(align_after(((void*) region) + sizeof(WatermarkAlloc), 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
@ -413,7 +422,7 @@ void *alloc(Arena *arena, uintptr_t size, uintptr_t align) {
region->left = NULL;
region->type = RT_TREE_NODE;
#ifdef DEBUG
printf("sizeof(TreeAlloc): %lu\n", (uintptr_t) sizeof(TreeAlloc));
printf("sizeof(TreeAlloc): %lu\n", (uintptr_t) sizeof(WatermarkAlloc));
printf("start: %p, end: %p, adjusted end: %p\n", region, ((void*) region) + size, true_end);
printf("size: %lu -> %lu\n", size, new_size);
#endif

2
util.c

@ -15,7 +15,7 @@ void* align_after(void* address, int align) {
rv = (void*) (addr + align - align % offset);
}
#ifdef DEBUG
printf("aligning %p at alignment %lx to %p\n", address, align, rv);
printf("aligning %p at alignment %x to %p\n", address, align, rv);
#endif
return rv;
}

70
watermark_alloc.c

@ -1,28 +1,42 @@
/*
* Allocates space within a tree allocator for performing
* watermark allocations.
*/
WatermarkAlloc *new_watermark_allocator(TreeAlloc *ta, int size) {
// TODO: Allocate space correctly when that is ironed out.
// This will just SIGSEGV 100% of the time for now.
WatermarkAlloc *wma = NULL;
wma->type = RT_WATERMARK;
wma->parent = ta;
wma->left = wma->right = NULL; // TODO: How should these be set?
wma->size = size;
wma->num_allocs = 0;
wma->next_alloc = wma + sizeof(wma);
return wma;
}
#include <stddef.h>
#include "allocator_internal.h"
/*
* Attempt to allocate space within a watermark region.
* Returns the null pointer if the allocation cannot fit.
* Attempt to allocate space within a watermark region. It will try to
* allocate more space if
*/
void *watermark_allocate(WatermarkAlloc *wma, int size) {
int space_left = wma + wma->size - wma->next_alloc;
if (space_left < size)
return NULL;
void *alloc_fixed(struct Arena *arena, uintptr_t size, uintptr_t align)
{
// Large allocations will never fit inside this allocator.
if (size > MIN_NEW_MEM_SIZE) return NULL;
WatermarkAlloc *wma = arena->head_watermark;
int space_left;
if (!wma) {
// No watermark allocators are currently active, so a new one
// needs to be created to act as the head.
wma = alloc(arena, MIN_NEW_MEM_SIZE + sizeof(WatermarkAlloc), align);
arena->head_watermark = wma;
wma->before = wma->after = NULL;
} else {
// Scan through the current allocators until one with enough space is
// found or the end of the list is reached. In the latter case, alloc
// a new allocator.
while(wma) {
if(wma->size <= size) {
// There is enough room for the allocation in this allocator,
// so use it.
break;
} else if (!wma->after) {
wma->after = alloc(arena, MIN_NEW_MEM_SIZE + sizeof(WatermarkAlloc), align);
wma->after->before = (TreeAlloc *) wma;
wma = (WatermarkAlloc *) wma->after;
break;
}
wma = (WatermarkAlloc *) wma->after;
}
}
void *allocation = wma->next_alloc;
wma->next_alloc += size;
@ -30,15 +44,3 @@ void *watermark_allocate(WatermarkAlloc *wma, int size) {
return allocation;
}
/*
* "Frees" space inside the watermark region. Since this
* is watermark, however, this doesn't actually do anything
* besides decrement the ref-count. It returns the new
* ref-count so that the parent allocator can clean up the
* space properly.
*/
bool watermark_free(WatermarkAlloc *wma) {
wma->num_allocs -= 1;
return wma->num_allocs;
}
Loading…
Cancel
Save