?? mem.c
字號(hào):
* cannot allocate an aligned buffer from
* either partition, it calls memMallocEM
* to try to allocate a buffer of the correct
* size without the proper alignment.
*
* Arguments:
* size - the new size of the memory buffer to be
* allocated in internal memory
*
* Return: If memory is insufficient to satisfy the request
* from either partition, memMallocAlignedIM returns NULL
*
*******************************************************/
void * memMallocAlignedEM (size_t size)
{
void * pMem;
pMem = memMallocAligned (&ExternalMemoryPool, size);
if (pMem == NULL) {
pMem = memMallocAligned (&InternalMemoryPool, size);
if (pMem == NULL) {
pMem = memMallocEM (size);
}
}
return pMem;
}
/*******************************************************
*
* Method: memFreeEM
*
* Description: This function deallocates a memory block
* in external memory that previously had
* been dynamically allocated with
* the routine memMallocEM.
*
* Arguments:
* memblock - pointer to previously allocated memory
*
* Return: None
*
*******************************************************/
void memFreeEM (void * memblock)
{
if (memIsEM(memblock)) {
memFree (&ExternalMemoryPool, memblock);
}
else {
memFree (&InternalMemoryPool, memblock);
}
}
/*******************************************************
*
* Method: memIsAligned
*
* Description: This function checks the address of
* a memory block to determine whether
* it is properly aligned to use modulo
* addressing.
*
* Arguments:
* memblock - the address of the memory block
* to check alignment for modulo addressing
* size - the size to which the block should
* be aligned for modulo addressing
*
* Return: The function memIsAligned returns true
* if the address is aligned so that modulo
* addressing can be used; otherwise, it
* returns false.
*
*******************************************************/
bool memIsAligned (void * memblock, size_t size)
{
UInt16 Modulo; /* Modulo of the defined memory size */
UInt16 ModuloMask; /* Bits mask of the modulo size */
Modulo = 1; /* Set minimal modulo */
while(size > Modulo){
Modulo=Modulo << 1; /* Set modulo to a double modulo (2,4,8,16, ...) */
}
ModuloMask = Modulo - 1; /* Set bits mask of the modulo */
return (((UInt16)memblock & ModuloMask) == 0); /* TRUE - memblock mod Modulo = 0 */
/* FALSE - memblock mod Modulo > 0 */
}
/*******************************************************
* Mem
*
* Description:
* General-purpose ANSI C-compliant memory pool manager.
*
* Author:
* Mark Glenn
*
* Design:
* These routines manage a memory buffer that you specify, internally
* called the pool. Blocks of memory are allocated from and returned
* to this pool.
*
* The first UInt32 of every block is the size of the block
* in bytes, inclusive. This value is positive if the block is free,
* negative if the block is in use, and zero if this is the last block
* of the pool.
*******************************************************/
/* The header for each memory block in a pool. */
#pragma warn_padding off
typedef struct {
/* The size of the block. This includes the size of this sBlockHead. */
Int32 Size;
} sBlockHead;
/* sPool -- Holds the state of a memory pool. */
typedef struct {
/* Points to the first block of the pool. */
sBlockHead * pFirst;
/* Points to the last block of the pool. */
sBlockHead * pLast;
/* Points to a block within the pool. It is used
// to remain "close" to memory most likely to be free. We could just
// start from the beginning of the pool each time, but then we would
// very likely have to skip over many in-use blocks, especially as
// memory is allocated from a fresh pool. We wrap to pFirst if
// there isn't enough memory between pCurrent and the end of the pool,
// to satisfy the request. */
sBlockHead * pCurrent;
/* If set, aborts the program when the memory pool is
// exhausted. Otherwise, behave as ANSI requires. */
bool Assert;
/* True if we are to mutex-protect the pool. */
bool Protect;
} sPool;
#pragma warn_padding reset
/*******************************************************
*
* Method: memProtect
*
* Description: This function set memory protection.
*
* Arguments:
* pMemPool - pointer to the memory pool
*
* Return: None
*
*******************************************************/
extern void memProtect(mem_sPool * pMemPool)
{
sPool * pPool=(sPool *)pMemPool;
pPool -> Protect=true;
}
/*******************************************************
*
* Method: memCleanUp
*
* Description: This function cleans memory.
* Starting from the beginning of the pool,
* merge blocks that are not in use.
* Stop at the first in-use block.
*
* Arguments:
* pMemPool - pointer to the memory pool
*
* Return: Size of the free memory
*
*******************************************************/
extern size_t memCleanUp(mem_sPool * pMemPool)
{
bool bSatMode;
sPool * pPool = (sPool *) pMemPool;
sBlockHead * pBlock = pPool -> pFirst;
sBlockHead * pFirstBlock = pBlock;
Int32 TotalSize = 0;
Int32 Size;
bSatMode = archGetSetSaturationMode(false);
pPool -> pCurrent = pBlock;
while (Size = pBlock -> Size, Size != 0) {
if (Size < 0) break;
TotalSize += Size;
pBlock = (sBlockHead *) (((char *) pBlock) + Size);
}
pFirstBlock -> Size = TotalSize;
archGetSetSaturationMode(bSatMode);
return (size_t)TotalSize;
}
/*******************************************************
*
* Method: MergeFree
*
* Description: This function assumes that pBlock points to a block not in-use.
* Checks the block following to determine its state. If it is not in-use,
* merge it to the current block. pBlock will not change, but the
* size of the block to which it points may increase.
*
* Arguments:
* pPool - pointer to the memory pool
* pBlock - pointer to the memory pool
* SizeNeeded - size of the memory block
*
* Return: None
*
*******************************************************/
static Int32 MergeFree(sPool* pPool, sBlockHead * pBlock, Int32 SizeNeeded)
{
bool bSatMode;
Int32 CurrentSize = pBlock -> Size;
bSatMode = archGetSetSaturationMode(false);
assert ((((UWord16)pBlock) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
while (true) {
sBlockHead * pNext;
Int32 NextSize;
/* Get a pointer to the next block and retrieve it's size. */
pNext = ((sBlockHead *)(((char *) pBlock) + CurrentSize));
assert ((((UWord16)pNext) & 0x0001) == 0); /* Ensure that pNext is double-word aligned */
NextSize = pNext -> Size;
assert ((NextSize & 0x0003) == 0); /* Ensure that NextSize is double-word aligned */
/* If the next block is in use or is the last block (Size == 0), return. */
if (NextSize <= 0) {
assert ((CurrentSize & 0x0003) == 0); /* Ensure that NextSize is double-word aligned */
pBlock -> Size = CurrentSize;
archGetSetSaturationMode (bSatMode);
return CurrentSize;
}
/* Increment the known size of the current block. We won't store it
// until we are about to leave the routine. */
CurrentSize += NextSize;
/* If pCurrent happens to point to the block that we are about
// to combine, reset it to point to the beginning of the merged block. */
if (pNext == pPool -> pCurrent)
pPool -> pCurrent = pBlock;
/* Optimized to get out as soon as we know we can satisfy the request. */
if (CurrentSize >= SizeNeeded) {
assert ((CurrentSize & 0x0003) == 0); /* Ensure that NextSize is double-word aligned */
pBlock -> Size = CurrentSize;
archGetSetSaturationMode (bSatMode);
return CurrentSize;
}
}
}
/*******************************************************
*
* Method: SplitBlock
*
* Description: Assumes that pBlock points to a block larger than SizeNeeded.
* If the block is large enough to contain SizeNeeded plus another block,
* the block is split. The area returned to the user is the user
* portion of the first block. The remainder in its entirety will
* be set to describe a not-in-use block.
*
* Arguments:
* pPool - pointer to the memory pool
* pBlock - pointer to the memory pool
* SizeNeeded - size of the memory block
*
* Return: None
*
*******************************************************/
#pragma warn_unusedarg off
static void * SplitBlock(sPool * pPool, sBlockHead * pBlock, Int32 SizeNeeded)
{
bool bSatMode;
Int32 Remainder;
sBlockHead * pUser = pBlock + 1;
Int32 BlockSize = pBlock -> Size;
bSatMode = archGetSetSaturationMode(false);
assert ((((UWord16)pBlock) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
#ifdef ADDRESSING_8
/* Allocate in 4 8-bit units only. */
SizeNeeded = (SizeNeeded + 3) & ~3;
#endif
if ((Remainder = BlockSize - SizeNeeded) > sizeof(sBlockHead)) {
assert ((Remainder & 0x0003) == 0); /* Ensure that Remainder is double-word aligned */
assert ((SizeNeeded & 0x0003) == 0); /* Ensure that Remainder is double-word aligned */
/* Set the size of the first part of the split. */
pBlock -> Size = -SizeNeeded;
/* Point to the next block of the split. */
pBlock = (sBlockHead *) ((char *) pBlock + SizeNeeded);
assert ((((UWord16)pBlock) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
pBlock -> Size = Remainder;
}
else {
/* Don't split block. */
pBlock -> Size = -BlockSize;
pBlock = (sBlockHead *) ((char *) pBlock + BlockSize);
assert ((((UWord16)pBlock) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
}
/* Store a pointer to a likely candidate block. */
pPool -> pCurrent = pBlock;
archGetSetSaturationMode(bSatMode);
return pUser;
}
#pragma warn_unusedarg reset
/*******************************************************
*
* Method: SplitBlockRev
*
* Description: Assumes that pBlock points to a block larger than SizeNeeded.
* If the block is large enough to contain SizeNeeded plus another block,
* the block is split. The area returned is the
* portion of the end of the block. The remainder in its entirety will
* be set to describe a not-in-use block.
*
* Arguments:
* pPool - pointer to the memory pool
* pBlock - pointer to the memory pool
* SizeNeeded - size of the memory block
*
* Return: None
*
*******************************************************/
#pragma warn_unusedarg off
static void * SplitBlockRev(sPool * pPool, sBlockHead * pBlock, UInt32 SizeNeeded)
{
bool bSatMode;
sBlockHead * pUser;
Int32 BlockSize = pBlock -> Size;
bSatMode = archGetSetSaturationMode(false);
assert ((((UWord16)pBlock) & 0x0001) == 0); /* Ensure that pBlock is double-word aligned */
#ifdef ADDRESSING_8
/* Allocate in 4 8-bit units only. */
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -