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); 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 * Example: User requests 1 byte
* LHS * LHS
* requested size = 0b00000001 * requested size = 0b00000001
@ -42,6 +43,26 @@ static inline uint32_t align(uint32_t size)
return 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) struct gc_chunk *find_next_chunk(struct gc_chunk *curr)
{ {
unsigned size = curr->size; unsigned size = curr->size;
@ -69,8 +90,7 @@ int get_footer(struct gc_chunk *curr)
struct gc_chunk *init_gc_chunk(void) struct gc_chunk *init_gc_chunk(void)
{ {
const size_t page_size = getpagesize(); const size_t len = getpagesize();
const size_t len = page_size * sizeof(uint64_t);
struct gc_chunk *chunk = struct gc_chunk *chunk =
(struct gc_chunk *)mmap(NULL, len, PROT_READ | PROT_WRITE, (struct gc_chunk *)mmap(NULL, len, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@ -78,7 +98,7 @@ struct gc_chunk *init_gc_chunk(void)
if (chunk == MAP_FAILED) if (chunk == MAP_FAILED)
return NULL; return NULL;
chunk->size = page_size - MAGIC - OVERHEAD; chunk->size = len - MAGIC - OVERHEAD;
chunk->merge = 0; chunk->merge = 0;
chunk->free = 1; chunk->free = 1;
chunk->next = NULL; chunk->next = NULL;
@ -92,11 +112,16 @@ struct gc_chunk *init_gc_chunk(void)
sentinel->next = NULL; sentinel->next = NULL;
sentinel->prev = chunk; sentinel->prev = chunk;
chk_freelist(); // TODO: Remove this line after debugging
return chunk; return chunk;
} }
struct gc_chunk *find_free_chunk(size_t size) 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; struct gc_chunk *found;
while (1) { while (1) {
@ -104,6 +129,7 @@ struct gc_chunk *find_free_chunk(size_t size)
while (found != NULL) { while (found != NULL) {
if (found->size >= size) { if (found->size >= size) {
// found, TODO: split when appropriate // found, TODO: split when appropriate
// remaining block needs to be at least MIN + OVERHEAD
break; break;
} }
found = found->next; found = found->next;
@ -129,7 +155,9 @@ void merge_chunk(struct gc_chunk *curr)
{ {
if (curr->merge) { if (curr->merge) {
struct gc_chunk *prev = find_prev_chunk(curr); struct gc_chunk *prev = find_prev_chunk(curr);
chk_freelist(); // TODO: Remove this line after debugging
struct gc_chunk *next = find_next_chunk(curr); struct gc_chunk *next = find_next_chunk(curr);
chk_freelist(); // TODO: Remove this line after debugging
if (next->free) { if (next->free) {
// TODO Case 1: merge prev and next // TODO Case 1: merge prev and next
@ -139,6 +167,7 @@ void merge_chunk(struct gc_chunk *curr)
set_footer(prev); set_footer(prev);
} else { } else {
struct gc_chunk *next = find_next_chunk(curr); struct gc_chunk *next = find_next_chunk(curr);
chk_freelist(); // TODO: Remove this line after debugging
if (next->free) { if (next->free) {
// TODO Case 3: merge with after // TODO Case 3: merge with after
} else { } else {
@ -148,3 +177,27 @@ void merge_chunk(struct gc_chunk *curr)
set_footer(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
}
}