⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uffs_mem.c

📁 nandflash文件系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	p = _kmalloc(size);
	if(p)
		memset(p, 0, size);
	return p;
}
#endif

/*!
 * \brief Return a block to heap memory.
 *
 * An application calls this function, when a previously
 * allocated memory block is no longer needed.
 *
 * The heap manager checks, if the released block adjoins any
 * other free regions. If it does, then the adjacent free regions
 * are joined together to form one larger region.
 *
 * \note Interrupts are automatically enabled, when this
 *       function returns.
 *
 * \param block Points to a memory block previously allocated
 *              through a call to _kmalloc().
 *
 * \return 0 on success, -1 if the caller tried to free
 *         a block which had been previously released.
 */
static int _kfree(void *block)
{
	HEAPNODE *node;
	HEAPNODE *prev;
	HEAPNODE *next;
	if (block == NULL) {
		return -1;	//the pointer of the memory is invalid.
	}
	uffs_CriticalEnter();	/* enter critical */
	
	node = (HEAPNODE *)((u32)block - ALLOC_OFFSET);
	if(node->mark != (int)HEAP_NODE_ALLOCED || node->size <= ALLOC_OFFSET) {
		uffs_CriticalExit();/* exit critical */
		return -1;	/*!!!! at this moment, the heap 
						management info must be damaged !!!!!*/
	}
	_k_heap_available += node->size;
	
	prev = node->prevNode;
	next = (HEAPNODE *)((u32)node + node->size);

	if(prev->mark == HEAP_NODE_FREE){
        /*
         * If there' s a free node in front of us, merge it.
         */
		prev->size += node->size;
		next->prevNode = prev;
		HeapDeleteFromFreeList(prev);
		node = prev;
	}

	if(next->mark == HEAP_NODE_FREE){
        /*
         * If there' s a free node following us, merge it.
         */
		node->size += next->size;
		((HEAPNODE *)((u32)next + next->size))->prevNode = node;
		HeapDeleteFromFreeList(next);
	}

	/*
	 *	now, we just chain the node to free list head.
	 */
	node->mark = HEAP_NODE_FREE;
	HeapChainToFreeList(node);
	uffs_CriticalExit();	/* exit critical */
	
	return 0;
}


/*!
 * \brief
 * Add a new memory region to the free heap.
 *
 * This function is called during
 * initialization.
 *
 * Applications typically do not call this function.
 *
 * \param addr Start address of the memory region.
 * \param size Number of bytes of the memory region.
 */
void uffs_InitHeapMemory(void *addr, int size)
{
	HEAPNODE *np;
	
	
	if(!((u32)addr & 3)){
		addr = (void *)(((u32)addr) + 4);
		addr = (void *)(((u32)addr) & ~3);
	}
	size &= ~ALLOC_PAGE_MASK;
	if(size < ALLOC_PAGE_SIZE * 3) return;

	uffs_CriticalEnter();
	
	/* pre alloc header node, size is ALLOC_PAGE_SIZE */
	np = (HEAPNODE *)addr;
	np->size = ALLOC_PAGE_SIZE;
	np->mark = HEAP_NODE_ALLOCED;
	np->prevNode = NULL;

	/* pre alloc tail node, size is -1 */
    np = (HEAPNODE *)((u32)addr + size - ALLOC_PAGE_SIZE);
	np->mark = HEAP_NODE_ALLOCED;
	np->size = -1;
	np->prevNode = (HEAPNODE *)((u32)addr + ALLOC_PAGE_SIZE);
	_k_heapTail_ = np;

	/* Free list head */
    np = (HEAPNODE *)((u32)addr + ALLOC_PAGE_SIZE);
    np->mark = HEAP_NODE_FREE;
    np->prevNode = (HEAPNODE *)addr;
    np->size = size - 2 * ALLOC_PAGE_SIZE;
    np->nextFree = NULL;
    np->prevFree = NULL;
	_k_heapFreeList = np;
	_k_heap_available = np->size;
	_minimu_heap_avaiable = _k_heap_available;
	
	_kernel_heap_total += size;

	uffs_CriticalExit();
}

/******************************************************************************************/


static void *__umalloc(uffs_memAllocator *mem, unsigned int size, HASHTBL * heapHashTbl);
static void *__ucalloc(uffs_memAllocator *mem, unsigned int num, unsigned int size, HASHTBL *heapHashTbl);
static void *__urealloc(uffs_memAllocator *mem, void *block, unsigned int size, HASHTBL *heapHashTbl);
static int __ufree(uffs_memAllocator *mem, void *p, HASHTBL * heapHashTbl);


///* init malloc/free system */
//static HASHTBL * InitHeapMM(void)
//{
//	HASHTBL * heapHashTbl;
//	heapHashTbl = (HASHTBL *)_kmalloc(sizeof(HEAP_MM*) * HEAP_HASH_SIZE);
//	if(heapHashTbl != NULL){
//		memset(heapHashTbl, 0, sizeof(HEAP_MM*) * HEAP_HASH_SIZE);
//		return heapHashTbl;
//	}
//	else{
//		return NULL;
//	}
//}

/* release all alloced memory from hash table,
 * return alloced pointer nummber.
 */
static int ReleaseHeap(uffs_memAllocator *mem, HASHTBL *heapHashTbl)
{
	int i;
	int count = 0;
	HEAP_MM volatile * node;

	if(heapHashTbl == NULL) return -1;
	for(i = 0; i < HEAP_HASH_SIZE; i++){
		while((node = heapHashTbl[i]) != NULL){
			__ufree(mem, node->p, heapHashTbl);
			count++;
		}
	}
	_kfree(heapHashTbl);
	return count;
}

static void *uffs_malloc(struct uffs_DeviceSt *dev, unsigned int size)
{
	HASHTBL * heapHashTbl;

	if((int)size < 0) return NULL;
	heapHashTbl = dev->mem.tbl;
	if(heapHashTbl){
		return __umalloc(&dev->mem, size, heapHashTbl);
	}
	else{
		return NULL;
	}
}


/* alloc one block with given size, return the block pointer */
static void *__umalloc(uffs_memAllocator *mem, unsigned int size, HASHTBL *heapHashTbl)
{
	void *p;
	HEAP_MM *node;
	int idx;
	
	/* calling kernel routin allocate bigger size memory block */
	p = _kmalloc(HEAP_MAGIC_SIZE + size + HEAP_MAGIC_SIZE);
	
	if(p){
		node = (HEAP_MM *)_kmalloc(sizeof(HEAP_MM));
		if(node == NULL){
			_kfree(p);
			return NULL;
		}
		p = (void *)((u32)p + HEAP_MAGIC_SIZE);	/* adjust pointer first */
		node->p = p;
		node->size = size;
		mem->count += size;
		if (mem->maxused < mem->count) mem->maxused = mem->count;
		node->task_id = uffs_OSGetTaskId();	/* get task id */
		
		uffs_CriticalEnter();
		
		/* insert node to hash table */
		idx = GET_HASH_INDEX(p);
		node->next = heapHashTbl[idx];
		heapHashTbl[idx] = node;
		
		uffs_CriticalExit();
		return p;	/* ok, return the pointer */
	}
	return NULL;
}

/* Allocates an array in memory with elements initialized to 0 */
static void *__ucalloc(uffs_memAllocator *mem, unsigned int num, unsigned int size, HASHTBL *heapHashTbl)
{
	return __umalloc(mem, num * size, heapHashTbl);
}


/* realloc one block with given size, return the block pointer */
static void *__urealloc(uffs_memAllocator *mem, void *block, unsigned int size, HASHTBL *heapHashTbl)
{
	void *p, *pNew;
	HEAP_MM *prev, *node;
	int idx;

	if(block == NULL) {
		return __umalloc(mem, size, heapHashTbl);
	}

	if(size == 0) {
		__ufree(mem, block, heapHashTbl);
		return NULL;
	}

	/* calculate hash idx */
	idx = GET_HASH_INDEX(block);

	/* check whether block pointer is alloc from this heap... */
	uffs_CriticalEnter();
	node = heapHashTbl[idx];
	prev = NULL;
	while(node){
		if(node->p == block){
			break; /* got it! */
		}
		prev = node;
		node = node->next;	/* search for next node */
	}

	if(!node) {
		/* not my duty :-) */
		uffs_CriticalExit();
		return NULL;
	}

	/* ok, begin call kernel API to realloc memory */

	p = (void *)((u32)block - HEAP_MAGIC_SIZE);	/* get real pointer which kernel need */
	pNew = _krealloc(p, HEAP_MAGIC_SIZE + size + HEAP_MAGIC_SIZE);

	if(pNew == NULL) {	/* realloc fail */
		uffs_CriticalExit();
		return NULL;
	}

	if(pNew == p) {
		/* new block is the same as the old block */
		uffs_CriticalExit();
		return block;
	}

	/* new block is difference with old block, we need to change hash table ... */
	if(prev){
		/* prev is not the first */
		prev->next = node->next;
	}
	else{
		/* this node is the first, so.. */
		heapHashTbl[idx] = node->next;
	}
	uffs_CriticalExit();

	node->p = (void *)((u32)pNew + HEAP_MAGIC_SIZE);
	node->size = size;
	node->task_id = uffs_OSGetTaskId();

	/* insert node into hash table */
	idx = GET_HASH_INDEX(node->p);
	uffs_CriticalEnter();
	node->next = heapHashTbl[idx];
	heapHashTbl[idx] = node;
	uffs_CriticalExit();

	return node->p;
	
}


/* free the block, if the pointer(parameter 'p') is 
 * not valid(allocated by this allocate system) or error occur, return -1,
 * else return 0
 */
static int __ufree(uffs_memAllocator *mem, void *p, HASHTBL *heapHashTbl)
{
	HEAP_MM *node, *prev;
	
	if(p){	/* check the pointer */
		uffs_CriticalEnter();
		node = heapHashTbl[GET_HASH_INDEX(p)];
		prev = NULL;
		while(node){
			if(node->p == p) {
				/* we find the node, so begin to release */
				if(prev){
					/* this node is not the first */
					prev->next = node->next;
				}
				else{
					/* this node is the first node of hash channel */
					heapHashTbl[GET_HASH_INDEX(p)] = node->next;
				}

				mem->count -= node->size;
				
				uffs_CriticalExit();
				if(_kfree(node) == -1)	/* calling kernel routine release node */
					return -1;			/* fail, return -1 */
				
				/* calling kernel routine and return */
				return _kfree((void *)((u32)p - HEAP_MAGIC_SIZE)); 
			}
			prev = node;
			node = node->next;	/* search for next node */
		}
		uffs_CriticalExit();
	}
	return -1;
}

static URET uffs_free(struct uffs_DeviceSt *dev, void *block)
{
	HASHTBL *heapHashTbl;
	heapHashTbl = dev->mem.tbl;
	if(heapHashTbl){
		if (__ufree(&dev->mem, block, heapHashTbl) < 0) {
			uffs_Perror(UFFS_ERR_SERIOUS, PFX"Try to free unmanaged memory ?\n");
			return U_FAIL;
		}
	}
	return U_SUCC;
}

URET uffs_initNativeMemAllocator(uffs_Device *dev)
{
	uffs_memAllocator *mem = &dev->mem;

	memset(mem->tbl, 0, sizeof(mem->tbl));
	mem->malloc = uffs_malloc;
	mem->free = uffs_free;
	mem->blockinfo_buffer_size = 0;
	mem->page_buffer_size = 0;
	mem->tree_buffer_size = 0;
	mem->one_page_buffer_size = 0;

	return U_SUCC;
}


URET uffs_releaseNativeMemAllocator(uffs_Device *dev)
{
	int count;
	URET ret = U_SUCC;
	if (dev) {
		count = ReleaseHeap(&dev->mem, dev->mem.tbl);
		if (count < 0) {
			uffs_Perror(UFFS_ERR_SERIOUS, PFX"Release native memory allocator fail!\n");
			ret = U_FAIL;
		}
		else if (count > 0) {
			uffs_Perror(UFFS_ERR_NORMAL, PFX"Find %d block memory leak!\n", count);
		}
	}
	return ret;
}

/**
 * \brief Setup the memory allocator to native memory allocator
 *
 * \param allocator memory allocator to be setup
 */
void uffs_SetupNativeMemoryAllocator(uffs_memAllocator *allocator)
{
	memset(allocator, 0, sizeof(uffs_memAllocator));
	allocator->init = uffs_initNativeMemAllocator;
	allocator->release = uffs_releaseNativeMemAllocator;
}

#endif //USE_NATIVE_MEMORY_ALLOCATOR

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -