⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cphysmem.cpp

📁 Intel PXA270 Wince5.0 BSP
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    //
    // 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 + -