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

📄 pgpool.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
                        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 + -