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

📄 physmem.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 3 页
字号:
hpDone:
    LeaveCriticalSection(&PhysCS);
    if (fSetGweOomEvent) {
        SetOOMEvt ();
    }
    return bRet;
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
DupPhysPage(
    PHYSICAL_ADDRESS paPFN
    ) 
{
    PFREEINFO pfi;
    uint ix;

    //NOTE: DupPhysage and FreePhysPage are only called by the virtual memory
    // system with the VA critical section held so DupPhysPage does not need to
    // claim the physical memory critical section because it does not change
    // the page free count.
    if ((pfi = GetRegionFromAddr(paPFN)) != 0) {
        ix = (paPFN - pfi->paStart) / PFN_INCR;
        DEBUGCHK((pfi->pUseMap[ix] != 0) && (pfi->pUseMap[ix] != 0xff));
        DEBUGMSG(ZONE_PHYSMEM, (TEXT("DupPhysPage: PFN=%8.8lx ix=%x rc=%d\r\n"), paPFN,
                ix, pfi->pUseMap[ix]));
        ++pfi->pUseMap[ix];
    }
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
FreePhysPage(
    PHYSICAL_ADDRESS paPFN
    ) 
{
    PFREEINFO pfi;
    uint ix;

    if ((pfi = GetRegionFromAddr(paPFN)) != 0) {
        ix = (paPFN - pfi->paStart) / PFN_INCR;
        DEBUGMSG(ZONE_PHYSMEM, (TEXT("FreePhysPage: PFN=%8.8lx ix=%x rc=%d\r\n"), paPFN,
                ix, pfi->pUseMap[ix]));
        EnterPhysCS();
        DEBUGCHK(pfi->pUseMap[ix] != 0);
        if ((pfi->pUseMap[ix] != 0xff) && (!--pfi->pUseMap[ix])) {
            DEBUGMSG(ZONE_PHYSMEM, (TEXT("FreePhysPage: PFN=%8.8lx\r\n"), paPFN));
            ZeroPage((LPBYTE)Phys2Virt(paPFN)+0x20000000);
            KCall((PKFN)LinkPhysPage,Phys2Virt(paPFN));
            // If there are enough free pages, clear the PageOutNeeded flag.
            if (PageFreeCount > PageOutLevel)
                PageOutNeeded = 0;
        }
        LeaveCriticalSection(&PhysCS);
    }
}

LPVOID PhysPageToZero (PHYSICAL_ADDRESS paPFN) 
{
    PFREEINFO pfi;
    uint ix;
    LPVOID pPage = NULL;

    if ((pfi = GetRegionFromAddr(paPFN)) != 0) {
        ix = (paPFN - pfi->paStart) / PFN_INCR;
        DEBUGMSG(ZONE_PHYSMEM, (TEXT("PhysPageToZero: PFN=%8.8lx ix=%x rc=%d\r\n"), paPFN,
                ix, pfi->pUseMap[ix]));
        EnterPhysCS();
        DEBUGCHK(pfi->pUseMap[ix] != 0);
        if ((pfi->pUseMap[ix] != 0xff) && (!--pfi->pUseMap[ix])) {
            DEBUGMSG(ZONE_PHYSMEM, (TEXT("PhysPageToZero: PFN=%8.8lx\r\n"), paPFN));
            pPage = (LPVOID) Phys2VirtUC (paPFN);
            DEBUGCHK (pPage);
            // set pfi->pUseMap[ix] = 0xff to avoid being used by GetContigiousPages, which
            // scans pUseMap to find pages.
            pfi->pUseMap[ix] = 0xff;
            // save &pfi->pUseMap[ix] on the page so we can clean it later
            *(LPDWORD) ((DWORD)pPage + sizeof(LPVOID)) = (DWORD) &pfi->pUseMap[ix];
            
        }
        LeaveCriticalSection(&PhysCS);
    }
    return pPage;
}

void ZeroAndLinkPhysPage (LPVOID pPage)
{
    LPBYTE pUseMap = (LPBYTE) (*(LPDWORD) ((DWORD)pPage + sizeof(LPVOID)));
    DEBUGMSG(ZONE_PHYSMEM, (TEXT("ZeroAndLinkPhysPage: pPage=%8.8lx\r\n"), pPage));
    DEBUGCHK ((DWORD)pPage & 0x20000000);  // MUST BE A UNCACHED ADDRESS
    ZeroPage (pPage);
    
    EnterPhysCS ();
    // reset pfi->pUseMap[ix] to 0 (set to 0xff in PhysPageToZero)
    DEBUGCHK (0xff == *pUseMap);
    *pUseMap = 0;
    KCall((PKFN)LinkPhysPage, (LPBYTE) pPage - 0x20000000); // LinkPhysPage takes cached address as argument
    // If there are enough free pages, clear the PageOutNeeded flag.
    if (PageFreeCount > PageOutLevel)
        PageOutNeeded = 0;
    LeaveCriticalSection (&PhysCS);
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
TakeSpecificPage(
    PFREEINFO pfi, 
    uint ix,
    LPBYTE pMem
    ) 
{
    KCALLPROFON(40);
    if (pfi->pUseMap[ix]) {
        KCALLPROFOFF(40);
        return FALSE;
    }
    pfi->pUseMap[ix] = 1;
    UnlinkPhysPage(pMem);
    KCALLPROFOFF(40);
    return TRUE;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPBYTE 
GiveSpecificPage(
    PFREEINFO pfi, 
    uint ix, 
    LPBYTE pMem
    ) 
{
    KCALLPROFON(40);
    if (pfi->pUseMap[ix] != 1) {
        KCALLPROFOFF(40);
        return 0;
    }
    pfi->pUseMap[ix] = 0;
    LinkPhysPageOnly(pMem);
    KCALLPROFOFF(40);
    return pMem;
}


//------------------------------------------------------------------------------
//
// Try to grab physically contiguous pages. This routine needs to be preemptive
// as much as possible, so we may take some pages and end up giving them back if
// a full string of pages can't be found. Pages are potentially coming and 
// going, but we'll only make one pass through memory.
//
//------------------------------------------------------------------------------
PHYSICAL_ADDRESS
GetContiguousPages(
    DWORD dwPages,
    DWORD dwAlignment, 
    DWORD dwFlags
    ) 
{
    PFREEINFO pfi, pfiEnd;
    uint ixWalk, ixTarget, ixStart, ixTotal, ixTemp;
    PHYSICAL_ADDRESS paRet = INVALID_PHYSICAL_ADDRESS;
    DWORD pfc;
    
    if (((DWORD) PageFreeCount > dwPages + MIN_PROCESS_PAGES) && HoldPages(dwPages, FALSE)) {
        //
        // We've at least got enough pages available and that many have been set
        // aside for us (though not yet assigned). 
        //
        pfi = &MemoryInfo.pFi[0];
        pfiEnd = pfi + MemoryInfo.cFi;

        for (; pfi < pfiEnd ; ++pfi) {
            //
            // For each memory section, scan the free pages.
            //
            ixTotal = (pfi->paEnd - pfi->paStart) / PFN_INCR;
            //
            // Find a string of free pages
            //
            for (ixStart = 0; ixStart <= (ixTotal - dwPages); ) {
                
                if (pfi->pUseMap[ixStart] || (dwAlignment & PFN2PA(pfi->paStart + (ixStart * PFN_INCR))) ) {
                    //
                    // Page in use or doesn't match alignment request, skip ahead
                    //
                    ixStart++;
                } else {
                    ixTarget = ixStart + dwPages;
                    for (ixWalk = ixStart; ixWalk < ixTarget; ixWalk++) {
                        
                        if (pfi->pUseMap[ixWalk] || 
                            !KCall((PKFN)TakeSpecificPage, pfi, ixWalk, Phys2Virt(pfi->paStart + (ixWalk * PFN_INCR)))) {

                            //
                            // Page in use, free all the pages so far and reset start
                            //
                            for (ixTemp = ixStart; ixTemp < ixWalk; ixTemp++) {
                                KCall((PKFN)GiveSpecificPage, pfi, ixTemp, Phys2Virt(pfi->paStart + (ixTemp * PFN_INCR)));
                            }
                            ixStart = ixWalk + 1;
                            break;
                        } 
                    }

                    if (ixWalk == ixTarget) {
                        paRet = pfi->paStart + (ixStart * PFN_INCR);
                        goto foundPages;
                    }
                }
            }
        }
        //
        // We couldn't lock down a contiguous section so free up the "held" 
        // pages before leaving.
        //
        do {
            pfc = PageFreeCount;
        } while (InterlockedTestExchange(&PageFreeCount,pfc,pfc+dwPages) != (LONG)pfc);
    }
foundPages:
    DEBUGMSG(ZONE_PHYSMEM,(TEXT("GetContiguousPages: Returning %8.8lx\r\n"), paRet));
    return paRet;
}



ERRFALSE(sizeof(SECTION) == 2048);

#if PAGE_SIZE == 4096


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PSECTION 
GetSection(void)
{
    PHYSICAL_ADDRESS pAddr;
    if ((PageFreeCount > 1+MIN_PROCESS_PAGES) && HoldPages(1, FALSE)) {
        if (pAddr = GetHeldPage()) {
            InterlockedIncrement(&KInfoTable[KINX_SYSPAGES]);
            return Phys2Virt(pAddr); // can't put GetHeldPage, since Phys2Virt's a macro!
        }
        InterlockedIncrement(&PageFreeCount);
    }
    return 0;
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
FreeSection(
    PSECTION pscn
    ) 
{
#if defined (MIPS) || defined (SHx)
	// MIPS and SHx: flush TLB since the same ASID can be reused by new process
    OEMCacheRangeFlush (0, 0, CACHE_SYNC_DISCARD | CACHE_SYNC_FLUSH_TLB);
#else
    OEMCacheRangeFlush (0, 0, CACHE_SYNC_DISCARD);
#endif
    FreePhysPage(GetPFN(pscn));
    InterlockedDecrement(&KInfoTable[KINX_SYSPAGES]);
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID 
GetHelperStack(void) 
{
    return AllocMem(HEAP_HLPRSTK);
//  return GetSection();
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
FreeHelperStack(
    LPVOID pMem
    ) 
{
    FreeMem(pMem,HEAP_HLPRSTK);
//  FreeSection(pMem);
}

#else

ERRFALSE((sizeof(SECTION)+PAGE_SIZE-1)/PAGE_SIZE == 2);



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
FreeSection(
    PSECTION pscn
    ) 
{
    PHYSICAL_ADDRESS paSect;
    paSect = GetPFN(pscn);
    OEMCacheRangeFlush (0, 0, CACHE_SYNC_DISCARD);
    FreePhysPage(paSect);
    FreePhysPage(NextPFN(paSect));
    InterlockedDecrement(&KInfoTable[KINX_SYSPAGES]);
    InterlockedDecrement(&KInfoTable[KINX_SYSPAGES]);
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPBYTE 
TakeTwoPages(
    PFREEINFO pfi, 
    uint ix, 
    LPBYTE pMem
    ) 
{
    KCALLPROFON(40);
    if (pfi->pUseMap[ix] || pfi->pUseMap[ix+1]) {
        KCALLPROFOFF(40);
        return 0;
    }
    pfi->pUseMap[ix] = 1;
    pfi->pUseMap[ix+1] = 1;
    UnlinkPhysPage(pMem);
    UnlinkPhysPage(pMem+PAGE_SIZE);
    KCALLPROFOFF(40);
    return pMem;
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PSECTION 
GetSection(void) 
{
    PFREEINFO pfi, pfiEnd;
    uint ix;
    PHYSICAL_ADDRESS paSect;
    PSECTION pscn = 0;
    LPVOID pMem;
    while (pMem = InterlockedPopList(&pFreeKStacks))
        FreeHelperStack(pMem);
    if ((PageFreeCount > 2+MIN_PROCESS_PAGES) && HoldPages(2, FALSE)) {
        pfi = &MemoryInfo.pFi[0];
        for (pfi = &MemoryInfo.pFi[0], pfiEnd = pfi+MemoryInfo.cFi ; pfi < pfiEnd ; ++pfi) {
            paSect = pfi->paEnd - 2 * PFN_INCR;
            ix = (paSect - pfi->paStart) / PFN_INCR;
            while (paSect >= pfi->paStart) {
                if (pscn = (PSECTION)KCall((PKFN)TakeTwoPages,pfi,ix,Phys2Virt(paSect))) {
                    InterlockedIncrement(&KInfoTable[KINX_SYSPAGES]);
                    InterlockedIncrement(&KInfoTable[KINX_SYSPAGES]);
                    goto foundPages;
                }
                ix--;
                paSect -= PFN_INCR;
            }
        }
        InterlockedIncrement(&PageFreeCount);
        InterlockedIncrement(&PageFreeCount);
    }
foundPages:
    DEBUGMSG(ZONE_PHYSMEM,(TEXT("GetSection: Returning %8.8lx\r\n"), pscn));
    return pscn;
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID 
GetHelperStack(void) 
{
    PHYSICAL_ADDRESS pAddr;
    if (HoldPages(1, FALSE)) {
        if (pAddr = GetHeldPage()) {
            InterlockedIncrement(&KInfoTable[KINX_SYSPAGES]);
            return Phys2Virt(pAddr); // can't put GetHeldPage, since Phys2Virt's a macro!
        }
        InterlockedIncrement(&PageFreeCount);
    }
    return 0;
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
FreeHelperStack(
    LPVOID pMem
    ) 
{
    OEMCacheRangeFlush (0, 0, CACHE_SYNC_DISCARD);
    FreePhysPage(GetPFN(pMem));
    InterlockedDecrement(&KInfoTable[KINX_SYSPAGES]);
}

#endif

⌨️ 快捷键说明

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