📄 pgpool.c
字号:
break;
}
}
}
if (dwEntry) {
// page isn't locked. Page it out
for (i = 1, dwInUse = dwInUseOrig; dwInUse; i ++) {
DEBUGCHK (i < MAX_PROCESSES);
if (dwInUse & (1 << i)) {
dwInUse &= ~(1 << i);
pmb = (*(SectionTable[i+1]))[ixBlock];
DEBUGCHK (NULL_BLOCK != pmb);
if (RESERVED_BLOCK != pmb) {
DEBUGCHK (!pmb->aPages[ixPage] || ((pmb->aPages[ixPage] & -PAGE_SIZE) == (dwEntry & -PAGE_SIZE)));
pmb->aPages[ixPage] = 0;
#if HARDWARE_PT_PER_PROC
// after we updated all platforms to support single entry TLB flush,
// we'll do the same for all CPUs
InvalidateRange (MapPtrProc(dwZeroAddr, ProcArray + i), PAGE_SIZE);
#endif
}
}
}
}
}
// update the common part (process, shared, or secure slot)
if (dwEntry) {
OEMCacheRangeFlush (MapPtrProc(dwZeroAddr, ProcArray), PAGE_SIZE, CACHE_SYNC_INSTRUCTIONS);
pmbMaster->aPages[ixPage] = 0;
}
}
LeaveCriticalSection (&VAcs);
DEBUGMSG (!dwEntry && ZONE_PAGING, (L"TryInvalidateAddr: dwAddr (%8.8lx) locked.\r\n", dwAddr));
if (dwEntry) {
// We're counting on Invalidate Range for anything other than x86 will flush the TLB.
// MUST update this if we decided to do range flush on TLB for other CPUs
InvalidateRange ((LPVOID) dwAddr, PAGE_SIZE);
return TRUE;
}
return FALSE;
}
static WORD PageOutPage (void)
{
WORD idxEntry, idxOrig = gidxHead;
DWORD va, dwInuse;
PPGPOOL_Q ppq;
DEBUGCHK (!gnFreePages && (INVALID_PG_INDEX != gidxHead));
//
// try to find a page that we can page it out (can't page it out if it's locked).
//
do {
// always start from head pointer as it'll be updated on every loop
idxEntry = gidxHead;
va = gpPoolArr[idxEntry].va;
// advance the head pointer
gidxHead = gpPoolArr[idxEntry].idxNext;
DEBUGCHK (INVALID_PG_INDEX != gidxHead);
DEBUGMSG (ZONE_PAGING, (L"PageOutPage: Trying paging out entry %8.8lx, va = %8.8lx\r\n", idxEntry, va));
if (ZeroPtr (va) < (DWORD) DllLoadBase) {
// process
ppq = &((PPROCESS) gpPoolArr[idxEntry].pModProc)->pgqueue;
dwInuse = 0;
} else if ((va >= FIRST_MAPPER_ADDRESS) && (va < LAST_MAPPER_ADDRESS)) {
// memory mapped file
ppq = &((LPFSMAP) gpPoolArr[idxEntry].pModProc)->pgqueue;
dwInuse = 0;
} else {
// module
PMODULE pMod = (PMODULE) gpPoolArr[idxEntry].pModProc;
ppq = &pMod->pgqueue;
dwInuse = pMod->inuse;
}
DEBUGCHK (idxEntry == ppq->idxHead);
// remove the entry from the page owned by the process/module
pg_dequeue (ppq);
// try to remove the page entry from VM
if (TryInvalidateAddr (va, dwInuse)) {
// successfully paged out the page, remove it from the used list and return the entry
pg_RemoveFromUsedPage (idxEntry);
#ifdef DEBUG
{
LPCWSTR pszName;
if (ZeroPtr (va) < (DWORD) DllLoadBase) {
pszName = L"Process";
} else if ((va >= FIRST_MAPPER_ADDRESS) && (va < LAST_MAPPER_ADDRESS)) {
pszName = L"MapFile";
} else {
pszName = L"Module";
}
gpPoolArr[idxEntry].va = FREE_PAGE_VA;
DEBUGMSG (ZONE_PAGING, (L"PageOutPage: Paged out page at %8.8lx, in %s %8.8lx\r\n",
va, pszName, gpPoolArr[idxEntry].pModProc));
}
#endif
return idxEntry;
}
// the page is locked, link it back to the end of the list owned by the process/module
pg_enqueue (ppq, idxEntry);
} while (gidxHead != idxOrig);
// we've exhausted the paging pool and can't find a page to page out.
// fail the request.
DEBUGMSG (1, (L"PageOutPage: ALL PAGES IN PAGING POOL ARE LOCKED\r\n"));
return INVALID_PG_INDEX;
}
static WORD GetFreePage (void)
{
WORD idxEntry;
DEBUGCHK ((gnFreePages > 0) && (INVALID_PG_INDEX != gidxFree) && IsKernelVa (gpPoolArr[gidxFree].va));
idxEntry = gidxFree;
gidxFree = gpPoolArr[gidxFree].idxNext;
-- gnFreePages;
DEBUGCHK (gnFreePages || (INVALID_PG_INDEX == gidxFree));
DEBUGMSG (ZONE_PAGING, (L"GetFreePage: Got free page at index %8.8lx, va = %8.8lx\r\n", idxEntry, gpPoolArr[idxEntry].va));
return idxEntry;
}
LPBYTE GetPagingPage (PPGPOOL_Q ppq, o32_lite *optr, BYTE filetype, WORD *pidx)
{
if (!cbNKPagingPoolSize // no paging pool
|| (optr // not memory mapped file
&& ((optr->o32_flags & (IMAGE_SCN_MEM_WRITE|IMAGE_SCN_MEM_NOT_PAGED)) // not read only or not pageable
|| ((FA_XIP & filetype) && !(optr->o32_flags & IMAGE_SCN_COMPRESSED)))) // XIP-able and not compressed
) {
DEBUGMSG (cbNKPagingPoolSize && ZONE_PAGING,
(L"GetPagingPage: Not using paging pool (filetype = %d, o32_flags = %8.8lx)\r\n", filetype, optr->o32_flags));
return NULL;
}
DEBUGCHK (PagerCS.OwnerThread == hCurThread);
DEBUGCHK ((gnFreePages > 0) || (INVALID_PG_INDEX == gidxFree));
// grab a page either from the free list or page out a page
*pidx = gnFreePages? GetFreePage () : PageOutPage ();
if (INVALID_PG_INDEX == *pidx) {
// ALL PAGES LOCKED!!
DEBUGCHK (0);
return NULL;
}
DEBUGCHK (FREE_PAGE_VA == gpPoolArr[*pidx].va);
DEBUGMSG (ZONE_PAGING, (L"GetPagingPage: Found page (va = %8.8lx, *pidx = %8.8lx)\r\n",
gpPagingPool + (((DWORD) *pidx) << VA_PAGE), *pidx));
return gpPagingPool + (((DWORD) *pidx) << VA_PAGE);
}
void AddPageToFreeList (WORD idx)
{
DEBUGCHK (PagerCS.OwnerThread == hCurThread);
DEBUGCHK (FREE_PAGE_VA == gpPoolArr[idx].va);
gpPoolArr[idx].idxNext = gidxFree;
gidxFree = idx;
gnFreePages ++;
DEBUGMSG (ZONE_PAGING, (L"AddPageToFreeList: (idx = %8.8lx)\r\n", idx));
}
void AddPageToQueue (PPGPOOL_Q ppq, WORD idx, DWORD vaddr, LPVOID pModProc)
{
DWORD zaddr = ZeroPtr (vaddr);
DEBUGCHK (PagerCS.OwnerThread == hCurThread);
DEBUGCHK (FREE_PAGE_VA == gpPoolArr[idx].va);
// for Modules, uses the secure slot address
if (zaddr >= (DWORD) DllLoadBase)
vaddr = (DWORD) MapPtrProc (zaddr, ProcArray);
// now the page is used for the new user mode va
gpPoolArr[idx].va = vaddr;
gpPoolArr[idx].pModProc = pModProc;
// add the entry to the used list
pg_AddToUsedPage (idx);
// add the entry to the process/module's owned list
pg_enqueue (ppq, idx);
#ifdef DEBUG
{
LPCWSTR pszName;
if (zaddr < (DWORD) DllLoadBase) {
pszName = L"Process";
} else if ((zaddr >= FIRST_MAPPER_ADDRESS) && (zaddr < LAST_MAPPER_ADDRESS)) {
pszName = L"MapFile";
} else {
pszName = L"Module";
}
DEBUGMSG (ZONE_PAGING, (L"AddPageToQueue: add entry %8.8lx (%8.8lx) to %s %8.8lx owned list\r\n",
idx, vaddr, pszName, pModProc));
}
#endif
}
void FreeAllPagesFromQ (PPGPOOL_Q ppq)
{
WORD idx;
EnterCriticalSection (&PagerCS);
while (INVALID_PG_INDEX != (idx = pg_dequeue (ppq))) {
// remove from the used list
pg_RemoveFromUsedPage (idx);
DEBUGCHK (gpPoolArr[idx].va != FREE_PAGE_VA);
#ifdef DEBUG
gpPoolArr[idx].va = FREE_PAGE_VA;
#endif
// add to free list
AddPageToFreeList (idx);
}
LeaveCriticalSection (&PagerCS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -