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

📄 pgpool.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//------------------------------------------------------------------------------
// 
//      NK Kernel loader code
// 
// 
// Module Name:
// 
//      pgpool.c
// 
// Abstract:
// 
//      This file implements fixed-size paging pool
// 
// 
//------------------------------------------------------------------------------
//
// The loader is derived from the Win32 executable file format spec.  The only
// interesting thing is how we load a process.  When we load a process, we
// simply schedule a thread in a new process context.  That thread (in coredll)
// knows how to read in an executable, and does so.  Then it traps into the kernel
// and starts running in the new process.  Most of the code below is simply a direct
// implimentation of the executable file format specification
//
//------------------------------------------------------------------------------

#include "kernel.h"

#define MIN_PGPOOL_SIZE     (64*PAGE_SIZE)          // minimum paging pool size 256K

// uncomment the following line to debug PAGING POOL
// #define DEBUG_PAGING_POOL

#ifdef DEBUG_PAGING_POOL
#undef  ZONE_PAGING
#define ZONE_PAGING     1
#endif

//
// the paging pool entry
//
// NOTE: we use index instead of direct pointer becuase we want to keep the size of this entry of 
//       size 16 byte. Allocation and cache is better utilized this way.
//
typedef struct _PagingPoolEntry {
    WORD idxPrev;       // index to the previous entry
    WORD idxNext;       // index to the next entry
    WORD idxNextInMod;  // index to the next entry of the same MOD/PROC
    WORD pad;           // padding
    DWORD va;           // VA of the page
    LPVOID pModProc;    // pointer to MODULE/PROC that owns this page
} PAGINGPOOL, *PPAGINGPOOL;


// the size of the paging pool. Defualt 0, which uses unlimited paging pool
DWORD cbNKPagingPoolSize = (DWORD) -1;

static LPBYTE gpPagingPool;             // the paging memory pool
static PPAGINGPOOL gpPoolArr;           // the paging pool structure array
static LONG gnFreePages;                // total number of free pages
static WORD gidxFree;                   // index of the head of the free list
static WORD gidxHead;                   // head of the used list (circular)

extern CRITICAL_SECTION PagerCS, VAcs;  // the pager critical section

#define FREE_PAGE_VA        0xabababab

BOOL InitPgPool (void)
{
    int i;

#ifdef DEBUG_PAGING_POOL
    cbNKPagingPoolSize = MIN_PGPOOL_SIZE;
#endif

    // treat -1 as 0
    if ((DWORD) -1 == cbNKPagingPoolSize) {
        cbNKPagingPoolSize = 0;
    }

    // do nothing if not using paging pool
    if (!cbNKPagingPoolSize) {
        return TRUE;
    }

    // adjust to min/max, align to page size
    if (cbNKPagingPoolSize < MIN_PGPOOL_SIZE) {
        cbNKPagingPoolSize = MIN_PGPOOL_SIZE;
    } else {
        cbNKPagingPoolSize = PAGEALIGN_UP(cbNKPagingPoolSize);
    }

    // initially all pages are free
    gnFreePages = (cbNKPagingPoolSize / PAGE_SIZE);

    // make sure we don't have too many pages that we can account for
    if ((DWORD)gnFreePages >= (DWORD) INVALID_PG_INDEX) {
        gnFreePages = INVALID_PG_INDEX - 1;
        cbNKPagingPoolSize = gnFreePages * PAGE_SIZE;
    }

    // total memory needed == PAGE_ALIGN_UP(gnFreePages * sizeof (PAGINGPOOL)) + cbNKPagingPoolSize, carve it from the begining of free RAM
    gpPagingPool = (LPBYTE) (pTOC->ulRAMFree + MemForPT);
    MemForPT += cbNKPagingPoolSize + PAGEALIGN_UP(gnFreePages * sizeof (PAGINGPOOL));
    gpPoolArr = (PPAGINGPOOL) (gpPagingPool + cbNKPagingPoolSize);

    DEBUGMSG (1, (L"Using Paging Pool, size = 0x%8.8lx, Addr = 0x%8.8lx, gpPoolArr = 0x%8.8lx\r\n", cbNKPagingPoolSize, gpPagingPool, gpPoolArr));

    // initialize the free list
    for (i = 0; i < gnFreePages; i ++) {
        gpPoolArr[i].idxNext = (WORD) (i+1);
#ifdef DEBUG
        gpPoolArr[i].va = FREE_PAGE_VA;
        gpPoolArr[i].pModProc = (LPVOID) 0xabababab;
        gpPoolArr[i].idxPrev = INVALID_PG_INDEX;
        gpPoolArr[i].idxNextInMod = INVALID_PG_INDEX;
#endif
    }

    // take care of 'next' of the last element
    gpPoolArr[gnFreePages-1].idxNext = INVALID_PG_INDEX;

    gidxHead = INVALID_PG_INDEX;

    return TRUE;
}


_inline WORD pg_dequeue (PPGPOOL_Q ppq)
{
    WORD idx = ppq->idxHead;
    if (INVALID_PG_INDEX != idx)
        ppq->idxHead = gpPoolArr[idx].idxNextInMod;
    return idx;
}

_inline void pg_enqueue (PPGPOOL_Q ppq, WORD idx)
{
    DEBUGCHK (INVALID_PG_INDEX != idx);
    gpPoolArr[idx].idxNextInMod = INVALID_PG_INDEX;

    if (INVALID_PG_INDEX == ppq->idxHead) {
        // queue was empty
        ppq->idxHead = idx;
    } else {
        DEBUGCHK (INVALID_PG_INDEX != ppq->idxTail);
        gpPoolArr[ppq->idxTail].idxNextInMod = idx;
    }
    ppq->idxTail = idx;
}

_inline void pg_AddToUsedPage (WORD idx)
{
    if (INVALID_PG_INDEX == gidxHead) {
        gpPoolArr[idx].idxNext = gpPoolArr[idx].idxPrev = gidxHead = idx;
    } else {
        WORD idxPrev = gpPoolArr[gidxHead].idxPrev;
        gpPoolArr[idx].idxNext = gidxHead;
        gpPoolArr[idx].idxPrev = idxPrev;
        gpPoolArr[gidxHead].idxPrev = gpPoolArr[idxPrev].idxNext = idx;
    }
}

_inline void pg_RemoveFromUsedPage (WORD idx)
{
    DEBUGCHK (INVALID_PG_INDEX != idx);
    if (gpPoolArr[idx].idxNext == idx) {
        // last page
        DEBUGCHK ((idx == gidxHead) && (idx == gpPoolArr[idx].idxPrev));
        gidxHead = INVALID_PG_INDEX;
    } else {
        WORD idxPrev = gpPoolArr[idx].idxPrev;
        WORD idxNext = gpPoolArr[idx].idxNext;
        gpPoolArr[idxPrev].idxNext = idxNext;
        gpPoolArr[idxNext].idxPrev = idxPrev;
        if (gidxHead == idx)
            gidxHead = idxNext;
    }
}

static BOOL TryInvalidateAddr (DWORD dwAddr, DWORD dwInUseOrig)
{
    PSECTION pscn;
    MEMBLOCK *pmbMaster;
    DWORD   dwZeroAddr = ZeroPtr(dwAddr);
    int     ixBlock = (dwAddr >> VA_BLOCK) & BLOCK_MASK;
    int     ixPage = (dwAddr >> VA_PAGE) & PAGE_MASK;
    DWORD   dwEntry = 0;

    DEBUGCHK (!IsKernelVa (dwAddr));

    EnterCriticalSection (&VAcs);
    DEBUGMSG(ZONE_PAGING,(L"TryInvalidateAddr: dwAddr = %8.8lx, dwInUseOrig = %8.8lx\r\n", dwAddr, dwInUseOrig));

    // find the right section based on address
    if (dwZeroAddr >= (DWORD) DllLoadBase) {
        // DLL's address
        DEBUGCHK ((dwZeroAddr >= (DWORD) DllLoadBase) && !(dwInUseOrig & 1));
        pscn = (dwZeroAddr < (1 << VA_SECTION))? &NKSection : SectionTable[dwZeroAddr >> VA_SECTION];
    } else {
        // Process address or memory mapped area
        DEBUGCHK (!dwInUseOrig);
        pscn = SectionTable[dwAddr >> VA_SECTION];
    }

    pmbMaster = (*pscn)[ixBlock];
    if (!pmbMaster || (NULL_BLOCK == pmbMaster) || (RESERVED_BLOCK == pmbMaster) || !pmbMaster->aPages[ixPage]) {
        // the page has already freed. just return TRUE
        LeaveCriticalSection (&VAcs);
        return TRUE;
    }

    // we can only page it out if it's not locked
    if (!pmbMaster->cLocks) {

        dwEntry = pmbMaster->aPages[ixPage];

        DEBUGCHK (dwEntry);

        // if it's the old style DLL, need to make sure the page is not locked in any process
        if (dwInUseOrig && (dwZeroAddr < (1 << VA_SECTION))) {
            int i;
            MEMBLOCK *pmb;
            DWORD dwInUse;
            // make sure no page is locked.
            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) && pmb->cLocks) {
                        // page is locked, can't page this one out
                        dwEntry = 0;

⌨️ 快捷键说明

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