blob: 8ea6ff6dd88a8a4adaf65e8bb275e79a17e14543 [file] [log] [blame]
#line 1 "memmgr.c"
#line 1 "./memmgr.h"
typedef unsigned char byte;
typedef unsigned long ulong;
void memmgr_init();
void* memmgr_alloc(ulong nbytes);
void memmgr_free(void* ap);
void memmgr_print_stats();
#line 9 "memmgr.c"
typedef ulong Align;
union mem_header_union
{
struct
{
union mem_header_union* next;
ulong size;
} s;
Align align_dummy;
};
typedef union mem_header_union mem_header_t;
static mem_header_t base;
static mem_header_t* freep = 0;
static byte pool[8 * 1024] = {0};
static ulong pool_free_pos = 0;
void memmgr_init()
{
base.s.next = 0;
base.s.size = 0;
freep = 0;
pool_free_pos = 0;
}
void memmgr_print_stats()
{
mem_header_t* p;
printf("------ Memory manager stats ------\n\n");
printf( "Pool: free_pos = %lu (%lu bytes left)\n\n",
pool_free_pos,8 * 1024 - pool_free_pos);
p = (mem_header_t*) pool;
while (p < (mem_header_t*) (pool + pool_free_pos))
{
printf( " * Addr: 0x%8lu; Size: %8lu\n",
p, p->s.size);
p += p->s.size;
}
printf("\nFree list:\n\n");
if (freep)
{
p = freep;
while (1)
{
printf( " * Addr: 0x%8lu; Size: %8lu; Next: 0x%8lu\n",
p, p->s.size, p->s.next);
p = p->s.next;
if (p == freep)
break;
}
}
else
{
printf("Empty\n");
}
printf("\n");
}
static mem_header_t* get_mem_from_pool(ulong nquantas)
{
ulong total_req_size;
mem_header_t* h;
if (nquantas < 16)
nquantas = 16;
total_req_size = nquantas * sizeof(mem_header_t);
if (pool_free_pos + total_req_size <= 8 * 1024)
{
h = (mem_header_t*) (pool + pool_free_pos);
h->s.size = nquantas;
memmgr_free((void*) (h + 1));
pool_free_pos += total_req_size;
}
else
{
return 0;
}
return freep;
}
void* memmgr_alloc(ulong nbytes)
{
mem_header_t* p;
mem_header_t* prevp;
ulong nquantas = (nbytes + sizeof(mem_header_t) - 1) / sizeof(mem_header_t) + 1;
if ((prevp = freep) == 0)
{
base.s.next = freep = prevp = &base;
base.s.size = 0;
}
for (p = prevp->s.next; ; prevp = p, p = p->s.next)
{
if (p->s.size >= nquantas)
{
if (p->s.size == nquantas)
{
prevp->s.next = p->s.next;
}
else
{
p->s.size -= nquantas;
p += p->s.size;
p->s.size = nquantas;
}
freep = prevp;
return (void*) (p + 1);
}
else if (p == freep)
{
if ((p = get_mem_from_pool(nquantas)) == 0)
{
return 0;
}
}
}
}
void memmgr_free(void* ap)
{
mem_header_t* block;
mem_header_t* p;
block = ((mem_header_t*) ap) - 1;
for (p = freep; !(block > p && block < p->s.next); p = p->s.next)
{
if (p >= p->s.next && (block > p || block < p->s.next))
break;
}
if (block + block->s.size == p->s.next)
{
block->s.size += p->s.next->s.size;
block->s.next = p->s.next->s.next;
}
else
{
block->s.next = p->s.next;
}
if (p + p->s.size == block)
{
p->s.size += block->s.size;
p->s.next = block->s.next;
}
else
{
p->s.next = block;
}
freep = p;
}