malloc: defined gc_malloc, gc_free, and debug func chk_freelist

This commit is contained in:
Andrew Scott 2024-09-18 14:41:30 -04:00
parent 5749c68035
commit 3ecb5d560f
Signed by: a
GPG key ID: 7CD5A5977E4931C1

View file

@ -19,8 +19,9 @@ static inline struct gc_chunk *magic(void *mem)
return (struct gc_chunk *)((uint64_t *)mem - MAGIC);
}
// Aligns the amount of memory requested by the user with chunk size
/*
* Aligns the amount of memory requested by the user with chunk size
*
* Example: User requests 1 byte
* LHS
* requested size = 0b00000001
@ -42,6 +43,26 @@ static inline uint32_t align(uint32_t size)
return size;
}
// Useful for debugging after find or merge are called
static void chk_freelist(void)
{
struct gc_chunk *next = freelist;
struct gc_chunk *prev = NULL;
while (next != NULL) {
assert(next->free);
assert(next->merge == 0);
assert(next->size >= MIN);
assert(get_footer(next) == next->size);
assert(next->prev == prev);
struct gc_chunk *after = find_next_chunk(next);
assert(after->merge == 1);
assert(after->free == 0);
prev = next;
next = next->next;
}
}
struct gc_chunk *find_next_chunk(struct gc_chunk *curr)
{
unsigned size = curr->size;
@ -69,8 +90,7 @@ int get_footer(struct gc_chunk *curr)
struct gc_chunk *init_gc_chunk(void)
{
const size_t page_size = getpagesize();
const size_t len = page_size * sizeof(uint64_t);
const size_t len = getpagesize();
struct gc_chunk *chunk =
(struct gc_chunk *)mmap(NULL, len, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@ -78,7 +98,7 @@ struct gc_chunk *init_gc_chunk(void)
if (chunk == MAP_FAILED)
return NULL;
chunk->size = page_size - MAGIC - OVERHEAD;
chunk->size = len - MAGIC - OVERHEAD;
chunk->merge = 0;
chunk->free = 1;
chunk->next = NULL;
@ -87,16 +107,21 @@ struct gc_chunk *init_gc_chunk(void)
struct gc_chunk *sentinel = find_next_chunk(chunk);
sentinel->footer = chunk->size;
sentinel->size = 0;
sentinel-> merge = 1;
sentinel->merge = 1;
sentinel->free = 1;
sentinel->next = NULL;
sentinel->prev = chunk;
chk_freelist(); // TODO: Remove this line after debugging
return chunk;
}
struct gc_chunk *find_free_chunk(size_t size)
{
// HACK: The first loop will run forever if we can never get a big enough chunk
if (size > getpagesize())
return NULL;
struct gc_chunk *found;
while (1) {
@ -104,6 +129,7 @@ struct gc_chunk *find_free_chunk(size_t size)
while (found != NULL) {
if (found->size >= size) {
// found, TODO: split when appropriate
// remaining block needs to be at least MIN + OVERHEAD
break;
}
found = found->next;
@ -129,7 +155,9 @@ void merge_chunk(struct gc_chunk *curr)
{
if (curr->merge) {
struct gc_chunk *prev = find_prev_chunk(curr);
chk_freelist(); // TODO: Remove this line after debugging
struct gc_chunk *next = find_next_chunk(curr);
chk_freelist(); // TODO: Remove this line after debugging
if (next->free) {
// TODO Case 1: merge prev and next
@ -139,6 +167,7 @@ void merge_chunk(struct gc_chunk *curr)
set_footer(prev);
} else {
struct gc_chunk *next = find_next_chunk(curr);
chk_freelist(); // TODO: Remove this line after debugging
if (next->free) {
// TODO Case 3: merge with after
} else {
@ -148,3 +177,27 @@ void merge_chunk(struct gc_chunk *curr)
set_footer(curr);
}
}
void *gc_malloc(size_t size)
{
if (size == 0)
return NULL;
uint32_t bytes = align(size);
struct gc_chunk *curr = find_free_chunk(bytes);
chk_freelist(); // TODO: Remove this line after debugging
if (curr == NULL)
return curr;
return hide(curr);
}
void gc_free(void *ptr)
{
if (ptr != NULL) {
struct gc_chunk *curr = magic(ptr);
merge_chunk(curr);
chk_freelist(); // TODO: Remove this line after debugging
}
}