www.pudn.com > ASM86_64.rar > balloc.c
/*
*
* the file for mik's assmbler: a64 poject;
*
*
*/
#include "balloc.h"
/* free-memory-link buffer */
static mem_link_t free_link_buf[FREELINKSIZE];
/* used-memory-link buffer */
static mem_link_t used_link_buf[USEDLINKSIZE];
/* default buffer-heap for balloc() */
static char buf_heap[POOLSIZE];
/* alloc-heap-struct for balloc() */
static alloc_heap_t alloc_heap, *alloc_heap_ptr = &alloc_heap;
/*
* this function for test....
*/
void print_alloc_heap()
{
mem_link_t *free_link = alloc_heap_ptr->free_link;
mem_link_t *used_link = alloc_heap_ptr->used_link;
int i = 1;
printf("\nfree_link_buf is %x\n", free_link_buf);
printf("used_link_buf is %x\n", used_link_buf);
printf("buffer heap is %x\n\n", alloc_heap_ptr->heap);
printf(" free buffer-heap-link: \n");
printf("--------------------------------------------------\n");
printf("no.\tsize\thead\ttail\tused\n");
while (free_link) {
printf("%d\t%d\t%x\t%x\t%d\n", i++, free_link->size,
free_link->head_ptr, free_link->tail_ptr,
free_link->used);
free_link = free_link->next;
}
puts("\n");
puts(" used buffer-heap-link: ");
puts("------------------------------------------------------");
printf("no.\tsize\thead\ttial\tused\n");
i = 1;
while (used_link) {
printf("%d\t%d\t%x\t%x\t%d\n", i++, used_link->size,
used_link->head_ptr, used_link->tail_ptr,
used_link->used);
used_link = used_link->next;
}
}
__inline__ void init_mem_link()
{
memset(free_link_buf, 0, sizeof(free_link_buf));
memset(used_link_buf, 0, sizeof(used_link_buf));
}
int init_alloc_heap(unsigned int size, void *bufptr)
{
unsigned int poolsize;
/* initialize the free_link_buf & used_link_buf */
init_mem_link();
/* the buffer pool already initialize */
if (alloc_heap_ptr->heap && alloc_heap_ptr->heap == bufptr)
return EOK;
if (!bufptr) {
/* default buffer heap for user */
alloc_heap_ptr->heap = (void *)buf_heap;
poolsize = POOLSIZE;
} else {
if (!size)
return EINIT;
alloc_heap_ptr->heap = (void *)bufptr;
poolsize = size;
}
memset(alloc_heap_ptr->heap, 0, poolsize);
alloc_heap_ptr->total_size = poolsize;
alloc_heap_ptr->free_size = poolsize;
alloc_heap_ptr->used_link = 0;
alloc_heap_ptr->free_link = &free_link_buf[0];
/* free-heap-link initialize */
free_link_buf[0].size = alloc_heap_ptr->free_size;
free_link_buf[0].head_ptr = (void *)alloc_heap_ptr->heap;
free_link_buf[0].tail_ptr = (void *)alloc_heap_ptr->heap + poolsize;
free_link_buf[0].used = 1;
free_link_buf[0].next = 0;
free_link_buf[0].prev = 0;
/* successed */
return EOK;
}
/* allocate a mem-link */
unsigned int alloc_memlink(mem_link_t *mem_link)
{
int i = 0;
int linksize =
mem_link == free_link_buf ? FREELINKSIZE : USEDLINKSIZE;
while (i < linksize) {
if (mem_link[i].used == 0) /* free */
return i;
i++;
}
return -1;
}
__inline__ unsigned int alloc_free_memlink()
{
return alloc_memlink(free_link_buf);
}
__inline__ unsigned int alloc_used_memlink()
{
return alloc_memlink(used_link_buf);
}
/**********************************************************************/
unsigned int mount_link(mem_link_t *link, mem_link_t *new)
{
int is_free_link = link == alloc_heap_ptr->free_link ? 1 : 0;
while (link) {
if (is_free_link) {
if ((link->tail_ptr + 1 == new->head_ptr)
&& (link->next->head_ptr == new->tail_ptr + 1))
{
link->tail_ptr += new->size + link->next->size;
link->next = link->next->next;
link->size += new->size + link->next->size;
memset(link->next, 0, sizeof(mem_link_t));
memset(new, 0, sizeof(mem_link_t));
return EOK;
} else if (link->tail_ptr + 1 == new->head_ptr) {
link->tail_ptr += new->size;
link->size += new->size;
memset(new, 0, sizeof(mem_link_t));
return EOK;
} else if (link->head_ptr == new->tail_ptr + 1) {
link->head_ptr -= new->size;
link->size += new->size;
memset(new, 0, sizeof(mem_link_t));
return EOK;
}
}
if (!link->next) break;
link = link->next;
}
link->next = new;
link->next->next = 0;
link->next->prev = link;
return EOK;
}
/* the function: mount the free memory link */
unsigned int mount_free_link(void *ptr, unsigned int size)
{
int number = alloc_free_memlink();
if (number == -1) return -1;
free_link_buf[number].used = 1;
free_link_buf[number].head_ptr = ptr;
free_link_buf[number].tail_ptr = ptr + size - 1;
free_link_buf[number].size = size;
if (alloc_heap_ptr->free_link)
return mount_link(alloc_heap_ptr->free_link,
&free_link_buf[number]);
free_link_buf[number].next = 0;
free_link_buf[number].prev = 0;
alloc_heap_ptr->free_link = &free_link_buf[number];
return EOK;
}
/* the function: mount the used memory link */
unsigned int mount_used_link(void *ptr, unsigned int size)
{
int number = alloc_used_memlink();
if (number == -1) return -1;
used_link_buf[number].used = 1; /* used by alloc */
used_link_buf[number].size = size;
used_link_buf[number].head_ptr = ptr;
used_link_buf[number].tail_ptr = ptr + size - 1;
if (alloc_heap_ptr->used_link)
return mount_link(alloc_heap_ptr->used_link,
&used_link_buf[number]);
/* no used and full free */
used_link_buf[number].next = 0;
used_link_buf[number].prev = 0;
alloc_heap_ptr->used_link = &used_link_buf[number];
return EOK;
}
/***********************************************************************/
__inline__ void do_umount_link(mem_link_t *old)
{
if (old->prev)
old->prev->next = old->next;
if (old->next)
old->next->prev = old->prev;
}
void umount_free_link(mem_link_t *old, unsigned int size)
{
old->used = 0;
alloc_heap_ptr->free_size -= size;
if (!old->prev && !old->next) {
/* only 1-node */
if (alloc_heap_ptr->free_size == 0)
alloc_heap_ptr->free_link = 0;
else {
old->used = 1;
old->size -= size;
old->head_ptr += size;
}
} else if (!old->prev) {
alloc_heap_ptr->free_link = old->next;
old->next->prev = 0;
} else
do_umount_link(old);
}
void umount_used_link(mem_link_t *old)
{
old->used = 0;
alloc_heap_ptr->free_size += old->size;
if (!old->prev && !old->next)
if (alloc_heap_ptr->free_size == alloc_heap_ptr->total_size) {
alloc_heap_ptr->used_link = 0;
} else {
old->used = 1;
}
else if (!old->prev) {
alloc_heap_ptr->used_link = old->next;
old->next->prev = 0;
} else
do_umount_link(old);
}
/***********************************************************************/
/* the function same as C malloc */
void *balloc(unsigned int size)
{
mem_link_t *free_link = alloc_heap_ptr->free_link;
mem_link_t *used_link = alloc_heap_ptr->used_link;
while (free_link && (alloc_heap_ptr->free_size >= size)) {
if (free_link->size >= size) { /* OK */
void *ret = free_link->head_ptr;
/* mount at used link */
if (mount_used_link(ret, size) == -1) {
return 0;
}
/* umount the free link */
umount_free_link(free_link, size);
return ret;
}
free_link = free_link->next;
}
return 0;
}
/* the function same as C free */
int bfree(void *ptr)
{
if (!ptr) return EOK;
mem_link_t *used_link = alloc_heap_ptr->used_link;
mem_link_t *free_link = alloc_heap_ptr->free_link;
while (used_link) {
if ((ptr >= used_link->head_ptr) &&
(ptr <= used_link->tail_ptr))
{
/* umount used link, so the memory block is free */
umount_used_link(used_link);
/* mount at free link*/
mount_free_link(ptr, used_link->size);
return EOK;
}
used_link = used_link->next;
}
return EERROR;
}