📄 physmem.c
字号:
/* Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved. */#include "kernel.h"//#define PHYSPAGESTOLEDS 1#ifdef PHYSPAGESTOLEDS#define LogPhysicalPages(PageFreeCount) OEMWriteDebugLED(0,PageFreeCount);#else#define LogPhysicalPages(PageFreeCount) (0)#endif#define STACK_RESERVE 15#define MIN_PROCESS_PAGES STACK_RESERVE#define PAGEOUT_LOW (( 68*1024)/PAGE_SIZE) // do pageout once below this mark, reset when above high#define PAGEOUT_HIGH ((132*1024)/PAGE_SIZE)#define PAGE_OUT_TRIGGER (( 24*1024)/PAGE_SIZE) // page out if below highwater and this much paged in recentlyvoid ZeroPage(void *pvPage);BOOL ScavengeStacks(int cNeed);HANDLE GwesOOMEvent;long GwesLowThreshold;long GwesCriticalThreshold;long GwesLowBlockSize;long GwesCriticalBlockSize;LPBYTE pFreeKStacks;extern void FreeSpareBytes(LPBYTE lpb, uint size);extern CRITICAL_SECTION PhysCS;extern PTHREAD pCleanupThread;// PageOutNeeded is set to 1 when the number of free pages drops below// PageOutTrigger and the cleanup thread's event is signalled. When the// cleanup thread starts performing page out, it sets the variable to 2.// When the page free count rises above PageOutLevel, PageOutNeeded is// reset to 0.//// The free page count thresholds are set based upon the Gwes OOM level.long PageOutNeeded;long PageOutTrigger; // Threshold level to start page out.long PageOutLevel; // Threshold to stop page out./* GWE calls this function to register an Out Of Memory event, which * HoldPages sets when free physical memory drops below the given threshold. */VOID SC_SetGwesOOMEvent(HANDLE hEvent, DWORD cpLow, DWORD cpCritical, DWORD cpLowBlockSize, DWORD cpCriticalBlockSize) { DEBUGMSG(ZONE_ENTRY,(L"SC_SetGwesOOMEvent entry: %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx\r\n", hEvent,cpLow,cpCritical,cpLowBlockSize,cpCriticalBlockSize)); GwesOOMEvent = hEvent; GwesLowThreshold = cpLow; GwesCriticalThreshold = cpCritical; GwesLowBlockSize = cpLowBlockSize; GwesCriticalBlockSize = cpCriticalBlockSize; PageOutLevel = GwesLowThreshold + PAGEOUT_HIGH; PageOutTrigger = GwesLowThreshold + PAGEOUT_LOW; DEBUGMSG(ZONE_ENTRY,(L"SC_SetGwesOOMEvent exit\r\n"));}#if PAGE_SIZE < 2048void UnlinkPhysPage(LPBYTE pMem) { KCALLPROFON(38); if (*(DWORD *)((DWORD)pMem + 0x20000000)) *(LPBYTE *)(*(DWORD *)((DWORD)pMem + 0x20000000) + 0x20000004) = *(LPBYTE *)((DWORD)pMem + 0x20000004); if (*(DWORD *)((DWORD)pMem + 0x20000004)) *(LPBYTE *)(*(DWORD *)((DWORD)pMem + 0x20000004) + 0x20000000) = *(LPBYTE *)((DWORD)pMem + 0x20000000); else LogPtr->pKList = *(LPBYTE *)((DWORD)pMem + 0x20000000); *(LPDWORD)(pMem + 0x20000000) = 0; *(LPDWORD)(pMem + 0x20000004) = 0; KCALLPROFOFF(38);}#endifvoid LinkPhysPage(LPBYTE pMem) { KCALLPROFON(32); *(LPBYTE *)((DWORD)pMem + 0x20000000) = LogPtr->pKList; *(LPBYTE *)((DWORD)pMem + 0x20000004) = 0; if (LogPtr->pKList) *(LPBYTE *)((DWORD)LogPtr->pKList + 0x20000004) = pMem; LogPtr->pKList = pMem; PageFreeCount++; LogPhysicalPages(PageFreeCount); KCALLPROFOFF(32);}LPBYTE GrabFirstPhysPage(DWORD dwCount) { PFREEINFO pfi; uint ix; PHYSICAL_ADDRESS paRet; LPBYTE pMem; KCALLPROFON(33); if (pMem = LogPtr->pKList) { paRet = GetPFN(pMem); if (LogPtr->pKList = *(LPBYTE *)((DWORD)pMem + 0x20000000)) *(LPBYTE *)((DWORD)LogPtr->pKList + 0x20000004) = 0; *(LPDWORD)(pMem + 0x20000000) = 0; *(LPDWORD)(pMem + 0x20000004) = 0; pfi = GetRegionFromAddr(paRet); ix = (paRet - pfi->paStart) / PFN_INCR; DEBUGCHK(pfi->pUseMap[ix] == 0); DEBUGCHK(dwCount && (dwCount <= 0xff)); pfi->pUseMap[ix] = (BYTE)dwCount; PageFreeCount--; LogPhysicalPages(PageFreeCount); DEBUGCHK(PageFreeCount >= 0); } DEBUGCHK(pMem); KCALLPROFOFF(33); return pMem; }// called by loader.c when moving memory "slider"void RemovePage(DWORD dwAddr) { DWORD pfn, ix; FREEINFO *pfi; pfn = GetPFN(dwAddr); pfi = GetRegionFromAddr(pfn); DEBUGCHK(pfi); ix = (pfn - pfi->paStart) / PFN_INCR; pfi->pUseMap[ix] = 0xff;}BOOL DemandCommit(ulong addr) { MEMBLOCK *pmb; LPDWORD pPage; PFREEINFO pfi; uint ix; PHYSICAL_ADDRESS paRet; LPBYTE pMem; pmb = (*SectionTable[addr>>VA_SECTION])[(addr>>VA_BLOCK) & BLOCK_MASK]; if (!*(pPage = &pmb->aPages[(addr>>VA_PAGE) & PAGE_MASK])) { pMem = LogPtr->pKList; if (GwesOOMEvent && (PageFreeCount < GwesCriticalThreshold)) { SetEvent(GwesOOMEvent); } if (!PageFreeCount || !pMem) { RETAILMSG(1,(L"--->>> DemandCommit: FATAL ERROR! COMPLETELY OUT OF MEMORY (%8.8lx %8.8lx)!\r\n",pMem,PageFreeCount)); INTERRUPTS_OFF(); while (1) { // we don't recover if there's no memory, so better off to just stop } return FALSE; } paRet = GetPFN(pMem); pMem = (LPBYTE)((DWORD)pMem + 0x20000000); if (LogPtr->pKList = *(LPBYTE *)pMem) *(LPBYTE *)((DWORD)LogPtr->pKList + 0x20000004) = 0; *(LPDWORD)pMem = 0; *(LPDWORD)(pMem + 4) = 0; pfi = GetRegionFromAddr(paRet); ix = (paRet - pfi->paStart) / PFN_INCR; DEBUGCHK(!pfi->pUseMap[ix]); pfi->pUseMap[ix] = 1; *pPage = paRet | PG_READ_WRITE; PageFreeCount--; LogPhysicalPages(PageFreeCount); DEBUGCHK(PageFreeCount >= 0); return TRUE; } return FALSE;}void EnterPhysCS(void) { LPVOID pMem; EnterCriticalSection(&PhysCS); DEBUGCHK(PhysCS.OwnerThread == hCurThread); if (PhysCS.LockCount == 1) while (pMem = InterlockedPopList(&pFreeKStacks)) FreeHelperStack(pMem);}BOOL SC_GiveKPhys(void *ptr, ulong length) { BOOL bRet = FALSE; LPBYTE pPage; DWORD loop; PFREEINFO pfi; PHYSICAL_ADDRESS paPFN; uint ix; if (pCurProc->bTrustLevel != KERN_TRUST_FULL) { KSetLastError(pCurThread, ERROR_ACCESS_DENIED); return 0; } DEBUGMSG(ZONE_ENTRY,(L"SC_GiveKPhys entry: %8.8lx %8.8lx\r\n",ptr,length)); SC_CacheSync(CACHE_SYNC_DISCARD); EnterPhysCS(); for (loop = 0; loop < length; loop++) { pPage = *((LPBYTE *)ptr+loop); ZeroPage(pPage + 0x20000000); paPFN = GetPFN(pPage); pfi = GetRegionFromAddr(paPFN); DEBUGCHK(pfi); ix = (paPFN - pfi->paStart) / PFN_INCR; DEBUGCHK(pfi->pUseMap[ix] == 0xff); pfi->pUseMap[ix] = 0; KCall((PKFN)LinkPhysPage,pPage); } KInfoTable[KINX_NUMPAGES] += length; // If there are enough free pages, clear the PageOutNeeded flag. if (PageFreeCount > PageOutLevel) PageOutNeeded = 0; bRet = TRUE; LeaveCriticalSection(&PhysCS); DEBUGMSG(ZONE_ENTRY,(L"SC_GiveKPhys exit: %8.8lx\r\n",bRet)); return bRet;}BOOL SC_GetKPhys(void *ptr, ulong length) { LPVOID *pPages; BOOL bRet = FALSE; DWORD dwCount; LPBYTE pMem; DEBUGMSG(ZONE_ENTRY,(L"SC_GetKPhys entry: %8.8lx %8.8lx\r\n",ptr,length)); if (pCurProc->bTrustLevel != KERN_TRUST_FULL) { KSetLastError(pCurThread, ERROR_ACCESS_DENIED); return 0; } pPages = (LPVOID *)ptr; EnterPhysCS(); ScavengeStacks(100000); // Reclaim all extra stack pages. if ((length == 1) || ((DWORD)PageFreeCount > length + PageOutTrigger)) { for (dwCount = length; dwCount; dwCount--) { if (!(pMem = (LPBYTE)KCall((PKFN)GrabFirstPhysPage,0xff))) { LeaveCriticalSection(&PhysCS); SC_GiveKPhys(ptr,length - dwCount); DEBUGCHK(0); RETAILMSG(1,(L"Error getting pages!\r\n")); return 0; } KInfoTable[KINX_NUMPAGES]--; *pPages++ = pMem; } bRet = TRUE; } LeaveCriticalSection(&PhysCS); DEBUGMSG(ZONE_ENTRY,(L"SC_GetKPhys exit: %8.8lx\r\n",bRet)); return bRet;} void InitMemoryPool() { PFREEINFO pfi, pfiEnd; DWORD loop; LPBYTE pPage; /* Fill in data fields in user visible kernel data page */ KInfoTable[KINX_PROCARRAY] = (long)ProcArray; KInfoTable[KINX_PAGESIZE] = PAGE_SIZE;#ifdef PFN_SHIFT KInfoTable[KINX_PFN_SHIFT] = PFN_SHIFT;#endif KInfoTable[KINX_PFN_MASK] = (DWORD)PFNfromEntry(~0); KInfoTable[KINX_SECTIONS] = (long)SectionTable; KInfoTable[KINX_MEMINFO] = (long)&MemoryInfo; KInfoTable[KINX_KDATA_ADDR] = (long)&KData; SC_CacheSync(CACHE_SYNC_DISCARD); for (pfi = MemoryInfo.pFi, pfiEnd = pfi+MemoryInfo.cFi ; pfi < pfiEnd ; ++pfi) { DEBUGMSG(ZONE_MEMORY, (TEXT("InitMemoryPool: Init range: map=%8.8lx start=%8.8lx end=%8.8lx\r\n"), pfi->pUseMap, pfi->paStart, pfi->paEnd)); pPage = 0; for (loop = pfi->paStart; loop < pfi->paEnd; loop += PFN_INCR) { if (!pfi->pUseMap[(loop-pfi->paStart)/PFN_INCR]) { pPage = Phys2Virt(loop); ZeroPage(pPage + 0x20000000); LinkPhysPage(pPage); LogPtr->pKList = pPage; KInfoTable[KINX_NUMPAGES]++; } } } DEBUGMSG(ZONE_MEMORY,(TEXT("InitMemoryPool done, free=%d\r\n"),PageFreeCount));}PTHREAD PthScavTarget;PPROCESS PprcScavTarget = &ProcArray[0];int StackScavCount;HTHREAD ScavengeOnePage(void) { HTHREAD ret; KCALLPROFON(13); if (!PthScavTarget) { if (++PprcScavTarget >= &ProcArray[MAX_PROCESSES]) PprcScavTarget = ProcArray; ++StackScavCount; if (!PprcScavTarget->dwVMBase || !(PthScavTarget = PprcScavTarget->pTh)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -