diff --git a/src/gc_malloc.c b/src/gc_malloc.c index 544a98a..1f27382 100644 --- a/src/gc_malloc.c +++ b/src/gc_malloc.c @@ -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 + } +}