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

📄 cphysmem.cpp

📁 Intel PXA270 Wince5.0 BSP
💻 CPP
📖 第 1 页 / 共 3 页
字号:


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

BOOL 
CPhysMem::AllocateSpecialMemory(
    IN const DWORD DEBUG_ONLY( dwSize ), // dwSize ignored in retail
    OUT PUCHAR* const pVirtAddr )
{
    DEBUGCHK( dwSize <= USBPAGESIZE );
    DEBUGCHK( pVirtAddr != NULL );

    // during suspend/resume this routine will be called again; we can safely
    // leave the special memory set aside since we will always need the same amount.
    if(!m_bSpecialTaken) {
        m_bSpecialTaken = TRUE;
        DEBUGCHK( m_dwSpecialPA == VaToPa( PUCHAR(m_dwSpecialVA) ) );
        DEBUGCHK( m_dwSpecialPA % CPHYSMEM_MEMORY_ALIGNMENT == 0 );
    }

    *pVirtAddr = (PUCHAR) m_dwSpecialVA;

    DEBUGMSG(ZONE_CPHYSMEM && ZONE_VERBOSE,(TEXT("CPhysMem AllocateMemory : bSpecial allocated\r\n")));
    return(TRUE);
}

void 
CPhysMem::FreeSpecialMemory(
    IN const PUCHAR DEBUG_ONLY( virtAddr ) ) // virtAddr ignored in retail
{

    DEBUGCHK( m_dwSpecialVA == (DWORD) virtAddr );
    DEBUGCHK( m_bSpecialTaken );

    m_bSpecialTaken = FALSE;
}

