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

📄 physmem.c

📁 See Hanoi.cpp for the implementation of this cla
💻 C
📖 第 1 页 / 共 2 页
字号:
	    	KCALLPROFOFF(13);
	    	return 0;
	    }
	    if (PthScavTarget == pCurThread)
	    	PthScavTarget = pCurThread->pNextInProc;
	    KCALLPROFOFF(13);
	    return 0;
    }
    if (HandleToThread(PthScavTarget->hTh) != PthScavTarget) {
	    PthScavTarget = 0;
    	KCALLPROFOFF(13);
    	return 0;
    }
    ret = ((pCurThread != PthScavTarget) && MDTestStack(PthScavTarget)) ? PthScavTarget->hTh : 0;
    if ((PthScavTarget = PthScavTarget->pNextInProc) == pCurThread)
    	PthScavTarget = pCurThread->pNextInProc;
	KCALLPROFOFF(13);
    return ret;
}

HANDLE hCurrScav;

BOOL ScavengeStacks(int cNeed) {
    HTHREAD hth;
    PTHREAD pth;
	ulong addr, pages, base;
    ulong pte;
    int ixPage, ixBlock;
    PSECTION pscn;
    MEMBLOCK *pmb;
    ACCESSKEY ulOldKey;
    DEBUGMSG(ZONE_MEMORY, (TEXT("Scavenging stacks for %d pages.\r\n"), cNeed-PageFreeCount));
    StackScavCount = 0;
    SWITCHKEY(ulOldKey,0xffffffff);
    while ((StackScavCount <= MAX_PROCESSES) && (cNeed > PageFreeCount)) {
    	if (hth = (HTHREAD)KCall((PKFN)ScavengeOnePage)) {
        	if (SuspendThread(hth) != -1) {
        		hCurrScav = hth;
        		pages = 0;
        		pth = HandleToThread(hth);
				SC_CacheSync(CACHE_SYNC_DISCARD);
				while (addr = MDTestStack(pth)) {
				    pscn = SectionTable[addr>>VA_SECTION];
				    ixBlock = (addr>>VA_BLOCK) & BLOCK_MASK;
				    ixPage = (addr>>VA_PAGE) & PAGE_MASK;
				    if ((pmb = (*pscn)[ixBlock]) == NULL_BLOCK || pmb == RESERVED_BLOCK ||
						!(pmb->flags&MB_FLAG_AUTOCOMMIT) || pmb == PmbDecommitting ||
						!(pte = pmb->aPages[ixPage]) || pte == BAD_PAGE)
						break;
			        pmb->aPages[ixPage] = 0;
		            MDShrinkStack(pth);
					FreePhysPage(PFNfromEntry(pte));
		            DEBUGCHK(!pages || (base == addr - PAGE_SIZE));
		            base = addr;
		            pages++;
				}
				if (pages)
		            InvalidateRange((PVOID)base, PAGE_SIZE*pages);
        		hCurrScav = 0;
				ResumeThread(hth);
			}
		}
	}
	SETCURKEY(ulOldKey);
	return (StackScavCount > MAX_PROCESSES) ? FALSE : TRUE;
}

PHYSICAL_ADDRESS GetHeldPage(void) {
    PHYSICAL_ADDRESS paRet;
	LPBYTE pMem;
	if (pMem = (LPBYTE)KCall((PKFN)GrabFirstPhysPage,1)) {
	    PageFreeCount++; // since we already reserved it
		LogPhysicalPages(PageFreeCount);
		paRet = GetPFN(pMem);
	} else
		paRet = 0;
	DEBUGMSG(ZONE_PHYSMEM,(TEXT("GetHeldPage: Returning %8.8lx\r\n"), paRet));
    return paRet;
}

BOOL HoldPages(int cpNeed, BOOL bForce) {
	BOOL fSetGweOomEvent = FALSE;
	BOOL bRet = FALSE;
	WORD prio;
    EnterPhysCS();
    // Check if this request will drop the page free count below the
    // page out trigger and signal the clean up thread to start doing
    // pageouts if so.
    if ((cpNeed+PageOutTrigger > PageFreeCount) &&
    	(!PageOutNeeded || (PagedInCount > PAGE_OUT_TRIGGER))) {
        PageOutNeeded = 1;
        PagedInCount = 0;
        if (prio = GET_CPRIO(pCurThread))
        	prio--;
        if (prio < GET_CPRIO(pCleanupThread))
	        KCall((PKFN)SetThreadBasePrio, pCleanupThread->hTh, (DWORD)prio);
	    SetEvent(hAlarmThreadWakeup);
    }
    do {
        if (cpNeed+GwesLowThreshold <= PageFreeCount) {
        	DWORD pfc;
        	do {
				pfc = PageFreeCount;
			} while (InterlockedTestExchange(&PageFreeCount,pfc,pfc-cpNeed) != (LONG)pfc);
			LogPhysicalPages(PageFreeCount);
			bRet = TRUE;
			goto hpDone;
        }
    } while (ScavengeStacks(cpNeed+GwesLowThreshold));

	// Even after scavenging stacks, we were unable to satisfy the request
	// without going below the GWE low threshold.

	// Do not allow a request of size GwesLowBlockSize to succeed if
	// doing so would leave less than the low threshold.  Same with
	// GwesCriticalBlockSize and GwesCriticalThreshold.
	if (bForce || !((cpNeed > GwesLowBlockSize
	        && cpNeed+GwesLowThreshold > PageFreeCount)
		    || (cpNeed > GwesCriticalBlockSize
		    && cpNeed + GwesCriticalThreshold > PageFreeCount))) {

      	// Memory is low. Notify GWE, so that GWE can ask
    	// the user to close some apps.
    	if (GwesOOMEvent &&
			((PageFreeCount >= GwesLowThreshold) ||
			 ((PageFreeCount < cpNeed + GwesCriticalThreshold))))
           	fSetGweOomEvent = TRUE;
        
        if ((cpNeed + (bForce?0:STACK_RESERVE)) <= PageFreeCount) {
        	DWORD pfc;
        	do {
				pfc = PageFreeCount;
			} while (InterlockedTestExchange(&PageFreeCount,pfc,pfc-cpNeed) != (LONG)pfc);
			LogPhysicalPages(PageFreeCount);
        	bRet = TRUE;
        }
	}
hpDone:
    LeaveCriticalSection(&PhysCS);
	if (fSetGweOomEvent)
		SetEvent(GwesOOMEvent);
    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);
        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);
    }
}

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) {
	SC_CacheSync(CACHE_SYNC_DISCARD);
    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);
	SC_CacheSync(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) {
	SC_CacheSync(CACHE_SYNC_DISCARD);
    FreePhysPage(GetPFN(pMem));
	InterlockedDecrement(&KInfoTable[KINX_SYSPAGES]);
}

#endif

⌨️ 快捷键说明

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