diff --git a/ya_freelist.c b/ya_freelist.c index eac9e63..8b7d519 100644 --- a/ya_freelist.c +++ b/ya_freelist.c @@ -92,13 +92,20 @@ intptr_t *fl_find(intptr_t min_size) { return NULL; } -/* Force split of free block [block_size] into [size, block_size - size]. */ -void fl_split(intptr_t *block, intptr_t size) { - fl_set_next(block, block+size); - if (block == fl_end) { - fl_end = block+size; +/* Mends the free list after a free block has just been split into two blocks, + * block and new_next. */ +void fl_mend_split(intptr_t *block, intptr_t *new_next) { + if (!new_next) { + return; // block was not split + } + intptr_t *old_next = fl_next(new_next); + fl_set_next(block, new_next); + fl_set_prev(new_next, block); + if (old_next) { + fl_set_prev(old_next, new_next); + } else { + fl_end = new_next; } - fl_set_prev(block+size, block); } void fl_join_next(intptr_t *block) { diff --git a/ya_freelist.h b/ya_freelist.h index ee94f3c..70698b4 100644 --- a/ya_freelist.h +++ b/ya_freelist.h @@ -69,8 +69,9 @@ void fl_free(intptr_t *block); * Returns NULL if no adequate block is found. Does not grow the heap. */ intptr_t *fl_find(intptr_t min_size); -/* Force split of block [block_size] into [size, block_size - size]. */ -void fl_split(intptr_t *block, intptr_t size); +/* Mends the free list after a free block has just been split into two blocks, + * block and new_next. */ +void fl_mend_split(intptr_t *block, intptr_t *new_next); void fl_join_prev(intptr_t *block); diff --git a/yamalloc.c b/yamalloc.c index 92f7643..06f0aed 100644 --- a/yamalloc.c +++ b/yamalloc.c @@ -16,6 +16,18 @@ /* Function definitions */ /*----------------------*/ +/* Splits block both at the block level and in the free list. */ +void split(intptr_t *block, intptr_t size) { + fl_mend_split(block, block_split(block, size)); +} + +/* Coalesces block with neighbors if possible, both at the block level and in + * the free list. */ +void join(intptr_t *block) { + fl_join(block); + block_join(block); +} + /* Allocates enough memory to store at least size bytes. * Returns a dword-aligned pointer to the memory or NULL in case of failure. */ void *malloc(size_t n_bytes) { @@ -32,10 +44,7 @@ void *malloc(size_t n_bytes) { if (!block) { block = heap_extend(n_bytes); } - if (block_split(block, size)) { - // block was indeed split, so splt it in the free list as well - fl_split(block, size); - } + split(block, size); block_alloc(block); fl_alloc(block); return block; @@ -51,8 +60,7 @@ void free(void *ptr) { } block_free(block); fl_free(block); - fl_join(block); - block_join(block); + join(block); } /* Allocates enough memory to store an array of nmemb elements, @@ -100,31 +108,19 @@ void *realloc(void *ptr, size_t n_bytes) { return block; } intptr_t *next = block + size; - if (next == heap_end || - (!block_is_alloc(next) && next + block_size(next) == heap_end)) { + if (next == heap_end || next == fl_get_end()) { // grow the heap and extend block next = heap_extend(n_bytes); - fl_free(block); - fl_join_next(block); - block_join_next(block); - if (block_split(block, new_size)) { - fl_split(block, new_size); - } - block_alloc(block); - fl_alloc(block); - return block; + // then fall into next if clause which will use the newly extended + // heap to extend the block without moving it } // try to use next free block if (next < heap_end) { intptr_t next_size = block_size(next); if (!block_is_alloc(next) && new_size <= size + next_size) { // try to split the next block at the right size - if (block_split(next, new_size - size)) { - // split successful, must split in the free list too - fl_split(block, new_size); - } + split(next, new_size - size); fl_alloc(next); // remove the next block from the free list - fl_join_next(block); block_join_next(block); // coalesce block_alloc(block); // mark block as allocated return block;