📄 virtmem.c
字号:
} DEBUGMSG(ZONE_VIRTMEM, (TEXT("Reserved %d pages @%8.8lx\r\n"), cPages, lpvAddress)); if (cNeed) { /* Set unused entries to BAD_PAGE */ DEBUGMSG(ZONE_VIRTMEM, (TEXT("Reserved %d extra pages.\r\n"), -cNeed)); cNeed += PAGES_PER_BLOCK; for (ix = cNeed ; ix < PAGES_PER_BLOCK ; ++ix) pmb->aPages[ix] = BAD_PAGE; } /* If not committing pages, then return the address of the * reserved region */ if (!(fdwAllocationType & MEM_COMMIT)) { LeaveCriticalSection(&VAcs); ERRORMSG(!lpvAddress,(L"Failed VirtualAlloc/reserve of %8.8lx bytes\r\n",cbSize)); CELOG_VirtualAlloc((DWORD)lpvAddress, (DWORD)lpvAddress, cbSize, fdwAllocationType, fdwProtect); return lpvAddress; } } else { /* Not reserving memory, so must be committing. Verify that the * requested region is within range and within an existing reserved * memory region that the client is allowed to access. */ if (cbSize > (1<<VA_SECTION)) goto invalidParm; if (!(fdwAllocationType & MEM_COMMIT) || lpvAddress == 0) goto invalidParm; if ((ulong)lpvAddress>>VA_SECTION > SECTION_MASK) goto invalidParm; pscn = SectionTable[((ulong)lpvAddress>>VA_SECTION) & SECTION_MASK]; if (pscn == NULL_SECTION) goto invalidParm; ixBlock = ((ulong)lpvAddress >> VA_BLOCK) & BLOCK_MASK; /* Adjust lpvAddress to PAGE boundary and calculate the number * of pages to commit. */ lpvAddress = (LPVOID)((ulong)lpvAddress & ~(PAGE_SIZE-1)); cPages = (ulong)(lpbEnd - (LPBYTE)lpvAddress + PAGE_SIZE-1) / PAGE_SIZE; /* locate the starting block of the region */ if ((ixFirB = FindFirstBlock(pscn, ixBlock)) == UNKNOWN_BASE) goto invalidParm; } /* Verify that cPages of memory starting with the first page indicated by * lpvAddress can be committed within the region. * * (pscn) = ptr to section array * (ixBlock) = index of block containing the first page to commit * (cPages) = # of pages to commit */ ixPage = ((ulong)lpvAddress >> VA_PAGE) & PAGE_MASK; cpAlloc = ScanRegion(pscn, ixFirB, ixBlock, ixPage, cPages, 0); if (cpAlloc == -1) goto cleanUp; /* Commit cPages of memory starting with the first page indicated by * lpvAddress. Allocate all required pages before any changes to the * virtual region are performed. * * (pscn) = ptr to section array * (ixBlock) = index of block containing the first page to commit * (cPages) = # of pages to commit * (cpAlloc) = # of physical pages required */ DEBUGMSG(ZONE_VIRTMEM, (TEXT("Allocating %d pages.\r\n"), cpAlloc)); if (!HoldPages(cpAlloc, FALSE)) { err = ERROR_NOT_ENOUGH_MEMORY; goto setError; } ixBlock = (ixBlock*PAGES_PER_BLOCK+ixPage+cPages-1)/PAGES_PER_BLOCK; ix = ((ixPage + cPages - 1) % PAGES_PER_BLOCK) + 1; /* Walk the page tables to map in the physical pages. */ for (; cPages ; --ixBlock) { pmb = (*pscn)[ixBlock]; for (; cPages && ix-- > 0 ; --cPages) { if (pmb->aPages[ix] == 0) { DWORD dwRetries; for (dwRetries = 0; (dwRetries < 20) && !(ulPFN = GetHeldPage()); dwRetries++) Sleep(100); if (ulPFN) { DEBUGMSG(ZONE_VIRTMEM, (TEXT("Mapping %8.8lx @%3.3x%x000 perm=%x\r\n"), ulPFN, ixBlock, ix, ulPgMask)); pmb->aPages[ix] = ulPFN | ulPgMask; } else { InterlockedIncrement(&PageFreeCount); RETAILMSG(1,(L"--->>> VirtualAlloc: FATAL ERROR! COMPLETELY OUT OF MEMORY (%8.8lx)!\r\n",PageFreeCount)); } } else pmb->aPages[ix] = (pmb->aPages[ix] & ~PG_PERMISSION_MASK) | ulPgMask; } ix = PAGES_PER_BLOCK; /* start with last page of previous block */ } InvalidateRange(lpvAddress, cbSize); // in case we changed permissions above LeaveCriticalSection(&VAcs); ERRORMSG(!lpvAddress,(L"Failed VirtualAlloc(%8.8lx) of %8.8lx bytes\r\n",fdwAllocationType,cbSize)); CELOG_VirtualAlloc((DWORD)lpvAddress, (DWORD)lpvAddress, cbSize, fdwAllocationType, fdwProtect); return lpvAddress; /* There was an error reserving or commiting a range of pages. If reserving * pages, release any pages which were reserved before the failure occured. */invalidParm: err = ERROR_INVALID_PARAMETER;setError: DEBUGMSG(ZONE_VIRTMEM, (TEXT("VirtualAlloc failed. error=%d\r\n"), err)); KSetLastError(pCurThread, err);cleanUp: if (fdwAllocationType & MEM_RESERVE && ixFirB != UNKNOWN_BASE) { /* Remove the reservation */ ReleaseRegion(pscn, ixFirB); } LeaveCriticalSection(&VAcs); ERRORMSG(!lpvAddress,(L"Failed VirtualAlloc(%8.8lx) of %8.8lx bytes\r\n",fdwAllocationType,cbSize)); return 0;}BOOL SC_VirtualFree(LPVOID lpvAddress, /* address of region of committed pages */DWORD cbSize, /* size of the region */DWORD fdwFreeType) /* type of free operation */{ int ixBlock; int ixPage; int ixFirB; /* index of first block in region */ PSECTION pscn; int cpReserved; /* # of reserved (not commited) pages in region */ int cpRegion; /* total # of pages in region */ int cPages; /* # of pages to free */ DWORD baseScn; /* base address of section */ BOOL bForceDecommit; /* Verify that the requested region is within range and within an * existing reserved memory region that the client is allowed to * access and locate the starting block of the region. */ bForceDecommit = (fdwFreeType & 0x80000000); fdwFreeType &= ~0x80000000; CELOG_VirtualFree((DWORD)lpvAddress, cbSize, fdwFreeType); DEBUGMSG(ZONE_VIRTMEM, (TEXT("VirtualFree @%8.8lx size=%lx freetype=%lx\r\n"), lpvAddress, cbSize, fdwFreeType)); if (((DWORD)lpvAddress >= FIRST_MAPPER_ADDRESS) && !cbSize && (fdwFreeType == MEM_RELEASE)) { DEBUGMSG(ZONE_VIRTMEM, (TEXT("VirtualFree @%8.8lx size=%lx freetype=%lx : doing HugeVirtualRelease\r\n"), lpvAddress, cbSize, fdwFreeType)); return HugeVirtualRelease(lpvAddress); } /* Lockout other changes to the virtual memory state. */ EnterCriticalSection(&VAcs); if (lpvAddress == 0 || (ulong)lpvAddress>>VA_SECTION > SECTION_MASK) goto invalidParm; pscn = SectionTable[((ulong)lpvAddress>>VA_SECTION) & SECTION_MASK]; if (pscn == NULL_SECTION) goto invalidParm; baseScn = (DWORD)lpvAddress & (SECTION_MASK<<VA_SECTION); ixBlock = ((ulong)lpvAddress >> VA_BLOCK) & BLOCK_MASK; if ((ixFirB = FindFirstBlock(pscn, ixBlock)) == UNKNOWN_BASE) goto invalidParm; /* Verify the status of the region based upon the type of free operation * being performed. * * (pscn) = ptr to section array * (ixBlock) = index of block containing the first page of lpvAddress * (ixFirB) = index of first block in the region */ ixPage = ((ulong)lpvAddress >> VA_PAGE) & PAGE_MASK; if (fdwFreeType == MEM_RELEASE) { DEBUGMSG(ZONE_VIRTMEM, (TEXT("VirtualFree releasing region ixBlock=%x.\r\n"),ixBlock)); if (cbSize != 0 || ixPage != 0 || ixBlock != ixFirB) goto invalidParm; cpReserved = ScanRegion(pscn, ixFirB, ixFirB, 0, (BLOCK_MASK+1)*PAGES_PER_BLOCK, &cpRegion); DEBUGCHK(cpReserved != -1); DEBUGMSG(ZONE_VIRTMEM, (TEXT("VirtualFree: cpReserved=%d cpRegion=%d\r\n"), cpReserved, cpRegion)); /* The entire region must be either reserved or commited. */ if (cpReserved != cpRegion) { if (cpReserved != 0) goto invalidParm; DecommitPages(pscn, ixFirB, 0, cpRegion, baseScn, bForceDecommit); } ReleaseRegion(pscn, ixFirB); LeaveCriticalSection(&VAcs); return TRUE; } else if (fdwFreeType == MEM_DECOMMIT) { DEBUGMSG(ZONE_VIRTMEM, (TEXT("VirtualFree decommitting block %x page %x.\r\n"), ixBlock, ixPage)); if (cbSize == 0) goto invalidParm; cPages = (((ulong)lpvAddress + cbSize + PAGE_SIZE-1) / PAGE_SIZE) - ((ulong)lpvAddress / PAGE_SIZE); cpReserved = ScanRegion(pscn, ixFirB, ixBlock, ixPage, cPages, &cpRegion); if (cpRegion < cPages) goto invalidParm; if (cpReserved != cPages) DecommitPages(pscn, ixBlock, ixPage, cPages, baseScn, bForceDecommit); LeaveCriticalSection(&VAcs); return TRUE; }invalidParm: LeaveCriticalSection(&VAcs); DEBUGMSG(ZONE_VIRTMEM, (TEXT("VirtualFree failed.\r\n"))); KSetLastError(pCurThread, ERROR_INVALID_PARAMETER); return FALSE;}/* @doc INTERNAL @func BOOL | VirtualCopy | Duplicate a virtual memory range (Windows CE Only) @parm LPVOID | lpvDest | address of destination pages @parm LPVOID | lpvSrc | address of source pages @parm DWORD | cbSize | number of bytes to copy @parm DWORD | fdwProtect) | access protection for destination pages @comm Description unavailable at this time.*/BOOL DoVirtualCopy(LPVOID lpvDest, /* address of destination pages */LPVOID lpvSrc, /* address of source pages */DWORD cbSize, /* # of bytes to copy */DWORD fdwProtect) /* access protection for destination pages */{ int ixDestBlk, ixSrcBlk; int ixPage; int ixDestFirB; /* index of first block in destination region */ int ixSrcFirB; /* index of first block in destination region */ PSECTION pscnDest; PSECTION pscnSrc; int cpReserved; /* # of reserved (not commited) pages in region */ int cpRegion; /* total # of pages in region */ int cPages; /* # of pages to copy */ ulong ulPFN; /* page physical frame number */ ulong ulPgMask; BOOL bPhys = FALSE; /* TRUE if mapping physical pages */ /* Verify that the requested regions are within range and within * existing reserved memory regions that the client is allowed to * access and locate the starting block of both regions. */ CELOG_VirtualCopy((DWORD)lpvDest, (DWORD)lpvSrc, cbSize, fdwProtect); DEBUGMSG(ZONE_VIRTMEM, (TEXT("VirtualCopy %8.8lx <= %8.8lx size=%lx prot=%lx\r\n"), lpvDest, lpvSrc, cbSize, fdwProtect)); if (fdwProtect & PAGE_PHYSICAL) { bPhys = TRUE; fdwProtect &= ~PAGE_PHYSICAL; } if ((ulPgMask = MakePagePerms(fdwProtect)) == 0) return FALSE; /* invalid protection flags, error # already set */ /* Lockout other changes to the virtual memory state. */ EnterCriticalSection(&VAcs); /* Validate the destination parameters */ if (!cbSize || !lpvDest || (ulong)lpvDest>>VA_SECTION > SECTION_MASK) goto invalidParm; pscnDest = SectionTable[((ulong)lpvDest>>VA_SECTION) & SECTION_MASK]; if (pscnDest == NULL_SECTION) goto invalidParm; ixDestBlk = ((ulong)lpvDest >> VA_BLOCK) & BLOCK_MASK; ixDestFirB = FindFirstBlock(pscnDest, ixDestBlk); if (ixDestFirB == UNKNOWN_BASE) goto invalidParm; /* Verify that all of the destination pages are reserved (not committed). */ ixPage = ((ulong)lpvDest >> VA_PAGE) & PAGE_MASK; cPages = (((ulong)lpvDest + cbSize + PAGE_SIZE-1) / PAGE_SIZE) - ((ulong)lpvDest / PAGE_SIZE); cpReserved = ScanRegion(pscnDest, ixDestFirB, ixDestBlk, ixPage, cPages, 0); if (cpReserved != cPages) goto invalidParm; /* Validate the source address parameters */ if (bPhys) { ulPFN = PFNfrom256(lpvSrc); if (((ulong)lpvDest&(PAGE_SIZE-1)) != ((ulong)lpvSrc<<8 &(PAGE_SIZE-1))) goto invalidParm; } else if ((ulong)lpvSrc>>VA_SECTION > SECTION_MASK) { /* Mapping pages from a physical region. */ bPhys = TRUE; ulPFN = GetPFN(lpvSrc); if (((ulong)lpvDest&(PAGE_SIZE-1)) != ((ulong)lpvSrc&(PAGE_SIZE-1))) goto invalidParm; } else { /* Mapping pages from another virtual region. */ bPhys = FALSE; if (lpvSrc == 0 || ((ulong)lpvDest&0xFFFFL) != ((ulong)lpvSrc&0xFFFFL)) goto invalidParm; pscnSrc = SectionTable[((ulong)lpvSrc>>VA_SECTION) & SECTION_MASK]; if (pscnSrc == NULL_SECTION) goto invalidParm; ixSrcBlk = ((ulong)lpvSrc >> VA_BLOCK) & BLOCK_MASK; ixSrcFirB = FindFirstBlock(pscnSrc, ixSrcBlk); if (ixSrcFirB == UNKNOWN_BASE) goto invalidParm; /* Verify that all of the source pages are committed */ cpReserved = ScanRegion(pscnSrc, ixSrcFirB, ixSrcBlk, ixPage, cPages, &cpRegion); if (cpReserved || cpRegion != cPages) goto invalidParm; } /* Walk the the page tables mapping the pages in the source region into * the destination region. */ for (; cPages > 0 ; ++ixDestBlk, ++ixSrcBlk) { MEMBLOCK *pmbSrc; MEMBLOCK *pmbDest = (*pscnDest)[ixDestBlk]; if (!bPhys) pmbSrc = (*pscnSrc)[ixSrcBlk]; if (!bPhys && ixDestFirB == ixSrcFirB && ixPage == 0 && (cPages >= PAGES_PER_BLOCK || pmbSrc->aPages[cPages] == BAD_PAGE) && (pmbSrc->aPages[0]&PG_PERMISSION_MASK) == ulPgMask) { /* Copying an entire block with the same access permissions into * the same offset within the two sections. Share the same MEMBLOCK * by bumping the use count on the MEMBLOCK. */ DEBUGCHK(pmbDest != NULL_BLOCK && pmbDest != RESERVED_BLOCK); FreeMem(pmbDest,HEAP_MEMBLOCK); ++pmbSrc->cUses; AddAccess(&pmbSrc->alk, pCurProc->aky); (*pscnDest)[ixDestBlk] = pmbSrc; cPages -= PAGES_PER_BLOCK;#if defined(SH4) && (PAGE_SIZE==4096) } else if (bPhys && !ixPage && !(ixDestBlk & 15) && !(ulPFN&1048575) && (cPages >= 256)) { int loop, loop2; DWORD dwSetting = ulPgMask | PG_1M_MASK; for (loop = 0; loop < 16; loop++) { pmbDest = (*pscnDest)[ixDestBlk+loop]; for (loop2 = 0; loop2 < 16; loop2++) { pmbDest->aPages[loop2] = dwSetting | ulPFN; ulPFN = NextPFN(ulPFN); } } cPages-=256; ixDestBlk+=15;#endif } else { for ( ; cPages && ixPage < PAGES_PER_BLOCK ; ++ixPage, --cPages) { if (bPhys) { DEBUGMSG(ZONE_VIRTMEM, (TEXT("Mapping physical page %8.8lx @%3.3x%x000 perm=%x\r\n"), ulPFN, ixDestBlk, ixPage, ulPgMask));#if 0#if defined(SH3) && (PAGE_SIZE==1024) if (!(ixPage&3) && !(ulPFN&4095) && (cPages >= 4)) { int loop;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -