📄 uffs_mem.c
字号:
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 + -