📄 mem.c
字号:
/******************************************************************************
Copyright (c) 2006 by RockOS.
All rights reserved.
This software is supported by the Rock Software Workroom only.
Any bugs please contact the author with e-mail or QQ:
E-mail : baobaoba520@yahoo.com.cn
QQ : 59681888
*******************************************************************************
File name : mem.c
Description : memory management implement for RockOS.
:
:
Auther : sunxinqiu
History :
2006-3-15 first release.
******************************************************************************/
#include "os.h"
/******************************************************************************
Global var : MEMCB g_memCb[]
Description : the memory control block. It indicates a memory block is invalid,
: free, or busy and its owner task.
******************************************************************************/
MEMCB g_memCb[MEM_BLOCK_NUM];
/******************************************************************************
Global var : U8 * g_memStartAddr;
: U8 * g_memEndAddr;
Description : The memory block start address for RockOS.
: Always, to caculate this address is very compiler depended and
: must be provided by BSP.
******************************************************************************/
U8 * g_memStartAddr;
U8 * g_memEndAddr;
/******************************************************************************
Global var : int g_validMemBlkNum;
: int g_usedMemBlkNum;
Description : valid memory block numbers and used memory block numbers.
:
******************************************************************************/
int g_validMemBlkNum;
int g_usedMemBlkNum;
/******************************************************************************
Function : STATUS mem_init()
Params : N/A
:
:
:
Return : NO_ERRCODE always
Description : This function is called during system initializing.
******************************************************************************/
STATUS mem_init()
{
int i;
if (g_OSRunning != OS_PHASE_INIT)
{
OS_error("mem_init(): this function can't be called after system in scheduling!!!\n");
return OS_FAIL;
}
/* get OS heap memory start address. */
g_memStartAddr = getMemStartAddr();
if (g_memStartAddr == NULL)
{
OS_error("mem_init(): get memory block start address fail!!!\n");
return OS_FAIL;
}
/* get OS heap memory end address. */
g_memEndAddr = getMemEndAddr();
if ((g_memEndAddr == NULL)||(g_memEndAddr < g_memStartAddr))
{
OS_error("mem_init(): get memory block end address failure!!!\n");
return OS_FAIL;
}
g_validMemBlkNum = 0;
g_usedMemBlkNum = 0;
/* clear all heap memory to 0. */
memset (g_memStartAddr, 0, g_memEndAddr - g_memStartAddr);
/* create memory block list. */
for (i = 0; i < MEM_BLOCK_NUM; i++)
{
memset (&g_memCb[i], 0, sizeof(MEMCB));
g_memCb[i].owner = NULL_TASK;
g_memCb[i].start_addr = g_memStartAddr + i * MEM_BLOCK_SIZE;
if (g_memCb[i].start_addr + MEM_BLOCK_SIZE < g_memEndAddr)
{
g_memCb[i].state = MEM_BLK_FREE;
g_validMemBlkNum++;
}
else
{
g_memCb[i].state = MEM_BLK_INVALID;
}
}
return OS_SUCCESS;
}
/******************************************************************************
Function : void * memAlloc(U32 size, TASKID owner, const char * name)
Params : size - memory size to allocated.
: task_id - the memory block owner
: name - a description for this memory block(for Man-Machine
: inter-acting using.
:
Return : the memory block address, or NULL if failed.
Description : Call this function to allocate one or more memory blocks which
: best fit the size from mem pool.
: This function should never be called in ISRs.
******************************************************************************/
void * memAlloc(U32 size, HTASK owner, const char * name)
{
U32 i, j;
U32 blks;
void * pRet;
/* this function can't be called during ISR running. */
if (g_cpuIntDepth != 0)
{
OS_error("memAlloc(): can't be called during ISR running!!!");
return NULL;
}
/* Get the number of blocks. */
blks = (size + MEM_BLOCK_SIZE - 1)/MEM_BLOCK_SIZE;
if (blks == 0)
{
OS_error ("memAlloc(): zero memory size, return NULL, owner [%d]!!!\n", owner);
return NULL;
}
taskLock();
/* search continious memory blocks */
for (i = 0; i < MEM_BLOCK_NUM - blks; i++)
{
if (g_memCb[i].state == MEM_BLK_FREE)
{
/* check whether there were [blks] continuous free mem blocks. */
for (j = 0; j < blks; j++)
{
if (g_memCb[i+j].state != MEM_BLK_FREE)
{
break;
}
}
if (j >= blks)
{
/* there are [blks] free memory blocks. */
break;
}
}
}
/* found, mark those blocks as used. */
if (i < MEM_BLOCK_NUM - blks)
{
for (j = i; j < i + blks; j++)
{
g_memCb[j].state = MEM_BLK_BUSY;
strncpy (&g_memCb[j].name[0], name, MAX_NAME_LEN);
g_memCb[j].reqSize = size;
g_memCb[j].localSize = size - MEM_BLOCK_SIZE * (j - i);
g_memCb[j].owner = owner;
}
pRet = g_memCb[i].start_addr;
}
else
{
OS_error ("memAlloc(): not enough memory for size [%d], failure!!!\n", size);
pRet = NULL;
}
taskUnlock();
if (pRet != NULL)
{
g_usedMemBlkNum += blks;
}
return pRet;
}
/******************************************************************************
Function : STATUS memFree(void * p)
Params : p - the memory block start address.
:
Return : OS_SUCCESS or OS_FAIL.
Description : Call this function to release one or more memory blocks to mem
: block pool.
: In most embed systems, this function is not needed. RockOS-II
: support creating and removing task dynamicly, this function is
: still mandatory for this purpose.
******************************************************************************/
STATUS memFree(void * p)
{
U32 i;
U32 n;
U32 first;
U32 reqSize;
/* this function can't be called during ISR running. */
if (g_cpuIntDepth != 0)
{
OS_error("memFree(): can't be called during ISR running!!!");
return NULL;
}
/* params checking. */
if (p == NULL)
{
OS_error("memFree(): null pointer to free!!!\n");
return OS_SUCCESS;
}
if ((U8 *)p < g_memStartAddr)
{
OS_error("memFree(): invalid heap memory pointer [%p]!!!\n", p);
return OS_FAIL;
}
n = ((U8 *)p - g_memStartAddr)/MEM_BLOCK_SIZE;
reqSize = g_memCb[n].reqSize;
/* Find the first memory block if point [p] is not the first. */
first = n;
while ((first > 0)
&&(g_memCb[first].localSize > 0)
&&(g_memCb[first-1].localSize == g_memCb[first].localSize + MEM_BLOCK_SIZE)
&&(g_memCb[first-1].reqSize == g_memCb[first].reqSize))
{
first--;
}
if (first != n)
{
OS_error("memFree(): free pointer [%p] is not equal to alloc memory start address [%p], resume free!!!",
p, g_memCb[first].start_addr);
OS_error("owner = [%d], total size = [%d], name = [%s]!!!\n", g_memCb[first].owner,
g_memCb[first].localSize, g_memCb[first].name);
}
/* Free the memory blocks. */
taskLock();
for (i = first; (g_memCb[i].localSize >= MEM_BLOCK_SIZE)&&(g_memCb[i].reqSize == reqSize); i++)
{
memset (&g_memCb[i], 0, sizeof(MEMCB));
g_memCb[i].state = MEM_BLK_FREE;
g_memCb[i].owner = NULL_TASK;
g_memCb[i].start_addr = g_memStartAddr + i * MEM_BLOCK_SIZE;
g_usedMemBlkNum--;
}
taskUnlock();
return OS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -