📄 heapman.c
字号:
/**************************************************************************
* Function Name : HeapRemoveBlockToFreeList
* Inputs : psHostHeap - ptr to host heap this block belongs to
* psBlock - block to be removed to free list
* Outputs : None
* Returns : None
* Globals Used : None
* Description : Remove the block from the free list
**************************************************************************/
__inline IMG_VOID HeapRemoveBlockToFreeList(HOST_HEAP *psHostHeap, PGLOB_HEAP psBlock)
{
/* Remove block from free list */
if (psBlock->psNextFree != NULL)
{
psBlock->psNextFree->psPrevFree=psBlock->psPrevFree;
}
if (psBlock->psPrevFree != NULL)
{
psBlock->psPrevFree->psNextFree=psBlock->psNextFree;
}
else
{
psHostHeap->psFreeHeapStart=psBlock->psNextFree;
}
psBlock->psNextFree=(PGLOB_HEAP)NULL;
psBlock->psPrevFree=(PGLOB_HEAP)NULL;
}
/**************************************************************************
* Function Name : AddBlockAllocCallback
* Inputs : pfnFunc - ptr to callback function
* Outputs : None
* Returns : TRUE if installed ok, else FALSE
* Globals Used : None
* Description : Installs host heap block alloc callback
**************************************************************************/
IMG_BOOL AddBlockAllocCallback(PFN_HEAPBLOCK_CALLBACK pfnFunc)
{
IMG_UINT32 ui32Idx;
for (ui32Idx=0; ui32Idx<MAX_ALLOC_CALLBACKS; ui32Idx++)
{
/* Only allow one instance of a callback routine */
if (sfnBlockAllocCallbacks[ui32Idx] == pfnFunc)
{
return FALSE;
}
/* Check if free */
if (sfnBlockAllocCallbacks[ui32Idx] == NULL)
{
sfnBlockAllocCallbacks[ui32Idx]=pfnFunc;
return TRUE;
}
}
return FALSE;
}
/**************************************************************************
* Function Name : RemoveBlockAllocCallback
* Inputs : pfnFunc - ptr to callback function
* Outputs : None
* Returns : TRUE if installed ok, else FALSE
* Globals Used : None
* Description : Removes host heap block alloc callback
**************************************************************************/
IMG_VOID RemoveBlockAllocCallback(PFN_HEAPBLOCK_CALLBACK pfnFunc)
{
IMG_UINT32 ui32Idx;
for (ui32Idx=0; ui32Idx<MAX_ALLOC_CALLBACKS; ui32Idx++)
{
if (sfnBlockAllocCallbacks[ui32Idx] == pfnFunc)
{
sfnBlockAllocCallbacks[ui32Idx]=(PFN_HEAPBLOCK_CALLBACK)NULL;
return;
}
}
return;
}
/**************************************************************************
* Function Name : DoBlockCallbacksForHeap
* Inputs : psHeap - heap to process
* Outputs : None
* Returns : None
* Globals Used : None
* Description : Walks the heap and processes the host heap block callbacks
* for each block
**************************************************************************/
IMG_VOID DoBlockCallbacksForHeap(PHOST_HEAP psHeap)
{
PGLOB_HEAP psCurHeapBlock;
PGLOB_HEAP psStartHeapBlock;
IMG_UINT32 ui32AccumBlockSize=0;
#ifdef DEBUG
CheckSingleHeap(psHeap, FALSE);
#endif
/*Start at begining of the heap*/
psCurHeapBlock = psHeap->psHeapStart;
psStartHeapBlock = psCurHeapBlock;
/* Check each block */
while (psCurHeapBlock != NULL)
{
/*Add size of this block to running total*/
ui32AccumBlockSize+=psCurHeapBlock->ui32BlockSize;
/*
If this is end of this continuous linear address region of blocks
then process the callbacks for it!!!
*/
if (psCurHeapBlock->psNext == NULL || (psCurHeapBlock->psNext->ui32Flags & GHEAP_BLOCK_HEAD) == GHEAP_BLOCK_HEAD)
{
ProcessAllocCallbacks(TRUE, psStartHeapBlock, ui32AccumBlockSize);
ui32AccumBlockSize=0;
psStartHeapBlock = psCurHeapBlock->psNext;
}
/*Move to next block*/
psCurHeapBlock = psCurHeapBlock->psNext;
}
return;
}
/**************************************************************************
* Function Name : DoBlockCallbacksForHeap
* Inputs : psHeap - heap to process
* Outputs : None
* Returns : None
* Globals Used : None
* Description : Walks the heap and processes the host heap block callbacks
* for each block
**************************************************************************/
IMG_VOID ProcessAllocCallbacks(IMG_BOOL bAlloc, IMG_PVOID pvAddr, IMG_UINT32 ui32Size)
{
IMG_UINT32 ui32Idx;
for (ui32Idx=0; ui32Idx<MAX_ALLOC_CALLBACKS; ui32Idx++)
{
if (sfnBlockAllocCallbacks[ui32Idx] != NULL)
{
////don't need ExitKM((PPVRSRV_DEV_INFO)NULL);
(sfnBlockAllocCallbacks[ui32Idx])(bAlloc, pvAddr, ui32Size);
////don't need EnterKM((PPVRSRV_DEV_INFO)NULL);
}
}
return;
}
/**************************************************************************
* Function Name : CheckHeapFreeBlock
* Inputs : pvStart - pointer to start of free block of memory to check
* ui32Size - size of block in bytes
* Outputs : None
* Returns : Zero if memory has not been corrupted else the addr of the
* memory that has been corrupted.
* Globals Used : None
* Description : Check the given free block of memory has been corrupted
* This is done by checking that evey byte of the buffer is
* 0xe2
**************************************************************************/
IMG_UINT32 CheckHeapFreeBlock(IMG_PVOID pvStart, IMG_UINT32 ui32Size)
{
IMG_UINT32 ui32Ret;
IMG_UINT32 ui32DWORDCo=ui32Size/4;
IMG_UINT32 ui32Count;
IMG_UINT32 *pui32Temp;
if (ui32Size == 0)
{
return 0;
}
pui32Temp = (IMG_UINT32 *)pvStart;
for (ui32Count = 0; ui32Count < ui32DWORDCo; ui32Count++)
{
if ( pui32Temp[ui32Count] != (DBG_MEMORY_DEALLOC_INITIALIZER + (DBG_MEMORY_DEALLOC_INITIALIZER << 8) + (DBG_MEMORY_DEALLOC_INITIALIZER << 16) + (DBG_MEMORY_DEALLOC_INITIALIZER << 24)) )
{
ui32Ret = ((IMG_UINT32)pvStart) + ui32Count;
break;
}
}
return ui32Ret;
}
#define READ_GLOB_HEAP(addr, ptr, strct) ptr=(PGLOB_HEAP)addr;
#define READ_HOST_HEAP(addr, ptr, strct) ptr=(PHOST_HEAP)addr;
#define READ_DWORD(addr, var) var=*(PDWORD)addr;
/**************************************************************************
* Function Name : FindBlockAllocSize
* Inputs : psBlock - ptr to block
* Outputs : None
* Returns : Num bytes alloced by caller
* Globals Used : None
* Description :
**************************************************************************/
IMG_UINT32 FindBlockAllocSize(PGLOB_HEAP psBlock)
{
PDWORD pui32Ptr;
IMG_UINT32 ui32Val;
PDWORD pui32EndOfBlock;
IMG_UINT32 ui32BlockSize;
READ_DWORD(&psBlock->ui32BlockSize, ui32BlockSize);
pui32EndOfBlock=(PDWORD)((IMG_UINT32)psBlock + ui32BlockSize);
/* Start at end of header */
pui32Ptr=(PDWORD)(psBlock+1);
/* Check for the link ptr */
while (pui32Ptr < pui32EndOfBlock)
{
READ_DWORD(pui32Ptr, ui32Val);
if (ui32Val == (IMG_UINT32)psBlock)
{
return ui32BlockSize - ((IMG_UINT32)pui32Ptr - (IMG_UINT32)psBlock) - 4;
}
pui32Ptr++;
}
return 0;
}
/**************************************************************************
* Function Name : CheckSingleHeap
* Inputs : psHeap - pointer to heap to test
* Outputs : None
* Returns : None
* Globals Used : sGlbDbgAllocs
* Description : Walks through given heap checking for corruptions
**************************************************************************/
IMG_VOID CheckSingleHeap(HOST_HEAP *psHeap, IMG_BOOL bPrintHeap)
{
PGLOB_HEAP psCurHeapBlock;
IMG_PVOID pvCurHeapBlock;
GLOB_HEAP sCurHeapBlock={0};
IMG_PVOID pvPrevHeapBlock=NULL;
PGLOB_HEAP psNextHeapBlock=(PGLOB_HEAP)NULL;
GLOB_HEAP sNextHeapBlock={0};
IMG_UINT32 ui32AccumBlockSize=0;
IMG_UINT32 ui32TotalBlocks=0;
IMG_UINT32 ui32FreeBlocks=0;
IMG_UINT32 ui32FreeHeapBlkCo=0;
HOST_HEAP sHeap={0};
IMG_PVOID pvHeap=psHeap;
if (ui32HeapCheckLevel == HOST_HEAP_DBGCHK_NONE && bPrintHeap == FALSE)
{
return;
}
/* Read heap structure */
READ_HOST_HEAP(psHeap, psHeap, sHeap);
if (bPrintHeap)
{
PVR_DPF((PVR_DBG_MESSAGE, "ChkHostHeap : Heap 0x%lx", pvHeap));
DPF_NEWLINE;
PVR_DPF((PVR_DBG_MESSAGE, "ChkHostHeap : Total allocs in heap %ld", psHeap->ui32AllocsInHeap));
DPF_NEWLINE;
PVR_DPF((PVR_DBG_MESSAGE, "ChkHostHeap : Total pages in heap %ld", psHeap->ui32CurHeapSizeInPages));
DPF_NEWLINE;
PVR_DPF((PVR_DBG_MESSAGE, "ChkHostHeap : Heap page alloc fn 0x%lx", psHeap->pfnHostAllocPage));
DPF_NEWLINE;
PVR_DPF((PVR_DBG_MESSAGE, "ChkHostHeap : Heap page free fn 0x%lx\n\n", psHeap->pfnHostFreePage));
DPF_NEWLINE;
}
/*Start at begining of the heap*/
pvCurHeapBlock = psHeap->psHeapStart;
READ_GLOB_HEAP(pvCurHeapBlock, psCurHeapBlock, sCurHeapBlock);
/*Check each block*/
while( pvCurHeapBlock != NULL )
{
/*Add size of this block to running total*/
ui32AccumBlockSize+=psCurHeapBlock->ui32BlockSize;
ui32TotalBlocks++;
/*Check signiture*/
PVR_ASSERT(psCurHeapBlock->ui32Signiture == HOST_HEAP_SIGNITURE);
/*Check flags*/
PVR_ASSERT((psCurHeapBlock->ui32Flags & ~(GHEAP_BLOCK_ALLOCATED | GHEAP_BLOCK_HEAD)) == 0);
/* Check block points to last block */
PVR_ASSERT(psCurHeapBlock->psPrev == (PGLOB_HEAP)pvPrevHeapBlock);
/* Check blocks points back to the heap */
PVR_ASSERT(psCurHeapBlock->psHeap == pvHeap);
if (psCurHeapBlock->ui32Flags & GHEAP_BLOCK_ALLOCATED)
{
PVR_ASSERT(psCurHeapBlock->psPrevFree == NULL);
PVR_ASSERT(psCurHeapBlock->psNextFree == NULL);
}
else
{
ui32FreeBlocks++;
}
/*If next block is in same allocation then check the block size*/
if (psCurHeapBlock->psNext != NULL)
{
READ_GLOB_HEAP(psCurHeapBlock->psNext, psNextHeapBlock, sNextHeapBlock);
if ((psNextHeapBlock->ui32Flags & GHEAP_BLOCK_HEAD) != GHEAP_BLOCK_HEAD)
{
PVR_ASSERT(psCurHeapBlock->psNext == (PGLOB_HEAP)((BYTE *)pvCurHeapBlock + psCurHeapBlock->ui32BlockSize));
}
}
/*If this is end of this continuous linear address region of blocks
then check there combined size*/
if (psCurHeapBlock->psNext == NULL || (psNextHeapBlock->ui32Flags & GHEAP_BLOCK_HEAD) == GHEAP_BLOCK_HEAD)
{
PVR_ASSERT(ui32AccumBlockSize == (psHeap->ui32ExpandSizeInPages * HOST_PAGESIZE()));
ui32AccumBlockSize=0;
}
if (bPrintHeap)
{
if ((psCurHeapBlock->ui32Flags & GHEAP_BLOCK_HEAD) == GHEAP_BLOCK_HEAD)
{
PVR_DPF((PVR_DBG_MESSAGE, "ChkHostHeap : New Block"));
DPF_NEWLINE;
}
if (psCurHeapBlock->ui32Flags & GHEAP_BLOCK_ALLOCATED)
{
IMG_UINT32 ui32AllocSize=FindBlockAllocSize((PGLOB_HEAP)pvCurHeapBlock);
#ifdef DEBUG
PVR_DPF((PVR_DBG_MESSAGE, "0x%lx - 0x%lx : Alloced 0x%lx (0x%lx) (%ldKb) Owner 0x%lx", pvCurHeapBlock, (IMG_UINT32)pvCurHeapBlock + psCurHeapBlock->ui32BlockSize, ui32AllocSize, psCurHeapBlock->ui32BlockSize, ui32AllocSize/1024, psCurHeapBlock->pfnOwner));
#else
PVR_DPF((PVR_DBG_MESSAGE, "0x%lx - 0x%lx : Alloced 0x%lx (0x%lx) (%ldKb)", pvCurHeapBlock, (IMG_UINT32)pvCurHeapBlock + psCurHeapBlock->ui32BlockSize, ui32AllocSize, psCurHeapBlock->ui32BlockSize, ui32AllocSize/1024));
#endif
DPF_NEWLINE;
}
else
{
PVR_DPF((PVR_DBG_MESSAGE, "0x%lx - 0x%lx : Free 0x%lx (%ldKb)", pvCurHeapBlock, (IMG_UINT32)pvCurHeapBlock + psCurHeapBlock->ui32BlockSize, psCurHeapBlock->ui32BlockSize, psCurHeapBlock->ui32BlockSize/1024));
DPF_NEWLINE;
}
}
/*Move to next block*/
pvPrevHeapBlock=pvCurHeapBlock;
pvCurHeapBlock = psCurHeapBlock->psNext;
READ_GLOB_HEAP(pvCurHeapBlock, psCurHeapBlock, sCurHeapBlock);
}
PVR_ASSERT(psHeap->ui32AllocsInHeap == ui32TotalBlocks - ui32FreeBlocks);
if (bPrintHeap)
{
PVR_DPF((PVR_DBG_MESSAGE, "Total num blocks %ld", ui32TotalBlocks));
DPF_NEWLINE;
PVR_DPF((PVR_DBG_MESSAGE, "Total num alloced blocks %ld", psHeap->ui32AllocsInHeap));
DPF_NEWLINE;
PVR_DPF((PVR_DBG_MESSAGE, "Total num free blocks %ld", ui32FreeBlocks));
DPF_NEWLINE;
}
/* Now check the free list */
pvCurHeapBlock = psHeap->psFreeHeapStart;
READ_GLOB_HEAP(pvCurHeapBlock, psCurHeapBlock, sCurHeapBlock);
pvPrevHeapBlock=(PGLOB_HEAP)NULL;
if (ui32HeapCheckLevel >= HOST_HEAP_DBGCHK_FREEHEAP)
{
while(pvCurHeapBlock != NULL)
{
IMG_UINT32 ui32Addr=0;
/* Count number of blocks */
ui32FreeHeapBlkCo++;
/* Check block points to last block */
PVR_ASSERT(psCurHeapBlock->psPrevFree == pvPrevHeapBlock);
if (ui32HeapCheckLevel >= HOST_HEAP_DBGCHK_CORRUPTION)
{
/* Check free space has not been corrupted */
#if defined(DEBUG)
if ((psCurHeapBlock->ui32Flags & GHEAP_BLOCK_HEAD) == 0)
{
PVR_ASSERT((ui32Addr=CheckHeapFreeBlock((IMG_PVOID)(psCurHeapBlock+1), psCurHeapBlock->ui32BlockSize-sizeof(GLOB_HEAP))) == 0);
}
else
{
PVR_ASSERT((ui32Addr=CheckHeapFreeBlock((IMG_PVOID)(((PGLOB_HEAP_HEAD)psCurHeapBlock)+1), psCurHeapBlock->ui32BlockSize-sizeof(GLOB_HEAP_HEAD))) == 0);
}
#endif
}
/*Move to next block*/
pvPrevHeapBlock=pvCurHeapBlock;
pvCurHeapBlock = psCurHeapBlock->psNextFree;
READ_GLOB_HEAP(pvCurHeapBlock, psCurHeapBlock, sCurHeapBlock);
}
PVR_ASSERT(ui32FreeHeapBlkCo == ui32FreeBlocks);
}
/* Call the heap specific checking function if given */
if (psHeap->pfnDedicatedHeapCheck != NULL)
{
psHeap->pfnDedicatedHeapCheck(psHeap);
}
return;
}
/*****************************************************************************
End of file (heapman.c)
*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -