remaster & refactor dynamic memory allocator - heap
This commit is contained in:
parent
7ec6ee870c
commit
dae46bb74d
4 changed files with 94 additions and 141 deletions
9
cutil.c
9
cutil.c
|
|
@ -7,17 +7,20 @@ mheap_t cu_heap;
|
||||||
|
|
||||||
void* _cu_malloc(size_t size)
|
void* _cu_malloc(size_t size)
|
||||||
{
|
{
|
||||||
return heap_alloc(&cu_heap, size);
|
mblock_t* block = heap_alloc(&cu_heap, size);
|
||||||
|
return block ? (u8*)block + sizeof(mblock_t) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* _cu_realloc(void* mem, size_t size)
|
void* _cu_realloc(void* mem, size_t size)
|
||||||
{
|
{
|
||||||
return heap_realloc(&cu_heap, mem, size);
|
mblock_t* block = heap_realloc(&cu_heap,
|
||||||
|
(mblock_t*)((u8*)mem - sizeof(mblock_t)), size);
|
||||||
|
return block ? (u8*)block + sizeof(mblock_t) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _cu_free(void* mem)
|
void _cu_free(void* mem)
|
||||||
{
|
{
|
||||||
return heap_free(&cu_heap, mem);
|
return heap_free((mblock_t*)((u8*)mem - sizeof(mblock_t)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void* (*cu_malloc)(size_t) = _cu_malloc;
|
void* (*cu_malloc)(size_t) = _cu_malloc;
|
||||||
|
|
|
||||||
185
heap.c
185
heap.c
|
|
@ -1,138 +1,93 @@
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "cutil.h"
|
#include "cutil.h"
|
||||||
|
|
||||||
static mblock_t* mblock_get_next(mblock_t* block)
|
void heap_init(mheap_t* heap, void* start, uword size)
|
||||||
{
|
{
|
||||||
return (mblock_t*)((u8*)block+MBLOCK_ALIGN_SIZE(block->size));
|
heap->start = start;
|
||||||
}
|
|
||||||
|
|
||||||
static mblock_t* mblock_by_data(void* data)
|
|
||||||
{
|
|
||||||
return (mblock_t*)((u8*)data - MBLOCK_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t mblock_get_size(mblock_t* block)
|
|
||||||
{
|
|
||||||
return MBLOCK_ALIGN_SIZE(block->size & ~MBLOCK_ATTR_ALLOC);
|
|
||||||
}
|
|
||||||
|
|
||||||
void heap_init(mheap_t* heap, void* data, uword size)
|
|
||||||
{
|
|
||||||
heap->data = data;
|
|
||||||
heap->size = size;
|
heap->size = size;
|
||||||
|
|
||||||
|
mblock_t* block = (mblock_t*)heap->start;
|
||||||
|
block->prev = NULL;
|
||||||
|
block->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void heap_join(mblock_t* start, int dir)
|
void heap_split(mblock_t* block, uword size)
|
||||||
{
|
{
|
||||||
mblock_t* cur;
|
mblock_t* split = (mblock_t*)((u8*)block + size);
|
||||||
size_t blk_size;
|
|
||||||
|
|
||||||
blk_size = 0;
|
|
||||||
cur = start;
|
|
||||||
while(cur != NULL && !IS_MBLOCK_ALLOC(cur))
|
|
||||||
{
|
|
||||||
blk_size += mblock_get_size(cur);
|
|
||||||
cur->size = 0;
|
|
||||||
if(dir > 0) cur = cur->next;
|
|
||||||
else if(dir < 0) cur = cur->prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dir > 0)
|
|
||||||
{
|
|
||||||
start->next = cur;
|
|
||||||
start->size = MBLOCK_ALIGN_SIZE(blk_size);
|
|
||||||
if(cur)
|
|
||||||
{
|
|
||||||
if(cur->next) cur->next->prev = start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(dir < 0)
|
|
||||||
{
|
|
||||||
if(cur)
|
|
||||||
{
|
|
||||||
cur = cur->next;
|
|
||||||
cur->size = MBLOCK_ALIGN_SIZE(blk_size);
|
|
||||||
cur->next = start->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void heap_split(mblock_t* block, size_t req_size)
|
|
||||||
{
|
|
||||||
size_t tot_size = mblock_get_size(block);
|
|
||||||
mblock_t* split;
|
|
||||||
|
|
||||||
block->size = MBLOCK_ALIGN_SIZE(req_size)|MBLOCK_ATTR_ALLOC;
|
|
||||||
split = mblock_get_next(block);
|
|
||||||
|
|
||||||
//Init prev and next
|
|
||||||
split->prev = block;
|
split->prev = block;
|
||||||
split->next = block->next;
|
split->size = block->size - size;
|
||||||
block->next = split;
|
block->size = size;
|
||||||
|
|
||||||
split->size = MBLOCK_ALIGN_SIZE(tot_size-req_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* heap_alloc(mheap_t* heap, size_t size)
|
void heap_join(mblock_t* block, mblock_t* other)
|
||||||
{
|
{
|
||||||
mblock_t* start,*block,*prev;
|
if (block < other)
|
||||||
size = cu_round2_up((size + MBLOCK_SIZE), MBLOCK_ALIGN);
|
|
||||||
|
|
||||||
/*for(i = 0; i < heap->heapsz; i++)
|
|
||||||
{
|
{
|
||||||
start = (mblock_t*)((u8*)heap->heap+(i<<21));
|
mblock_t* next = (mblock_t*)((u8*)other + other->size);
|
||||||
if(!(start->size & MBLOCK_ATTR_ALLOC_2MB)) break;
|
next->prev = block;
|
||||||
|
block->size += other->size;
|
||||||
}
|
}
|
||||||
if(i == heap->heapsz) return NULL;*/
|
else if (block > other)
|
||||||
start = (mblock_t*)heap->data;
|
|
||||||
|
|
||||||
//Find free block
|
|
||||||
prev = NULL;
|
|
||||||
block = start;
|
|
||||||
do {
|
|
||||||
if((!IS_MBLOCK_ALLOC(block) && mblock_get_size(block) >= size)
|
|
||||||
|| block->size == 0)
|
|
||||||
break;
|
|
||||||
prev = block;
|
|
||||||
if(block->next) block = block->next;
|
|
||||||
else break;
|
|
||||||
} while(block);
|
|
||||||
if(prev == block) prev = NULL;
|
|
||||||
//Allocate
|
|
||||||
if(block->size == 0) //Unformatted
|
|
||||||
{
|
{
|
||||||
block->size = size|MBLOCK_ATTR_ALLOC;
|
mblock_t* next = (mblock_t*)((u8*)block + block->size);
|
||||||
block->prev = prev;
|
next->prev = other;
|
||||||
block->next = mblock_get_next(block);
|
other->size += block->size;
|
||||||
}
|
}
|
||||||
else heap_split(block,size);
|
|
||||||
|
|
||||||
if(prev && !prev->next) prev->next = block;
|
|
||||||
|
|
||||||
return block->data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* heap_realloc(mheap_t* heap, void* mem, size_t size)
|
mblock_t* heap_alloc(mheap_t* heap, uword _size)
|
||||||
{
|
{
|
||||||
mblock_t* block = (mblock_t*)((u8*)mem - MBLOCK_SIZE);
|
uword size = cu_round2_up(_size + sizeof(mblock_t), MBLOCK_ALIGN);
|
||||||
(void)heap;
|
mblock_t* block = (mblock_t*)((u8*)heap->start);
|
||||||
|
mblock_t* end = (mblock_t*)((u8*)heap->start + heap->size);
|
||||||
heap_free(heap, mem);
|
while ((block->size & MBLOCK_ALLOCATED) || MBLOCK_SIZE(block->size) < size)
|
||||||
void* newMem = heap_alloc(heap, size);
|
{
|
||||||
if (mem != newMem)
|
block = (mblock_t*)((u8*)block + MBLOCK_SIZE(block->size));
|
||||||
cu_memcpy(newMem, mem, mblock_get_size(block));
|
if (block >= end) return NULL;
|
||||||
|
}
|
||||||
return newMem;
|
|
||||||
|
if (block->size > size)
|
||||||
|
{
|
||||||
|
heap_split(block, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
block->size |= MBLOCK_ALLOCATED;
|
||||||
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void heap_free(mheap_t* heap, void* mem)
|
void heap_free(mblock_t* block)
|
||||||
{
|
{
|
||||||
mblock_t* block = (mblock_t*)((u8*)mem - MBLOCK_SIZE);
|
block->size &= ~MBLOCK_ALLOCATED;
|
||||||
(void)heap;
|
mblock_t* prev = block->prev;
|
||||||
|
mblock_t* next = (mblock_t*)((u8*)block + block->size);
|
||||||
//Unlink
|
if (!(prev->size & MBLOCK_ALLOCATED))
|
||||||
block->size &= ~MBLOCK_ATTR_ALLOC;
|
heap_join(block, prev);
|
||||||
//Link free blocks prev and next
|
if (!(next->size & MBLOCK_ALLOCATED))
|
||||||
heap_join(block,1);
|
heap_join(block, next);
|
||||||
heap_join(block,-1);
|
}
|
||||||
|
|
||||||
|
mblock_t* heap_realloc(mheap_t* heap, mblock_t* block, uword _size)
|
||||||
|
{
|
||||||
|
block->size &= ~MBLOCK_ALLOCATED;
|
||||||
|
uword size = cu_round2_up(_size, MBLOCK_ALIGN);
|
||||||
|
mblock_t* next = (mblock_t*)((u8*)block + block->size);
|
||||||
|
mblock_t* new;
|
||||||
|
if (!(next->size & MBLOCK_ALLOCATED) && next->size >= size)
|
||||||
|
{
|
||||||
|
new = block;
|
||||||
|
heap_join(new, next);
|
||||||
|
heap_split(new, size);
|
||||||
|
new->size |= MBLOCK_ALLOCATED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
heap_free(block);
|
||||||
|
new = heap_alloc(heap, size);
|
||||||
|
if (new)
|
||||||
|
{
|
||||||
|
cu_memcpy((u8*)new + sizeof(mblock_t),
|
||||||
|
(u8*)block + sizeof(mblock_t), size - sizeof(mblock_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
heap.h
39
heap.h
|
|
@ -3,35 +3,30 @@
|
||||||
|
|
||||||
#include "cutypes.h"
|
#include "cutypes.h"
|
||||||
|
|
||||||
typedef struct mblock_s {
|
|
||||||
struct mblock_s* prev;
|
|
||||||
struct mblock_s* next;
|
|
||||||
uword size;
|
|
||||||
u8 data[1];
|
|
||||||
} mblock_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8* data;
|
void* start;
|
||||||
uword size;
|
uword size;
|
||||||
} mheap_t;
|
} mheap_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* prev;
|
||||||
|
uword size;
|
||||||
|
} mblock_t;
|
||||||
|
|
||||||
|
#define MBLOCK_ALLOCATED (1<<0)
|
||||||
|
#define MBLOCK_SIZE(size) ((size) & ~MBLOCK_ALLOCATED)
|
||||||
|
|
||||||
#ifdef CU_64BIT
|
#ifdef CU_64BIT
|
||||||
# define MBLOCK_ALIGN 5
|
|
||||||
#else
|
|
||||||
# define MBLOCK_ALIGN 4
|
# define MBLOCK_ALIGN 4
|
||||||
|
#else
|
||||||
|
# define MBLOCK_ALIGN 3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MBLOCK_SIZE (CU_WORD_SIZE*3)
|
void heap_init(mheap_t* heap, void* start, uword size);
|
||||||
#define MBLOCK_SIZE_MASK ((CU_WORD_BITS/8) - 1)
|
void heap_split(mblock_t* block, uword size);
|
||||||
#define MBLOCK_ALIGN_SIZE(size) (cu_round2_up((size), MBLOCK_ALIGN))
|
void heap_join(mblock_t* block, mblock_t* other);
|
||||||
#define MBLOCK_ATTR_ALLOC (1<<0)
|
mblock_t* heap_alloc(mheap_t* heap, uword _size);
|
||||||
#define IS_MBLOCK_ALLOC(mblock) (mblock->size & MBLOCK_ATTR_ALLOC)
|
void heap_free(mblock_t* block);
|
||||||
|
mblock_t* heap_realloc(mheap_t* heap, mblock_t* block, uword _size);
|
||||||
void heap_init(mheap_t* heap, void* data, uword size);
|
|
||||||
void heap_join(mblock_t* start, int dir);
|
|
||||||
void heap_split(mblock_t* block, size_t req_size);
|
|
||||||
void* heap_alloc(mheap_t* heap, size_t size);
|
|
||||||
void* heap_realloc(mheap_t* heap, void* mem, size_t size);
|
|
||||||
void heap_free(mheap_t* heap, void* mem);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
2
test.c
2
test.c
|
|
@ -207,7 +207,7 @@ int main()
|
||||||
void* m1 = heap_alloc(&heap, 8);
|
void* m1 = heap_alloc(&heap, 8);
|
||||||
void* m2 = heap_alloc(&heap, 32);
|
void* m2 = heap_alloc(&heap, 32);
|
||||||
void* m3 = heap_alloc(&heap, 9);
|
void* m3 = heap_alloc(&heap, 9);
|
||||||
heap_free(&heap, m2);
|
heap_free(m2);
|
||||||
void* m4 = heap_alloc(&heap, 8);
|
void* m4 = heap_alloc(&heap, 8);
|
||||||
printf("heap_alloc\t%p\n", m1);
|
printf("heap_alloc\t%p\n", m1);
|
||||||
printf("heap_alloc\t%p\n", m2);
|
printf("heap_alloc\t%p\n", m2);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue