📄 mem.c
字号:
SizeNeeded &= ~3;
#endif
if (SizeNeeded >= sizeof(sBlockHead)) {
/* Set the size of the user part of the split. */
pUser = (sBlockHead *)(((char *)pBlock) + SizeNeeded);
assert ((((UWord16)pUser) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
assert (((BlockSize - SizeNeeded) & 0x0003) == 0); /* Ensure that Remainder is double-word aligned */
pUser -> Size = (Int32) (BlockSize - SizeNeeded);
assert ((pUser -> Size & 0x0003) == 0); /* Ensure that pUser -> Size is double-word aligned */
assert ((SizeNeeded & 0x0003) == 0); /* Ensure that Remainder is double-word aligned */
pBlock -> Size = (Int32) SizeNeeded;
assert ((pBlock -> Size & 0x0003) == 0); /* Ensure that pUser -> Size is double-word aligned */
}
else {
pUser = pBlock;
}
/* Store a pointer to a likely candidate block. */
archGetSetSaturationMode(bSatMode);
return pUser;
}
#pragma warn_unusedarg reset
/*******************************************************
*
* Method: memInitializePool
*
* Description: This function Initializes the memory pool to all zeroes.
* Brackets the pool with two blocks: The last sizeof(UInt32)
* bytes will be set to 0 to indicate the last block of the pool.
* The first sizeof(UInt32) bytes of the pool will be set
* to the size of the remainder of the pool.
*
* Arguments:
* pMemPool - pointer to the memory pool
* pMem - pointer to the memory
* Size - size of the memory block
* Protect - TRUE = enable protect memory
* Assert - TRUE = enable assert
*
* Return: None
*
*******************************************************/
extern void memInitializePool(mem_sPool * pMemPool,
void * pMem,
size_t Size,
bool Protect,
bool Assert)
{
bool bSatMode;
sBlockHead * pFirst = (sBlockHead *)pMem;
sBlockHead * pLast;
sPool * pPool = (sPool *) pMemPool;
bSatMode = archGetSetSaturationMode(false);
/* Ensure that pFirst is double-word aligned */
assert ((((UWord16)pFirst) & 0x0001) == 0);
/* Ensure that enough memory has been allocated */
assert (Size >= 2 * sizeof(sBlockHead));
/* Make sure that we've allocated enough space for the mem pool. */
assert(sizeof(mem_sPool) >= sizeof(sPool));
/* Clear the entire memory pool. */
memset((void *)pFirst, 0, Size);
/* Mark the first block with the size of the entire allocatable memory
// pool. The size always includes the size of the sBlockHead. */
Size -= sizeof(*pLast);
/* Ensure that Remainder is double-word aligned */
assert ((Size & 0x0003) == 0);
pFirst -> Size = (Int32)Size;
/* Point pLast to end of the memory pool and mark the end block with a
// zero end marker. */
pLast = (sBlockHead *) ((char *) pFirst + Size);
/* Ensure that pLast is double-word aligned */
assert ((((UWord16)pLast) & 0x0001) == 0);
pLast -> Size = 0;
/* If the user wants atomic access to this memory pool... */
if (Protect) {
memProtect((mem_sPool *) pPool);
}
/* Prime the memory pool. */
pPool -> Assert = Assert;
pPool -> pFirst = pFirst;
pPool -> pLast = pLast;
pPool -> pCurrent = pFirst;
pPool -> Protect = Protect;
archGetSetSaturationMode(bSatMode);
}
/*******************************************************
*
* Method: memExtendPool
*
* Description: Initializes the memory pool extension to all zeroes. Extends the
* pool previously initialized with memInitializePool.
*
* Arguments:
* pMemPool - pointer to the memory pool
* pMem - pointer to the memory block
* Size - size of the memory block
*
* Return: None
*
*******************************************************/
void memExtendPool ( mem_sPool * pMemPool,
void * pMem,
size_t Size
)
{
bool bSatMode;
sBlockHead * pFirst = (sBlockHead *)pMem;
sBlockHead * pLast;
sBlockHead * pTemp;
sBlockHead * pNext;
sPool * pPool = (sPool *) pMemPool;
bSatMode = archGetSetSaturationMode(false);
/* Ensure that pFirst is double-word aligned */
assert ((((UWord16)pFirst) & 0x0001) == 0);
/* Ensure that enough memory has been allocated */
assert (Size >= 2 * sizeof(sBlockHead));
/* Clear the entire memory pool. */
memset((void *)pFirst, 0, Size);
/* Mark the first block with the size of the entire extension
// The size always includes the size of the sBlockHead. */
Size -= sizeof(*pLast);
/* Ensure that Remainder is double-word aligned */
assert ((Size & 0x0003) == 0);
pFirst -> Size = (Int32)Size;
/* Point pLast to end of the memory pool and mark the end block with a
// zero end marker. */
pLast = (sBlockHead *) ((char *) pFirst + Size);
assert ((((UWord16)pLast) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
/* Link the extension into the pool */
if (pLast < pPool->pFirst) {
pLast->Size = (Int32)((UInt32)((char*)pLast) - (UInt32)((char*)(pPool->pFirst)));
pPool->pFirst = pFirst;
} else if (pFirst > pPool->pLast) {
pPool->pLast->Size = (Int32)(((UInt32)((char*)(pPool->pLast))) - ((UInt32)((char*)pFirst)));
pLast->Size = 0;
pPool->pLast = pLast;
} else {
pTemp = pPool->pFirst;
while (true) {
if (pTemp->Size > 0) {
pTemp = (sBlockHead *)(((char *)pTemp) + pTemp->Size);
/* Ensure that pBlock is double-word aligned */
assert ((((UWord16)pTemp) & 0x0001) == 0);
} else {
pNext = (sBlockHead *)(((char *)pTemp) - pTemp->Size);
/* Ensure that pBlock is double-word aligned */
assert ((((UWord16)pNext) & 0x0001) == 0);
if (pFirst > pTemp && pLast < pNext) {
pTemp->Size = (Int32)((UInt32)((char*)pTemp) - (UInt32)((char*)pFirst));
/* Ensure that Remainder is double-word aligned */
assert ((pTemp->Size & 0x0003) == 0);
pLast->Size = (Int32)((UInt32)((char *)pLast) - (UInt32)((char *)pNext));
/* Ensure that Remainder is double-word aligned */
assert ((pLast->Size & 0x0003) == 0);
break;
}
pTemp = pNext;
}
}
}
archGetSetSaturationMode (bSatMode);
}
/*******************************************************
*
* Method: memFree
*
* Description: This method frees the allocated memory.
*
* Arguments:
* pMemPool - pointer to the memory pool
*
* Return: None
*
*******************************************************/
#pragma warn_unusedarg off
extern void memFree(mem_sPool * pMemPool, void * pData)
{
bool bSatMode;
sBlockHead * pBlock = pData;
/* The following two lines are a check to ensure that
// dynamic memory has been enabled in the SDK application.
// If the user has failed to either "#define INCLUDE_MEMORY"
// in the appconfig.h file or include a dynamic memory
// partition list in the linker.cmd file, he will now get
// a link error. */
extern UInt16 memNumEMpartitions;
bSatMode = (bool) memNumEMpartitions;
assert (bMemInitialized);
assert ((((UWord16)pBlock) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
/* If pData is NULL, return, per ANSI C. */
if (pData == NULL)
return;
bSatMode = archGetSetSaturationMode(false);
pBlock -= 1;
if (pBlock -> Size > 0) {
assert(!"Attempt to free memory never allocated or previously freed");
}
/* Make the block available. */
/* Ensure that Remainder is double-word aligned */
assert ((pBlock->Size & 0x0003) == 0);
pBlock -> Size = -(pBlock -> Size);
archGetSetSaturationMode (bSatMode);
}
#pragma warn_unusedarg reset
/*******************************************************
*
* Method: memMallocWrapper
*
*******************************************************/
#pragma warn_unusedarg off
extern void * memMallocWrapper(mem_sPool * pPool, size_t Size,
const char *pFile, int Line)
{
void * pData;
/* Call the base allocator. We use the parenthesis to prevent the
// preprocessor from substituting memMalloc with memMallocWrapper,
// causing endless recursion into this routine. */
pData = (memMalloc)(pPool, Size);
if (pData == NULL)
return (void *) NULL;
return pData;
}
#pragma warn_unusedarg reset
/*******************************************************
*
* memMalloc
* If the size requested is 0, return NULL, per ANSI C.
*
* LABEL:
* WHILE we haven't yet allocated a block DO
* Skip blocks in use.
*
* IF we hit the tail block of the pool THEN
* IF we have already wrapped through the pool once THEN
* return NULL to indicate failure to allocate.
* ELSE
* Reset the block pointer to the first block of the pool.
* Indicate that we have wrapped around.
* Continue from LABEL.
* ENDIF
*
* Merge all contiguous free blocks from the current block to the
* first in-use block or the end of the pool.
* IF the consolidated block satisfies the request THEN
* Split the block, if it is large enough and return the first block
* of the split.
* ENDIF
*
* Bump the block search pointer to the next block
* ENDWHILE
*
*******************************************************/
void * (memMalloc)(mem_sPool * pMemPool, size_t Size)
{
bool bSatMode;
Int32 SizeNeeded = (Int32) Size;
Int32 BlockSize;
int Wrapped;
sBlockHead * pBlock;
void * pMemory = (void *) NULL;
sPool * pPool = (sPool *) pMemPool;
/* The following two lines are a check to ensure that
// dynamic memory has been enabled in the SDK application.
// If the user has failed to either "#define INCLUDE_MEMORY"
// in the appconfig.h file or include a dynamic memory
// partition list in the linker.cmd file, he will now get
// a link error. */
extern UInt16 memNumEMpartitions;
BlockSize = memNumEMpartitions;
if(bMemInitialized == false) {
Initialize();
}
if (SizeNeeded == 0) return (void *) NULL;
bSatMode = archGetSetSaturationMode(false);
#ifdef ADDRESSING_8
/* Allocate in 4 8-bit units only. */
SizeNeeded = ((SizeNeeded + 3) & ~3);
#endif
SizeNeeded += sizeof(sBlockHead);
assert ((SizeNeeded & 0x0003) == 0); /* Ensure that SizeNeeded is double-word aligned */
pBlock = pPool -> pCurrent;
assert ((((UWord16)pBlock) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
Wrapped = false;
while (true) {
/* Skip blocks in use. */
while (true) {
BlockSize = pBlock -> Size;
if (BlockSize >= 0) break;
/* Typecasting required to force 32 bit operation and preserve negative BlockSize */
pBlock = (sBlockHead *) (((UInt32)((char *)pBlock) - BlockSize)/2);
assert ((((UWord16)pBlock) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
}
/* Found a block that is not in use. If it's the last block of the pool,
// wrap to the beginning. If we reach the end after wrapping, then we're
// out of memory. */
if (BlockSize == 0) {
if (Wrapped) break;
pBlock = pPool -> pFirst;
assert ((((UWord16)pBlock) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
Wrapped = true;
continue;
}
/* We're now at a block that is not in use. We optimize for
// the hopeful case, where the current blocksize is big
// enough and we don't have to make a costly call to merge
// free blocks. If the block is big enough, we split it
// and leave the loop. */
if (BlockSize >= SizeNeeded) {
pMemory = SplitBlock(pPool, pBlock, SizeNeeded);
break;
}
/* Merge free blocks that immediately follow this one in an
// attempt to make the current block big enough. */
BlockSize = MergeFree(pPool, pBlock, SizeNeeded);
/* If the (now merged) free block is big enough, we split it in two
// if the remainder is big enough to make it worthwhile.
//
// If the block still isn't big enough, at least we made a bigger
// free block that will make for faster allocations later. */
if (BlockSize >= SizeNeeded) {
pMemory = SplitBlock(pPool, pBlock, SizeNeeded);
break;
}
/* Move to the next candidate block and loop back up to try again */
pBlock = (sBlockHead *) ((char *) pBlock + BlockSize);
assert ((((UWord16)pBlock) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -