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;
}