BOOL
CPhysMem::AllocateMemory(
    DEBUG_PARAM( IN const TCHAR* pszMemDescription, ) // description of memory being alloc'd
    IN const DWORD dwPassedInSize,
    OUT PUCHAR* const pVirtAddr,
    IN const DWORD dwFlags,
    IN BOOL* pfRequestingAbort // = NULL 
    )
{
#ifdef DEBUG
    DEBUGCHK( pszMemDescription != NULL );
    DEBUGCHK( dwPassedInSize > 0 );
    DEBUGCHK( pVirtAddr != NULL );
    // for now, only the following sets of flags should be passed in
    DEBUGCHK( dwFlags == 0 || // low priority, allow blocking
              dwFlags == CPHYSMEM_FLAG_NOBLOCK || // low priority, no blocking
              dwFlags == (CPHYSMEM_FLAG_HIGHPRIORITY | CPHYSMEM_FLAG_NOBLOCK) ); // high pri, no blocking

    if ( dwFlags & CPHYSMEM_FLAG_NOBLOCK ) {
        // pfRequestingAbort will be ignored for NO_BLOCK transfers,
        // so why is caller passing it in? Note that nothing
        // bad will happen if pfRequestingAbort != NULL, so
        // this check can be removed in the future if need be.
        DEBUGCHK( pfRequestingAbort == NULL );
    } else {
        // blocking transfers must pass in a pointer
        // for allowing the transfer to abort, and
        // the original state of this abort request
        // should be FALSE. If not, the blocking
        // request is ignored.
        DEBUGCHK( pfRequestingAbort != NULL &&
                  *pfRequestingAbort == FALSE );
    }
#endif // DEBUG

    PMEMLIST    pNode = NULL;
    const BOOL  fHighPri = !!(dwFlags & CPHYSMEM_FLAG_HIGHPRIORITY);
    const BOOL  fNoBlock = !!(dwFlags & CPHYSMEM_FLAG_NOBLOCK);
    // We keep our block sizes in multiples of CPHYSMEM_MEMORY_ALIGNMENT
    DWORD       dwSize = ( (dwPassedInSize - 1) & ~(CPHYSMEM_MEMORY_ALIGNMENT - 1) )
                                 + CPHYSMEM_MEMORY_ALIGNMENT;

    DEBUGCHK( dwSize % CPHYSMEM_MEMORY_ALIGNMENT == 0 );
    DEBUGCHK( dwSize - dwPassedInSize < CPHYSMEM_MEMORY_ALIGNMENT );
    DEBUGMSG(ZONE_CPHYSMEM && ZONE_VERBOSE && (dwSize != dwPassedInSize),
             (TEXT("AllocateMemory Desc = %s: (roundup %d->%d)\r\n"), pszMemDescription, dwPassedInSize, dwSize ));

    EnterCriticalSection( &m_csLock );

    DEBUGMSG( ZONE_CPHYSMEM && ZONE_VERBOSE, (TEXT("CPhysMem: Heap pri = %d before allocation of %d bytes:\n"), fHighPri, dwSize ) );
    VALIDATE_HEAPS(fHighPri);

    //
    // Scan the free list for the first chunk that's just big enough to satisfy
    // this request. Remove from the free list. Chop it up (unless the result 
    // is less than CPHYSMEM_MEMORY_ALIGNMENT bytes). Then re-sort the remaining
    // free chunk back into the free list and place the newly allocated chunk on
    // the IN USE list.
    //
    pNode = FindFreeBlock(dwSize, fHighPri);
    if ( pNode == NULL ) {
        if ( fHighPri ) {
            //
            // Not available from High Priority region, try allocating from Normal region.
            //
            LeaveCriticalSection(&m_csLock);

            DEBUGCHK( dwFlags == (CPHYSMEM_FLAG_HIGHPRIORITY | CPHYSMEM_FLAG_NOBLOCK) );
            return AllocateMemory( DEBUG_PARAM( pszMemDescription, )
                                   dwPassedInSize,
                                   pVirtAddr,
                                   CPHYSMEM_FLAG_NOBLOCK, // dwFlags & ~CPHYSMEM_FLAG_HIGHPRIORITY,
                                   pfRequestingAbort );

        } else if ( !fNoBlock &&
                    pfRequestingAbort != NULL ) {
            //
            // Caller requested block for memory 
            //
        #ifdef DEBUG
            DWORD dwStartBlockTickCount = GetTickCount();
        #endif // DEBUG
            do {
                LeaveCriticalSection(&m_csLock);

                if ( *pfRequestingAbort == FALSE ) {
                    m_fHasBlocked = TRUE;
                    WaitForSingleObject(m_hFreeMemEvent, CPHYSMEM_BLOCK_FOR_MEM_INTERVAL );

                    if ( *pfRequestingAbort ) {
                        *pVirtAddr = NULL;
                        return FALSE;
                    }

                    // if this fails, we've been waiting for memory too long
                    DEBUGCHK( GetTickCount() - dwStartBlockTickCount < CPHYSMEM_DEBUG_MAXIMUM_BLOCK_TIME );
                }

                EnterCriticalSection(&m_csLock);

                pNode = FindFreeBlock(dwSize, fHighPri);
            } while ( pNode == NULL );
            // rest of processing done below
        } else {
            DEBUGMSG( ZONE_WARNING, (TEXT("CPhysMem AllocateMemory : No memory available") ));
            LeaveCriticalSection(&m_csLock);
            *pVirtAddr = NULL;
            return FALSE;
        }
    }

    // case pNode == NULL should have been handled above

    if ( pNode->dwSize - dwSize >= CPHYSMEM_MEMORY_ALIGNMENT) {
        // There's enough left over to create a new block.
        PMEMLIST pNodeNew = CreateNewNode(pNode->dwSize - dwSize,
                                          pNode->dwVirtAddr + dwSize, 
                                          pNode->dwPhysAddr + dwSize);
    #ifdef DEBUG
        _tcscpy( pNodeNew->szDescription, pNode->szDescription );
    #endif // DEBUG
        AddNodeToFreeList(pNodeNew, fHighPri);

        pNode->dwSize = dwSize; // remember to resize old block
    }

#ifdef DEBUG
    // add description to block
    DEBUGCHK( _tcslen( pszMemDescription ) < CPHYSMEM_MAX_DEBUG_NODE_DESCRIPTION_LENGTH );
    _tcscpy( pNode->szDescription, pszMemDescription );
    // trash the memory before we return it to caller
    memset( PUCHAR( pNode->dwVirtAddr ), GARBAGE, pNode->dwSize );
#endif // DEBUG

    DEBUGMSG(ZONE_CPHYSMEM && ZONE_VERBOSE, (TEXT("CPhysMem AllocateMemory : PA = 0x%08X, VA = 0x%08X, Size = %d, Desc = %s\r\n"),
                          pNode->dwPhysAddr, pNode->dwVirtAddr, pNode->dwSize, pNode->szDescription ) );

    // mark this node used
    InsertNodeBefore(pNode, FirstNode(INUSELIST(fHighPri)));

    VALIDATE_HEAPS(fHighPri);

    LeaveCriticalSection(&m_csLock);

    DEBUGCHK( pNode->dwPhysAddr % CPHYSMEM_MEMORY_ALIGNMENT == 0 );
    *pVirtAddr = PUCHAR( pNode->dwVirtAddr );
    return TRUE;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
CPhysMem::FreeMemory(
    IN const PUCHAR virtAddr, 
    IN const ULONG physAddr, 
    IN const DWORD dwFlags
    )
{
    // for now, only the following sets of flags should be passed in
    DEBUGCHK( dwFlags == 0 || // low priority, allow blocking
              dwFlags == CPHYSMEM_FLAG_NOBLOCK || // low priority, no blocking
              dwFlags == (CPHYSMEM_FLAG_HIGHPRIORITY | CPHYSMEM_FLAG_NOBLOCK) ); // high pri, no blocking

    BOOL fRemoved = FALSE;
    BOOL fHighPri = !!(dwFlags & CPHYSMEM_FLAG_HIGHPRIORITY);

    // caller of FreeMemory is capable of calling
    // PaToVa or VaToPa if they need to. Also, 
    // we shouldn't be called to free NULL memory.
    DEBUGCHK( virtAddr != NULL && physAddr != 0 ); 
    DEBUGCHK( virtAddr == PaToVa( physAddr ) );
    DEBUGCHK( physAddr % CPHYSMEM_MEMORY_ALIGNMENT == 0 );

    EnterCriticalSection(&m_csLock);

    PMEMLIST pNode = FirstNode(INUSELIST(fHighPri));
    
    DEBUGMSG( ZONE_CPHYSMEM && ZONE_VERBOSE, (TEXT("CPhysMem: Heap pri = %d before free VA = 0x%08x:\n"), fHighPri, virtAddr ) );
    VALIDATE_HEAPS(fHighPri);

    //
    // Walk the list looking for this block
    //
    while (!EndOfList(INUSELIST(fHighPri), pNode)) {

        if ((pNode->dwVirtAddr == (DWORD) virtAddr) &&
            (pNode->dwPhysAddr == (DWORD) physAddr)) {
            
        #ifdef DEBUG
            // trash this memory
            DEBUGCHK( pNode->dwSize > 0 ); // otherwise, why are we calling FreeMemory??
            memset( PUCHAR( pNode->dwVirtAddr ), GARBAGE, pNode->dwSize );

            DEBUGMSG(ZONE_CPHYSMEM && ZONE_VERBOSE, 
                     (TEXT("CPhysMem FreeMemory : PA = 0x%08X, VA = 0x%08X, Size = %d, Desc = %s\r\n"),
                     pNode->dwPhysAddr, pNode->dwVirtAddr, pNode->dwSize, pNode->szDescription ));

            // change description
            _tcscpy( pNode->szDescription, TEXT("Freed Memory") );
        #endif // DEBUG
            RemoveNode(pNode);
            AddNodeToFreeList(pNode, fHighPri);
            fRemoved = TRUE;
            break;
        }
        pNode = pNode->next;
    }
    
    if (fHighPri && !fRemoved) {
        LeaveCriticalSection(&m_csLock);

        //
        // Try removing from normal region.
        //
        DEBUGCHK( dwFlags == ( CPHYSMEM_FLAG_HIGHPRIORITY | CPHYSMEM_FLAG_NOBLOCK ) );
        FreeMemory( virtAddr,
                    physAddr,
                    CPHYSMEM_FLAG_NOBLOCK ); // dwFlags & ~CPHYSMEM_FLAG_HIGHPRIORITY
        return;
    }
    DEBUGCHK( fRemoved );
    
    DEBUGMSG( ZONE_CPHYSMEM && ZONE_VERBOSE, (TEXT("CPhysMem: Heap pri = %d after free VA = 0x%08x:\n"), fHighPri, virtAddr ) );
    VALIDATE_HEAPS(fHighPri);

    LeaveCriticalSection(&m_csLock);

    //
    // Signal everyone waiting for memory that some just became available.
    //
    if (m_fHasBlocked)
        PulseEvent(m_hFreeMemEvent);
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL 
CPhysMem::ReleaseBlockedCalls()
{
    //
    // Signal everyone waiting for memory to check if they have been aborted.
    //
    if (m_fHasBlocked)
        PulseEvent(m_hFreeMemEvent);
    
    return(TRUE);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -