malloc: fix my shit code so it's less shitty
The allocator works now. At least when i compile it for amd64. I haven't actually flashed it yet tho lmao.
This commit is contained in:
parent
83ee9603e7
commit
8e9678577e
1 changed files with 62 additions and 63 deletions
125
lib/malloc.c
125
lib/malloc.c
|
@ -227,7 +227,6 @@ void *malloc(size_t size)
|
||||||
|
|
||||||
if (blk_get_size(cursor) >= size) {
|
if (blk_get_size(cursor) >= size) {
|
||||||
cursor = blk_slice(&generic_heap, cursor, size);
|
cursor = blk_slice(&generic_heap, cursor, size);
|
||||||
blk_set_alloc(cursor);
|
|
||||||
ptr = cursor->data;
|
ptr = cursor->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +254,6 @@ void *atomic_malloc(size_t size)
|
||||||
|
|
||||||
if (blk_get_size(cursor) >= size) {
|
if (blk_get_size(cursor) >= size) {
|
||||||
cursor = blk_slice(&atomic_heap, cursor, size);
|
cursor = blk_slice(&atomic_heap, cursor, size);
|
||||||
blk_set_alloc(cursor);
|
|
||||||
ptr = cursor->data;
|
ptr = cursor->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,34 +280,30 @@ void *calloc(size_t nmemb, size_t size)
|
||||||
|
|
||||||
void free(void *ptr)
|
void free(void *ptr)
|
||||||
{
|
{
|
||||||
struct memblk *blk = ptr - offsetof(struct memblk, data);
|
|
||||||
struct list_head *heap;
|
|
||||||
|
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
return; /* as per POSIX.1-2008 */
|
return; /* as per POSIX.1-2008 */
|
||||||
|
|
||||||
|
struct memblk *blk = ptr - offsetof(struct memblk, data);
|
||||||
|
|
||||||
if (ptr >= generic_heap_start && ptr <= generic_heap_end) {
|
if (ptr >= generic_heap_start && ptr <= generic_heap_end) {
|
||||||
heap = &generic_heap;
|
if (!blk_is_alloc(blk))
|
||||||
|
__breakpoint;
|
||||||
|
|
||||||
mutex_lock(&generic_heap_lock);
|
mutex_lock(&generic_heap_lock);
|
||||||
|
blk_clear_alloc(blk);
|
||||||
|
blk_try_merge(&generic_heap, blk);
|
||||||
|
mutex_unlock(&generic_heap_lock);
|
||||||
} else if (ptr >= atomic_heap_start && ptr <= atomic_heap_end) {
|
} else if (ptr >= atomic_heap_start && ptr <= atomic_heap_end) {
|
||||||
heap = &atomic_heap;
|
if (!blk_is_alloc(blk))
|
||||||
|
__breakpoint;
|
||||||
|
|
||||||
atomic_enter();
|
atomic_enter();
|
||||||
|
blk_clear_alloc(blk);
|
||||||
|
blk_try_merge(&atomic_heap, blk);
|
||||||
|
atomic_leave();
|
||||||
} else {
|
} else {
|
||||||
__breakpoint;
|
__breakpoint;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!blk_is_alloc(blk)) {
|
|
||||||
__breakpoint; /* probably double free */
|
|
||||||
}
|
|
||||||
|
|
||||||
blk_clear_alloc(blk);
|
|
||||||
blk_try_merge(heap, blk);
|
|
||||||
|
|
||||||
if (heap == &generic_heap)
|
|
||||||
mutex_unlock(&generic_heap_lock);
|
|
||||||
else
|
|
||||||
atomic_leave();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
|
@ -326,13 +320,24 @@ void free(void *ptr)
|
||||||
|
|
||||||
static inline struct memblk *blk_try_merge(struct list_head *heap, struct memblk *blk)
|
static inline struct memblk *blk_try_merge(struct list_head *heap, struct memblk *blk)
|
||||||
{
|
{
|
||||||
struct memblk *neigh = blk_prev(blk);
|
struct memblk *neighbor = blk_prev(blk);
|
||||||
if (neigh != NULL)
|
if (neighbor != NULL && !blk_is_alloc(neighbor)) {
|
||||||
blk = blk_merge(heap, neigh, blk);
|
list_delete(&neighbor->list);
|
||||||
|
blk = blk_merge(heap, neighbor, blk);
|
||||||
|
}
|
||||||
|
|
||||||
neigh = blk_next(blk);
|
neighbor = blk_next(blk);
|
||||||
if (neigh != NULL)
|
if (neighbor != NULL && !blk_is_alloc(neighbor)) {
|
||||||
blk = blk_merge(heap, blk, neigh);
|
list_delete(&neighbor->list);
|
||||||
|
blk = blk_merge(heap, blk, neighbor);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct memblk *cursor;
|
||||||
|
list_for_each_entry(heap, cursor, list) {
|
||||||
|
if (blk_get_size(cursor) >= blk_get_size(blk))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
list_insert_before(&cursor->list, &blk->list);
|
||||||
|
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
|
@ -343,68 +348,62 @@ static inline struct memblk *blk_merge(struct list_head *heap,
|
||||||
{
|
{
|
||||||
size_t bottom_size = blk_get_size(bottom);
|
size_t bottom_size = blk_get_size(bottom);
|
||||||
size_t top_size = blk_get_size(top);
|
size_t top_size = blk_get_size(top);
|
||||||
size_t total_size = bottom_size + top_size;
|
size_t total_size = bottom_size + top_size + OVERHEAD;
|
||||||
|
|
||||||
list_delete(&top->list);
|
|
||||||
list_delete(&bottom->list);
|
|
||||||
blk_set_size(bottom, total_size);
|
blk_set_size(bottom, total_size);
|
||||||
|
|
||||||
struct memblk *cursor;
|
|
||||||
list_for_each_entry(heap, cursor, list) {
|
|
||||||
if (blk_get_size(cursor) <= bottom->size)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
list_insert_before(&cursor->list, &bottom->list);
|
|
||||||
|
|
||||||
return bottom;
|
return bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct memblk *blk_slice(struct list_head *heap,
|
static struct memblk *blk_slice(struct list_head *heap, struct memblk *blk, size_t slice_size)
|
||||||
struct memblk *bottom,
|
|
||||||
size_t bottom_size)
|
|
||||||
{
|
{
|
||||||
list_delete(&bottom->list);
|
list_delete(&blk->list);
|
||||||
|
|
||||||
size_t top_size = blk_get_size(bottom) - bottom_size - OVERHEAD;
|
assert((slice_size & SIZE_MSK) == slice_size);
|
||||||
if (top_size < MIN_SIZE)
|
assert(slice_size > 0);
|
||||||
return bottom; /* hand out the entire block */
|
|
||||||
|
|
||||||
size_t bottom_words = bottom_size / sizeof(bottom->size);
|
size_t rest_size = blk_get_size(blk) - slice_size - OVERHEAD;
|
||||||
struct memblk *top = (void *)&bottom->endsz[bottom_words + 1];
|
if (rest_size < MIN_SIZE) {
|
||||||
blk_set_size(top, top_size);
|
blk_set_alloc(blk);
|
||||||
blk_clear_alloc(top);
|
return blk; /* hand out the entire block */
|
||||||
blk_clear_border_start(top);
|
}
|
||||||
|
|
||||||
blk_set_size(bottom, bottom_size);
|
size_t slice_words = slice_size / sizeof(blk->size);
|
||||||
blk_clear_border_end(bottom);
|
struct memblk *rest = (void *)&blk->endsz[slice_words + 1];
|
||||||
|
blk_set_size(rest, rest_size);
|
||||||
|
blk_clear_alloc(rest);
|
||||||
|
blk_clear_border_start(rest);
|
||||||
|
|
||||||
|
blk_set_size(blk, slice_size);
|
||||||
|
blk_set_alloc(blk);
|
||||||
|
blk_clear_border_end(blk);
|
||||||
|
|
||||||
struct memblk *cursor;
|
struct memblk *cursor;
|
||||||
list_for_each_entry(heap, cursor, list) {
|
list_for_each_entry(heap, cursor, list) {
|
||||||
if (blk_get_size(cursor) <= top_size)
|
if (blk_get_size(cursor) <= rest_size)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
list_insert_before(&cursor->list, &top->list);
|
list_insert_before(&cursor->list, &rest->list);
|
||||||
|
|
||||||
return bottom;
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t blk_get_size(struct memblk *blk)
|
static inline size_t blk_get_size(struct memblk *blk)
|
||||||
{
|
{
|
||||||
return (blk->size & SIZE_MSK) - OVERHEAD;
|
return blk->size & SIZE_MSK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void blk_set_size(struct memblk *blk, size_t size)
|
static void blk_set_size(struct memblk *blk, size_t size)
|
||||||
{
|
{
|
||||||
size &= SIZE_MSK;
|
assert((size & SIZE_MSK) == size);
|
||||||
size += OVERHEAD;
|
|
||||||
|
|
||||||
/* sizeof(size_t) is a power of 2 so this division will become a bitshift */
|
/* don't affect flags */
|
||||||
size_t words = size / sizeof(blk->size);
|
|
||||||
|
|
||||||
blk->size &= SIZE_MSK;
|
blk->size &= ~SIZE_MSK;
|
||||||
blk->size |= size;
|
blk->size |= size;
|
||||||
|
|
||||||
blk->endsz[words] &= SIZE_MSK;
|
size_t words = size / sizeof(blk->size);
|
||||||
|
blk->endsz[words] &= ~SIZE_MSK;
|
||||||
blk->endsz[words] |= size;
|
blk->endsz[words] |= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,7 +465,7 @@ static inline struct memblk *blk_prev(struct memblk *blk)
|
||||||
{
|
{
|
||||||
if (blk_is_border_start(blk))
|
if (blk_is_border_start(blk))
|
||||||
return NULL;
|
return NULL;
|
||||||
return (void *)blk - blk->prevsz[-1];
|
return (void *)blk - blk->prevsz[-1] - OVERHEAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct memblk *blk_next(struct memblk *blk)
|
static inline struct memblk *blk_next(struct memblk *blk)
|
||||||
|
@ -475,7 +474,7 @@ static inline struct memblk *blk_next(struct memblk *blk)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
size_t words = blk->size / sizeof(blk->size);
|
size_t words = blk->size / sizeof(blk->size);
|
||||||
return (void *)blk->endsz[words + 1];
|
return (void *)&blk->endsz[words + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue