📄 cphysmem.cpp
字号:
//
// Validate the NODES free list.
//
pNode = FirstNode(m_pNodeFreeListHead);
while (!EndOfList(m_pNodeFreeListHead, pNode)) {
dwNodesFree++;
// these are set in DeleteNode
DEBUGCHK( pNode->dwSize == 0xdeadbeef &&
pNode->dwPhysAddr == 0xdeadbeef &&
pNode->dwVirtAddr == 0xdeadbeef );
if ((pNode->next->prev != pNode) || (pNode->prev->next != pNode)) {
DEBUGMSG(ZONE_ERROR, (TEXT("CPhysMem ValidateHeaps : Invalid linked list (nodefree)\r\n")));
DEBUGCHK(0);
return(FALSE);
}
pNode = pNode->next;
}
DEBUGMSG(ZONE_CPHYSMEM && ZONE_VERBOSE, (TEXT("CPhysMem ValidateHeaps : Nodes Free = %d\r\n"),dwNodesFree));
return (TRUE);
}
#endif
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PMEMLIST
CPhysMem::CreateNewNode(
DWORD dwSize,
DWORD dwVirtAddr,
DWORD dwPhysAddr
)
{
#ifdef DEBUG
if ( dwSize == 0 ) {
DEBUGCHK( dwVirtAddr == 0 &&
dwPhysAddr == 0 );
} else {
DEBUGCHK( dwSize % CPHYSMEM_MEMORY_ALIGNMENT == 0 &&
dwPhysAddr % CPHYSMEM_MEMORY_ALIGNMENT == 0 &&
PUCHAR(dwVirtAddr) == PaToVa( dwPhysAddr ) );
}
#endif // DEBUG
PMEMLIST pNode;
//
// If we already have a node allocated and sitting around, use it.
//
if ((dwSize == 0) || IsListEmpty(m_pNodeFreeListHead)) {
pNode = (PMEMLIST) CPhysMem_Alloc(LPTR, sizeof(MEMLIST));
} else {
pNode = FirstNode(m_pNodeFreeListHead);
RemoveNode(pNode);
}
if (pNode != NULL) {
pNode->dwVirtAddr = dwVirtAddr;
pNode->dwPhysAddr = dwPhysAddr;
pNode->dwSize = dwSize;
pNode->next = NULL;
pNode->prev = NULL;
#ifdef DEBUG
_tcscpy( pNode->szDescription, TEXT("Default Desc") );
#endif // DEBUG
}
return (pNode);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
CPhysMem::DeleteNode(
PMEMLIST pNode
)
{
//
// We don't actually delete any of the nodes. We just keep them on our
// free list to use later. Keeps us from thrashing on the heap.
//
#ifdef DEBUG
pNode->dwSize = 0xdeadbeef;
pNode->dwPhysAddr = 0xdeadbeef;
pNode->dwVirtAddr = 0xdeadbeef;
_tcscpy( pNode->szDescription, TEXT("Deleted Node") );
#endif // DEBUG
InsertNodeBefore(pNode, FirstNode(m_pNodeFreeListHead));
return(TRUE);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PMEMLIST
CPhysMem::FindFreeBlock(
DWORD dwSize,
BOOL fHighPri
)
{
DEBUGCHK( dwSize >= CPHYSMEM_MEMORY_ALIGNMENT &&
dwSize % CPHYSMEM_MEMORY_ALIGNMENT == 0 );
//
// The free list is sorted by increasing block sizes, so just find the
// first block that's at least "dwSize" big.
//
PMEMLIST pNode = FirstNode(FREELIST(fHighPri));
while (!EndOfList(FREELIST(fHighPri), pNode)) {
if (dwSize <= pNode->dwSize) {
RemoveNode(pNode);
return (pNode);
}
pNode = pNode->next;
}
return (NULL);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
CPhysMem::AddNodeToFreeList(
PMEMLIST pNode,
BOOL fHighPri
)
{
//
// The free list is sorted by increasing block sizes, not by increasing
// address so we must scan the list for any possible connecting free blocks,
// and then coalesce them into a single free block. There will be at most
// two blocks to find (one on either end) so scan for both of them.
//
PMEMLIST pNodeTraverse = FirstNode(FREELIST(fHighPri));
PMEMLIST pNodePrevious = NULL; // Points to the previous connecting free block
PMEMLIST pNodeNext = NULL; // Points to the next connecting free block
//
// The endpoints that we are trying to match up to.
//
DWORD dwThisPA = pNode->dwPhysAddr;
DWORD dwNextPA = MEMLIST_NEXT_PA(pNode);
//
// Walk the list looking for blocks that are next to this one.
//
while (!EndOfList(FREELIST(fHighPri), pNodeTraverse)) {
if (dwThisPA == MEMLIST_NEXT_PA(pNodeTraverse)) {
//
// We've found the block just ahead of this one. Remember it.
//
pNodePrevious = pNodeTraverse;
} else if (dwNextPA == pNodeTraverse->dwPhysAddr) {
//
// We've found the block just after of this one.
//
pNodeNext = pNodeTraverse;
}
if ((pNodePrevious == NULL) || (pNodeNext == NULL)) {
//
// We haven't connected both ends, so keep on looking...
//
pNodeTraverse = pNodeTraverse->next;
} else {
//
// We've found blocks to connect on both ends, let's get on with it.
//
break;
}
}
if (pNodePrevious != NULL) {
//
// Combine with the previous block.
//
RemoveNode(pNodePrevious);
//
// Grow pNode to hold both.
//
pNode->dwSize = pNode->dwSize + pNodePrevious->dwSize;
pNode->dwVirtAddr = pNodePrevious->dwVirtAddr;
pNode->dwPhysAddr = pNodePrevious->dwPhysAddr;
DeleteNode(pNodePrevious);
}
if (pNodeNext != NULL) {
//
// Combine with the next block.
//
RemoveNode(pNodeNext);
//
// Grow pNode to hold both.
//
pNode->dwSize = pNode->dwSize + pNodeNext->dwSize;
#ifdef DEBUG
// take description of the largest block
_tcscpy( pNode->szDescription, pNodeNext->szDescription );
#endif // DEBUG
DeleteNode(pNodeNext);
}
//
// Add pNode to the free list in sorted size order.
//
pNodeTraverse = FirstNode(FREELIST(fHighPri));
while (!EndOfList(FREELIST(fHighPri), pNodeTraverse)) {
if (pNode->dwSize <= pNodeTraverse->dwSize) {
break;
}
pNodeTraverse = pNodeTraverse->next;
}
//
// Insert this node before the traverse node.
//
InsertNodeBefore(pNode, pNodeTraverse);
return TRUE;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CPhysMem::~CPhysMem()
{
DeleteCriticalSection(&m_csLock);
CloseHandle(m_hFreeMemEvent);
FreeList(&m_pInUseListHead);
FreeList(&m_pFreeListHead);
FreeList(&m_pHighPriorityInUseListHead);
FreeList(&m_pHighPriorityFreeListHead);
FreeList(&m_pNodeFreeListHead);
if( m_pPhysicalBufferAddr )
{
#ifdef OSV_LOCAL_MERLIN
// This is a merlin build, but merlin doesn't have AllocPhysMem or FreePhysMem
// implemented. This shouldn't be a problem since this routine is normally
// called with non-null values in pVirtAddr & pPhysAddr. But, just to be sure,
// print a message and assert if this part of the code is executed.
RETAILMSG(1,(TEXT("CPhysMem::CPhysMem: FreePhysMem not implemented on Merlin.\r\n")));
ASSERT(0);
#else
FreePhysMem(m_pPhysicalBufferAddr);
m_pPhysicalBufferAddr = 0;
#endif
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL CPhysMem::FreeList(PMEMLIST *ppHead)
{
PMEMLIST pCurrent;
PMEMLIST pNext;
DEBUGCHK( *ppHead != NULL );
if ( *ppHead != NULL ) {
pCurrent = (*ppHead)->next;
while ( pCurrent != *ppHead ) {
DEBUGCHK( pCurrent != NULL );
pNext = pCurrent->next;
CPhysMem_Free( pCurrent );
pCurrent = pNext;
}
CPhysMem_Free( *ppHead );
*ppHead = NULL;
}
return(TRUE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -