mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 23:25:45 +00:00
Virtual memory support
svn path=/trunk/; revision=2462
This commit is contained in:
parent
02e3483cf5
commit
a155c42316
26 changed files with 1154 additions and 787 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: fmutex.c,v 1.2 2001/12/20 03:56:08 dwelch Exp $
|
/* $Id: fmutex.c,v 1.3 2001/12/31 01:53:44 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -35,9 +35,19 @@ ExReleaseFastMutex (PFAST_MUTEX FastMutex)
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN FASTCALL
|
BOOLEAN FASTCALL
|
||||||
ExTryToAcquireFastMutex (PFAST_MUTEX FastMutex)
|
ExTryToAcquireFastMutex (PFAST_MUTEX FastMutex)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
KeEnterCriticalRegion();
|
||||||
|
if (InterlockedExchange(&FastMutex->Count, 0) == 1)
|
||||||
|
{
|
||||||
|
FastMutex->Owner = KeGetCurrentThread();
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $Id: Makefile,v 1.59 2001/12/27 23:56:41 dwelch Exp $
|
# $Id: Makefile,v 1.60 2001/12/31 01:53:44 dwelch Exp $
|
||||||
#
|
#
|
||||||
# ReactOS Operating System
|
# ReactOS Operating System
|
||||||
#
|
#
|
||||||
|
@ -150,7 +150,8 @@ OBJECTS_MM = \
|
||||||
mm/kmap.o \
|
mm/kmap.o \
|
||||||
mm/mpw.o \
|
mm/mpw.o \
|
||||||
mm/pageop.o \
|
mm/pageop.o \
|
||||||
mm/balance.o
|
mm/balance.o \
|
||||||
|
mm/rmap.o
|
||||||
|
|
||||||
# I/O Subsystem (Io)
|
# I/O Subsystem (Io)
|
||||||
OBJECTS_IO = \
|
OBJECTS_IO = \
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: view.c,v 1.31 2001/12/29 14:32:21 dwelch Exp $
|
/* $Id: view.c,v 1.32 2001/12/31 01:53:44 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -62,14 +62,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
/* TYPES *********************************************************************/
|
|
||||||
|
|
||||||
typedef struct _CC_FREE_CONTEXT
|
|
||||||
{
|
|
||||||
DWORD Maximum;
|
|
||||||
PVOID* FreedPages;
|
|
||||||
} CC_FREE_CONTEXT, *PCC_FREE_CONTEXT;
|
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
|
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
|
||||||
|
@ -85,17 +77,16 @@ static LIST_ENTRY CacheSegmentLRUListHead;
|
||||||
static FAST_MUTEX ViewLock;
|
static FAST_MUTEX ViewLock;
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
CcRosInternalFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg, PVOID Context);
|
CcRosInternalFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg);
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed, PVOID* FreedPages)
|
CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY current_entry;
|
PLIST_ENTRY current_entry;
|
||||||
PCACHE_SEGMENT current;
|
PCACHE_SEGMENT current;
|
||||||
ULONG PagesPerSegment;
|
ULONG PagesPerSegment;
|
||||||
CC_FREE_CONTEXT FreeContext;
|
|
||||||
ULONG PagesFreed;
|
ULONG PagesFreed;
|
||||||
|
|
||||||
DPRINT("CcRosTrimCache(Target %d)\n", Target);
|
DPRINT("CcRosTrimCache(Target %d)\n", Target);
|
||||||
|
@ -117,13 +108,10 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed, PVOID* FreedPages)
|
||||||
ExReleaseFastMutex(¤t->Lock);
|
ExReleaseFastMutex(¤t->Lock);
|
||||||
DPRINT("current->Bcb->CacheSegmentSize %d\n", current->Bcb->CacheSegmentSize);
|
DPRINT("current->Bcb->CacheSegmentSize %d\n", current->Bcb->CacheSegmentSize);
|
||||||
PagesPerSegment = current->Bcb->CacheSegmentSize / PAGESIZE;
|
PagesPerSegment = current->Bcb->CacheSegmentSize / PAGESIZE;
|
||||||
FreeContext.Maximum = min(PagesPerSegment, Target);
|
CcRosInternalFreeCacheSegment(current->Bcb, current);
|
||||||
FreeContext.FreedPages = FreedPages;
|
|
||||||
CcRosInternalFreeCacheSegment(current->Bcb, current, (PVOID)&FreeContext);
|
|
||||||
DPRINT("CcRosTrimCache(): Freed %d\n", PagesPerSegment);
|
DPRINT("CcRosTrimCache(): Freed %d\n", PagesPerSegment);
|
||||||
PagesFreed = min(PagesPerSegment, Target);
|
PagesFreed = min(PagesPerSegment, Target);
|
||||||
Target = Target - PagesFreed;
|
Target = Target - PagesFreed;
|
||||||
FreedPages = FreedPages + PagesFreed;
|
|
||||||
(*NrFreed) = (*NrFreed) + PagesFreed;
|
(*NrFreed) = (*NrFreed) + PagesFreed;
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&ViewLock);
|
ExReleaseFastMutex(&ViewLock);
|
||||||
|
@ -159,6 +147,80 @@ CcRosReleaseCacheSegment(PBCB Bcb,
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PCACHE_SEGMENT CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY current_entry;
|
||||||
|
PCACHE_SEGMENT current;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||||
|
current_entry = Bcb->BcbSegmentListHead.Flink;
|
||||||
|
while (current_entry != &Bcb->BcbSegmentListHead)
|
||||||
|
{
|
||||||
|
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
||||||
|
BcbSegmentListEntry);
|
||||||
|
if (current->FileOffset <= FileOffset &&
|
||||||
|
(current->FileOffset + Bcb->CacheSegmentSize) > FileOffset)
|
||||||
|
{
|
||||||
|
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||||
|
return(current);
|
||||||
|
}
|
||||||
|
current_entry = current_entry->Flink;
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CcRosSuggestFreeCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty)
|
||||||
|
{
|
||||||
|
PCACHE_SEGMENT CacheSeg;
|
||||||
|
|
||||||
|
ExAcquireFastMutex(&ViewLock);
|
||||||
|
CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
|
||||||
|
if (CacheSeg == NULL)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
ExAcquireFastMutex(&CacheSeg->Lock);
|
||||||
|
if (CacheSeg->MappedCount > 0)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
CacheSeg->Dirty = CacheSeg->Dirty || NowDirty;
|
||||||
|
if (CacheSeg->Dirty || CacheSeg->ReferenceCount > 0)
|
||||||
|
{
|
||||||
|
ExReleaseFastMutex(&CacheSeg->Lock);
|
||||||
|
ExReleaseFastMutex(&ViewLock);
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
ExReleaseFastMutex(&CacheSeg->Lock);
|
||||||
|
CcRosInternalFreeCacheSegment(CacheSeg->Bcb, CacheSeg);
|
||||||
|
ExReleaseFastMutex(&ViewLock);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty)
|
||||||
|
{
|
||||||
|
PCACHE_SEGMENT CacheSeg;
|
||||||
|
|
||||||
|
ExAcquireFastMutex(&ViewLock);
|
||||||
|
CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
|
||||||
|
if (CacheSeg == NULL)
|
||||||
|
{
|
||||||
|
ExReleaseFastMutex(&ViewLock);
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
CacheSeg->ReferenceCount++;
|
||||||
|
ExReleaseFastMutex(&ViewLock);
|
||||||
|
ExAcquireFastMutex(&CacheSeg->Lock);
|
||||||
|
CacheSeg->MappedCount--;
|
||||||
|
CacheSeg->Dirty = CacheSeg->Dirty || NowDirty;
|
||||||
|
ExReleaseFastMutex(&CacheSeg->Lock);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CcRosGetCacheSegment(PBCB Bcb,
|
CcRosGetCacheSegment(PBCB Bcb,
|
||||||
ULONG FileOffset,
|
ULONG FileOffset,
|
||||||
|
@ -167,7 +229,6 @@ CcRosGetCacheSegment(PBCB Bcb,
|
||||||
PBOOLEAN UptoDate,
|
PBOOLEAN UptoDate,
|
||||||
PCACHE_SEGMENT* CacheSeg)
|
PCACHE_SEGMENT* CacheSeg)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY current_entry;
|
|
||||||
PCACHE_SEGMENT current;
|
PCACHE_SEGMENT current;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -181,33 +242,26 @@ CcRosGetCacheSegment(PBCB Bcb,
|
||||||
/*
|
/*
|
||||||
* Look for a cache segment already mapping the same data.
|
* Look for a cache segment already mapping the same data.
|
||||||
*/
|
*/
|
||||||
current_entry = Bcb->BcbSegmentListHead.Flink;
|
current = CcRosLookupCacheSegment(Bcb, FileOffset);
|
||||||
while (current_entry != &Bcb->BcbSegmentListHead)
|
if (current != NULL)
|
||||||
{
|
{
|
||||||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
/*
|
||||||
BcbSegmentListEntry);
|
* Make sure the cache segment can't go away outside of our control.
|
||||||
if (current->FileOffset <= FileOffset &&
|
*/
|
||||||
(current->FileOffset + Bcb->CacheSegmentSize) > FileOffset)
|
current->ReferenceCount++;
|
||||||
{
|
/*
|
||||||
/*
|
* Release the global lock and lock the cache segment.
|
||||||
* Make sure the cache segment can't go away outside of our control.
|
*/
|
||||||
*/
|
ExReleaseFastMutex(&ViewLock);
|
||||||
current->ReferenceCount++;
|
ExAcquireFastMutex(¤t->Lock);
|
||||||
/*
|
/*
|
||||||
* Release the global lock and lock the cache segment.
|
* Return information about the segment to the caller.
|
||||||
*/
|
*/
|
||||||
ExReleaseFastMutex(&ViewLock);
|
*UptoDate = current->Valid;
|
||||||
ExAcquireFastMutex(¤t->Lock);
|
*BaseAddress = current->BaseAddress;
|
||||||
/*
|
*CacheSeg = current;
|
||||||
* Return information about the segment to the caller.
|
*BaseOffset = current->FileOffset;
|
||||||
*/
|
return(STATUS_SUCCESS);
|
||||||
*UptoDate = current->Valid;
|
|
||||||
*BaseAddress = current->BaseAddress;
|
|
||||||
*CacheSeg = current;
|
|
||||||
*BaseOffset = current->FileOffset;
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
current_entry = current_entry->Flink;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -302,26 +356,17 @@ CcRosRequestCacheSegment(PBCB Bcb,
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC VOID
|
STATIC VOID
|
||||||
CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr)
|
CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
|
||||||
|
BOOLEAN Dirty)
|
||||||
{
|
{
|
||||||
PCC_FREE_CONTEXT FreeContext = (PCC_FREE_CONTEXT)Context;
|
|
||||||
ULONG Offset = (Address - MemoryArea->BaseAddress) / PAGESIZE;
|
|
||||||
if (PhysAddr != 0)
|
if (PhysAddr != 0)
|
||||||
{
|
{
|
||||||
if (Context == NULL || Offset >= FreeContext->Maximum)
|
MmReleasePageMemoryConsumer(MC_CACHE, (PVOID)PhysAddr);
|
||||||
{
|
|
||||||
MmReleasePageMemoryConsumer(MC_CACHE, (PVOID)PhysAddr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("Address %X Offset %d PhysAddr %X\n", Address, Offset, PhysAddr);
|
|
||||||
FreeContext->FreedPages[Offset] = (PVOID)PhysAddr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
CcRosInternalFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg, PVOID Context)
|
CcRosInternalFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Releases a cache segment associated with a BCB
|
* FUNCTION: Releases a cache segment associated with a BCB
|
||||||
*/
|
*/
|
||||||
|
@ -335,7 +380,7 @@ CcRosInternalFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg, PVOID Context)
|
||||||
CacheSeg->BaseAddress,
|
CacheSeg->BaseAddress,
|
||||||
Bcb->CacheSegmentSize,
|
Bcb->CacheSegmentSize,
|
||||||
CcFreeCachePage,
|
CcFreeCachePage,
|
||||||
Context);
|
NULL);
|
||||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||||
ExFreePool(CacheSeg);
|
ExFreePool(CacheSeg);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
|
@ -346,7 +391,7 @@ CcRosFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ExAcquireFastMutex(&ViewLock);
|
ExAcquireFastMutex(&ViewLock);
|
||||||
Status = CcRosInternalFreeCacheSegment(Bcb, CacheSeg, NULL);
|
Status = CcRosInternalFreeCacheSegment(Bcb, CacheSeg);
|
||||||
ExReleaseFastMutex(&ViewLock);
|
ExReleaseFastMutex(&ViewLock);
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#ifndef __INCLUDE_INTERNAL_CC_H
|
#ifndef __INCLUDE_INTERNAL_CC_H
|
||||||
#define __INCLUDE_INTERNAL_CC_H
|
#define __INCLUDE_INTERNAL_CC_H
|
||||||
/* $Id: cc.h,v 1.8 2001/12/29 14:32:22 dwelch Exp $ */
|
/* $Id: cc.h,v 1.9 2001/12/31 01:53:44 dwelch Exp $ */
|
||||||
#include <ddk/ntifs.h>
|
#include <ddk/ntifs.h>
|
||||||
|
|
||||||
typedef struct _BCB
|
typedef struct _BCB
|
||||||
|
@ -62,5 +62,9 @@ NTSTATUS ReadCacheSegment(PCACHE_SEGMENT CacheSeg);
|
||||||
NTSTATUS WriteCacheSegment(PCACHE_SEGMENT CacheSeg);
|
NTSTATUS WriteCacheSegment(PCACHE_SEGMENT CacheSeg);
|
||||||
|
|
||||||
VOID CcInit(VOID);
|
VOID CcInit(VOID);
|
||||||
|
NTSTATUS
|
||||||
|
CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty);
|
||||||
|
NTSTATUS
|
||||||
|
CcRosSuggestFreeCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
/* TYPES *********************************************************************/
|
/* TYPES *********************************************************************/
|
||||||
|
|
||||||
struct _EPROCESS;
|
struct _EPROCESS;
|
||||||
|
|
||||||
|
struct _MM_RMAP_ENTRY;
|
||||||
|
struct _MM_PAGEOP;
|
||||||
typedef ULONG SWAPENTRY;
|
typedef ULONG SWAPENTRY;
|
||||||
|
|
||||||
#define MEMORY_AREA_INVALID (0)
|
#define MEMORY_AREA_INVALID (0)
|
||||||
|
@ -186,7 +189,7 @@ NTSTATUS MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
|
||||||
PVOID BaseAddress,
|
PVOID BaseAddress,
|
||||||
ULONG Length,
|
ULONG Length,
|
||||||
VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea,
|
VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea,
|
||||||
PVOID Address, ULONG PhysAddr),
|
PVOID Address, ULONG PhysAddr, BOOLEAN Dirty),
|
||||||
PVOID FreePageContext);
|
PVOID FreePageContext);
|
||||||
VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead);
|
VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead);
|
||||||
NTSTATUS MmLockMemoryArea(MEMORY_AREA* MemoryArea);
|
NTSTATUS MmLockMemoryArea(MEMORY_AREA* MemoryArea);
|
||||||
|
@ -209,7 +212,8 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
|
||||||
PADDRESS_RANGE BIOSMemoryMap,
|
PADDRESS_RANGE BIOSMemoryMap,
|
||||||
ULONG AddressRangeCount);
|
ULONG AddressRangeCount);
|
||||||
|
|
||||||
PVOID MmAllocPage(SWAPENTRY SavedSwapEntry);
|
PVOID
|
||||||
|
MmAllocPage(ULONG Consumer, SWAPENTRY SavedSwapEntry);
|
||||||
VOID MmDereferencePage(PVOID PhysicalAddress);
|
VOID MmDereferencePage(PVOID PhysicalAddress);
|
||||||
VOID MmReferencePage(PVOID PhysicalAddress);
|
VOID MmReferencePage(PVOID PhysicalAddress);
|
||||||
VOID MmDeletePageTable(struct _EPROCESS* Process,
|
VOID MmDeletePageTable(struct _EPROCESS* Process,
|
||||||
|
@ -280,14 +284,16 @@ VOID MmClearWaitPage(PVOID Page);
|
||||||
VOID MmSetWaitPage(PVOID Page);
|
VOID MmSetWaitPage(PVOID Page);
|
||||||
BOOLEAN MmIsPageDirty(struct _EPROCESS* Process, PVOID Address);
|
BOOLEAN MmIsPageDirty(struct _EPROCESS* Process, PVOID Address);
|
||||||
BOOLEAN MmIsPageTablePresent(PVOID PAddress);
|
BOOLEAN MmIsPageTablePresent(PVOID PAddress);
|
||||||
ULONG MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
|
NTSTATUS
|
||||||
MEMORY_AREA* MemoryArea,
|
MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
||||||
PVOID Address,
|
PMEMORY_AREA MemoryArea,
|
||||||
PBOOLEAN Ul);
|
PVOID Address,
|
||||||
ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
struct _MM_PAGEOP* PageOp);
|
||||||
PMEMORY_AREA MemoryArea,
|
NTSTATUS
|
||||||
PVOID Address,
|
MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
PBOOLEAN Ul);
|
PMEMORY_AREA MemoryArea,
|
||||||
|
PVOID Address,
|
||||||
|
struct _MM_PAGEOP* PageOp);
|
||||||
MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
|
MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
|
||||||
PVOID Address,
|
PVOID Address,
|
||||||
ULONG Length);
|
ULONG Length);
|
||||||
|
@ -295,17 +301,6 @@ MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
|
||||||
VOID ExUnmapPage(PVOID Addr);
|
VOID ExUnmapPage(PVOID Addr);
|
||||||
PVOID ExAllocatePage(VOID);
|
PVOID ExAllocatePage(VOID);
|
||||||
|
|
||||||
VOID MmLockWorkingSet(struct _EPROCESS* Process);
|
|
||||||
VOID MmUnlockWorkingSet(struct _EPROCESS* Process);
|
|
||||||
VOID MmInitializeWorkingSet(struct _EPROCESS* Process,
|
|
||||||
PMADDRESS_SPACE AddressSpace);
|
|
||||||
ULONG MmTrimWorkingSet(struct _EPROCESS* Process,
|
|
||||||
ULONG ReduceHint);
|
|
||||||
VOID MmRemovePageFromWorkingSet(struct _EPROCESS* Process,
|
|
||||||
PVOID Address);
|
|
||||||
VOID MmAddPageToWorkingSet(struct _EPROCESS* Process,
|
|
||||||
PVOID Address);
|
|
||||||
|
|
||||||
VOID MmInitPagingFile(VOID);
|
VOID MmInitPagingFile(VOID);
|
||||||
BOOLEAN MmReserveSwapPages(ULONG Nr);
|
BOOLEAN MmReserveSwapPages(ULONG Nr);
|
||||||
VOID MmDereserveSwapPages(ULONG Nr);
|
VOID MmDereserveSwapPages(ULONG Nr);
|
||||||
|
@ -322,10 +317,6 @@ VOID MmInit3(VOID);
|
||||||
NTSTATUS MmInitPagerThread(VOID);
|
NTSTATUS MmInitPagerThread(VOID);
|
||||||
|
|
||||||
VOID MmInitKernelMap(PVOID BaseAddress);
|
VOID MmInitKernelMap(PVOID BaseAddress);
|
||||||
|
|
||||||
VOID MmWaitForFreePages(VOID);
|
|
||||||
PVOID MmMustAllocPage(SWAPENTRY SavedSwapEntry);
|
|
||||||
PVOID MmAllocPageMaybeSwap(SWAPENTRY SavedSwapEntry);
|
|
||||||
NTSTATUS MmCreatePageTable(PVOID PAddress);
|
NTSTATUS MmCreatePageTable(PVOID PAddress);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -477,7 +468,7 @@ NTSTATUS MmCommitPagedPoolAddress(PVOID Address);
|
||||||
VOID
|
VOID
|
||||||
MmInitializeMemoryConsumer(ULONG Consumer,
|
MmInitializeMemoryConsumer(ULONG Consumer,
|
||||||
NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
|
NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
|
||||||
PULONG NrFreed, PVOID* FreedPages));
|
PULONG NrFreed));
|
||||||
VOID
|
VOID
|
||||||
MmInitializeBalancer(ULONG NrAvailablePages);
|
MmInitializeBalancer(ULONG NrAvailablePages);
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -491,4 +482,30 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, PVOID* AllocatedPag
|
||||||
#define MC_NPPOOL (3)
|
#define MC_NPPOOL (3)
|
||||||
#define MC_MAXIMUM (4)
|
#define MC_MAXIMUM (4)
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmSetRmapListHeadPage(PVOID PhysicalAddress, struct _MM_RMAP_ENTRY* ListHead);
|
||||||
|
struct _MM_RMAP_ENTRY*
|
||||||
|
MmGetRmapListHeadPage(PVOID PhysicalAddress);
|
||||||
|
VOID
|
||||||
|
MmInsertRmap(PVOID PhysicalAddress, PEPROCESS Process, PVOID Address);
|
||||||
|
VOID
|
||||||
|
MmDeleteAllRmaps(PVOID PhysicalAddress, PVOID Context,
|
||||||
|
VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process, PVOID Address));
|
||||||
|
VOID
|
||||||
|
MmDeleteRmap(PVOID PhysicalAddress, PEPROCESS Process, PVOID Address);
|
||||||
|
VOID
|
||||||
|
MmInitializeRmapList(VOID);
|
||||||
|
PVOID
|
||||||
|
MmGetLRUNextUserPage(PVOID PreviousPhysicalAddress);
|
||||||
|
PVOID
|
||||||
|
MmGetLRUFirstUserPage(VOID);
|
||||||
|
NTSTATUS
|
||||||
|
MmPageOutPhysicalAddress(PVOID PhysicalAddress);
|
||||||
|
NTSTATUS
|
||||||
|
MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, ULONG* PhysicalAddr);
|
||||||
|
VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -47,7 +47,7 @@ static PVOID PcrPages[MAXIMUM_PROCESSORS];
|
||||||
VOID
|
VOID
|
||||||
KePrepareForApplicationProcessorInit(ULONG Id)
|
KePrepareForApplicationProcessorInit(ULONG Id)
|
||||||
{
|
{
|
||||||
PcrPages[Id] = MmAllocPage(0);
|
MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &PcrPages[Id]);
|
||||||
KiGdtPrepareForApplicationProcessorInit(Id);
|
KiGdtPrepareForApplicationProcessorInit(Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,8 @@
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr)
|
KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
|
||||||
|
BOOLEAN Dirty)
|
||||||
{
|
{
|
||||||
if (PhysAddr != 0)
|
if (PhysAddr != 0)
|
||||||
{
|
{
|
||||||
|
@ -116,10 +117,16 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
|
||||||
}
|
}
|
||||||
for (i = 0; i < (MM_STACK_SIZE / PAGESIZE); i++)
|
for (i = 0; i < (MM_STACK_SIZE / PAGESIZE); i++)
|
||||||
{
|
{
|
||||||
|
PVOID Page;
|
||||||
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
Status = MmCreateVirtualMapping(NULL,
|
Status = MmCreateVirtualMapping(NULL,
|
||||||
KernelStack + (i * PAGESIZE),
|
KernelStack + (i * PAGESIZE),
|
||||||
PAGE_EXECUTE_READWRITE,
|
PAGE_EXECUTE_READWRITE,
|
||||||
(ULONG)MmAllocPage(0));
|
(ULONG)Page);
|
||||||
}
|
}
|
||||||
Thread->InitialStack = KernelStack + MM_STACK_SIZE;
|
Thread->InitialStack = KernelStack + MM_STACK_SIZE;
|
||||||
Thread->StackBase = KernelStack + MM_STACK_SIZE;
|
Thread->StackBase = KernelStack + MM_STACK_SIZE;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: connect.c,v 1.8 2001/12/02 23:34:42 dwelch Exp $
|
/* $Id: connect.c,v 1.9 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -16,8 +16,8 @@
|
||||||
#include <internal/port.h>
|
#include <internal/port.h>
|
||||||
#include <internal/dbg.h>
|
#include <internal/dbg.h>
|
||||||
#include <internal/pool.h>
|
#include <internal/pool.h>
|
||||||
#include <internal/mm.h>
|
|
||||||
#include <internal/safe.h>
|
#include <internal/safe.h>
|
||||||
|
#include <internal/mm.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: aspace.c,v 1.7 2001/11/25 15:21:11 dwelch Exp $
|
/* $Id: aspace.c,v 1.8 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -87,10 +87,6 @@ MmInitializeAddressSpace(PEPROCESS Process,
|
||||||
AddressSpace->LowestAddress = KERNEL_BASE;
|
AddressSpace->LowestAddress = KERNEL_BASE;
|
||||||
}
|
}
|
||||||
AddressSpace->Process = Process;
|
AddressSpace->Process = Process;
|
||||||
if (Process != NULL)
|
|
||||||
{
|
|
||||||
MmInitializeWorkingSet(Process, AddressSpace);
|
|
||||||
}
|
|
||||||
if (Process != NULL)
|
if (Process != NULL)
|
||||||
{
|
{
|
||||||
AddressSpace->PageTableRefCountTable =
|
AddressSpace->PageTableRefCountTable =
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: balance.c,v 1.2 2001/12/29 14:32:22 dwelch Exp $
|
/* $Id: balance.c,v 1.3 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top directory
|
* COPYRIGHT: See COPYING in the top directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -41,15 +41,24 @@ typedef struct _MM_MEMORY_CONSUMER
|
||||||
{
|
{
|
||||||
ULONG PagesUsed;
|
ULONG PagesUsed;
|
||||||
ULONG PagesTarget;
|
ULONG PagesTarget;
|
||||||
NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed, PVOID* FreedPages);
|
NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed);
|
||||||
} MM_MEMORY_CONSUMER, *PMM_MEMORY_CONSUMER;
|
} MM_MEMORY_CONSUMER, *PMM_MEMORY_CONSUMER;
|
||||||
|
|
||||||
|
typedef struct _MM_ALLOCATION_REQUEST
|
||||||
|
{
|
||||||
|
PVOID Page;
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
KEVENT Event;
|
||||||
|
} MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST;
|
||||||
|
|
||||||
/* GLOBALS ******************************************************************/
|
/* GLOBALS ******************************************************************/
|
||||||
|
|
||||||
static MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM];
|
static MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM];
|
||||||
static ULONG MiMinimumAvailablePages;
|
static ULONG MiMinimumAvailablePages;
|
||||||
static ULONG MiNrAvailablePages;
|
static ULONG MiNrAvailablePages;
|
||||||
static ULONG MiNrTotalPages;
|
static ULONG MiNrTotalPages;
|
||||||
|
static LIST_ENTRY AllocationListHead;
|
||||||
|
static KSPIN_LOCK AllocationListLock;
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
@ -57,6 +66,8 @@ VOID
|
||||||
MmInitializeBalancer(ULONG NrAvailablePages)
|
MmInitializeBalancer(ULONG NrAvailablePages)
|
||||||
{
|
{
|
||||||
memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
|
memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
|
||||||
|
InitializeListHead(&AllocationListHead);
|
||||||
|
KeInitializeSpinLock(&AllocationListLock);
|
||||||
|
|
||||||
MiNrAvailablePages = MiNrTotalPages = NrAvailablePages;
|
MiNrAvailablePages = MiNrTotalPages = NrAvailablePages;
|
||||||
|
|
||||||
|
@ -71,7 +82,7 @@ MmInitializeBalancer(ULONG NrAvailablePages)
|
||||||
VOID
|
VOID
|
||||||
MmInitializeMemoryConsumer(ULONG Consumer,
|
MmInitializeMemoryConsumer(ULONG Consumer,
|
||||||
NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
|
NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
|
||||||
PULONG NrFreed, PVOID* FreedPages))
|
PULONG NrFreed))
|
||||||
{
|
{
|
||||||
MiMemoryConsumers[Consumer].Trim = Trim;
|
MiMemoryConsumers[Consumer].Trim = Trim;
|
||||||
}
|
}
|
||||||
|
@ -79,9 +90,26 @@ MmInitializeMemoryConsumer(ULONG Consumer,
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
MmReleasePageMemoryConsumer(ULONG Consumer, PVOID Page)
|
MmReleasePageMemoryConsumer(ULONG Consumer, PVOID Page)
|
||||||
{
|
{
|
||||||
|
PMM_ALLOCATION_REQUEST Request;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
|
InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
|
||||||
InterlockedIncrement(&MiNrAvailablePages);
|
InterlockedIncrement(&MiNrAvailablePages);
|
||||||
MmDereferencePage(Page);
|
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
|
||||||
|
if (IsListEmpty(&AllocationListHead))
|
||||||
|
{
|
||||||
|
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||||
|
MmDereferencePage(Page);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Entry = RemoveHeadList(&AllocationListHead);
|
||||||
|
Request = CONTAINING_RECORD(Entry, MM_ALLOCATION_REQUEST, ListEntry);
|
||||||
|
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||||
|
Request->Page = Page;
|
||||||
|
KeSetEvent(&Request->Event, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,19 +126,17 @@ MiTrimMemoryConsumer(ULONG Consumer)
|
||||||
|
|
||||||
if (MiMemoryConsumers[Consumer].Trim != NULL)
|
if (MiMemoryConsumers[Consumer].Trim != NULL)
|
||||||
{
|
{
|
||||||
MiMemoryConsumers[Consumer].Trim(Target, 0, NULL, NULL);
|
MiMemoryConsumers[Consumer].Trim(Target, 0, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
MiRebalanceMemoryConsumers(PVOID* Page)
|
MiRebalanceMemoryConsumers(VOID)
|
||||||
{
|
{
|
||||||
LONG Target;
|
LONG Target;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
PVOID* FreedPages;
|
|
||||||
ULONG NrFreedPages;
|
ULONG NrFreedPages;
|
||||||
ULONG TotalFreedPages;
|
NTSTATUS Status;
|
||||||
PVOID* OrigFreedPages;
|
|
||||||
|
|
||||||
Target = MiMinimumAvailablePages - MiNrAvailablePages;
|
Target = MiMinimumAvailablePages - MiNrAvailablePages;
|
||||||
if (Target < 0)
|
if (Target < 0)
|
||||||
|
@ -118,36 +144,22 @@ MiRebalanceMemoryConsumers(PVOID* Page)
|
||||||
Target = 1;
|
Target = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
OrigFreedPages = FreedPages = alloca(sizeof(PVOID) * Target);
|
|
||||||
TotalFreedPages = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < MC_MAXIMUM && Target > 0; i++)
|
for (i = 0; i < MC_MAXIMUM && Target > 0; i++)
|
||||||
{
|
{
|
||||||
if (MiMemoryConsumers[i].Trim != NULL)
|
if (MiMemoryConsumers[i].Trim != NULL)
|
||||||
{
|
{
|
||||||
MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages, FreedPages);
|
Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
Target = Target - NrFreedPages;
|
Target = Target - NrFreedPages;
|
||||||
FreedPages = FreedPages + NrFreedPages;
|
|
||||||
TotalFreedPages = TotalFreedPages + NrFreedPages;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Target > 0)
|
if (Target > 0)
|
||||||
{
|
{
|
||||||
KeBugCheck(0);
|
KeBugCheck(0);
|
||||||
}
|
}
|
||||||
if (Page != NULL)
|
|
||||||
{
|
|
||||||
*Page = OrigFreedPages[0];
|
|
||||||
i = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
for (; i < TotalFreedPages; i++)
|
|
||||||
{
|
|
||||||
MmDereferencePage(OrigFreedPages[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -183,15 +195,18 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, PVOID* AllocatedPag
|
||||||
InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
|
InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
|
||||||
return(STATUS_NO_MEMORY);
|
return(STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
MiRebalanceMemoryConsumers(NULL);
|
MiRebalanceMemoryConsumers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Actually allocate the page.
|
* Actually allocate the page.
|
||||||
*/
|
*/
|
||||||
Page = MmAllocPage(0);
|
Page = MmAllocPage(Consumer, 0);
|
||||||
if (Page == NULL)
|
if (Page == NULL)
|
||||||
{
|
{
|
||||||
|
MM_ALLOCATION_REQUEST Request;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
/* Still not trimmed enough. */
|
/* Still not trimmed enough. */
|
||||||
if (!CanWait)
|
if (!CanWait)
|
||||||
{
|
{
|
||||||
|
@ -199,7 +214,19 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, PVOID* AllocatedPag
|
||||||
InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
|
InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
|
||||||
return(STATUS_NO_MEMORY);
|
return(STATUS_NO_MEMORY);
|
||||||
}
|
}
|
||||||
MiRebalanceMemoryConsumers(&Page);
|
|
||||||
|
/* Insert an allocation request. */
|
||||||
|
Request.Page = NULL;
|
||||||
|
KeInitializeEvent(&Request.Event, NotificationEvent, FALSE);
|
||||||
|
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
|
||||||
|
InsertTailList(&AllocationListHead, &Request.ListEntry);
|
||||||
|
KeReleaseSpinLock(&AllocationListLock, oldIrql);
|
||||||
|
MiRebalanceMemoryConsumers();
|
||||||
|
Page = Request.Page;
|
||||||
|
if (Page == NULL)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*AllocatedPage = Page;
|
*AllocatedPage = Page;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: cont.c,v 1.14 2001/12/29 14:32:22 dwelch Exp $
|
/* $Id: cont.c,v 1.15 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -20,7 +20,8 @@
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
VOID STATIC
|
VOID STATIC
|
||||||
MmFreeContinuousPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr)
|
MmFreeContinuousPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
|
||||||
|
BOOLEAN Dirty)
|
||||||
{
|
{
|
||||||
if (PhysAddr != 0)
|
if (PhysAddr != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,14 +34,15 @@ typedef struct _PHYSICAL_PAGE
|
||||||
SWAPENTRY SavedSwapEntry;
|
SWAPENTRY SavedSwapEntry;
|
||||||
ULONG LockCount;
|
ULONG LockCount;
|
||||||
ULONG MapCount;
|
ULONG MapCount;
|
||||||
|
struct _MM_RMAP_ENTRY* RmapListHead;
|
||||||
} PHYSICAL_PAGE, *PPHYSICAL_PAGE;
|
} PHYSICAL_PAGE, *PPHYSICAL_PAGE;
|
||||||
|
|
||||||
/* GLOBALS ****************************************************************/
|
/* GLOBALS ****************************************************************/
|
||||||
|
|
||||||
static PPHYSICAL_PAGE MmPageArray;
|
static PPHYSICAL_PAGE MmPageArray;
|
||||||
|
|
||||||
static LIST_ENTRY UsedPageListHead;
|
|
||||||
static KSPIN_LOCK PageListLock;
|
static KSPIN_LOCK PageListLock;
|
||||||
|
static LIST_ENTRY UsedPageListHeads[MC_MAXIMUM];
|
||||||
static LIST_ENTRY FreeZeroedPageListHead;
|
static LIST_ENTRY FreeZeroedPageListHead;
|
||||||
static LIST_ENTRY FreeUnzeroedPageListHead;
|
static LIST_ENTRY FreeUnzeroedPageListHead;
|
||||||
static LIST_ENTRY BiosPageListHead;
|
static LIST_ENTRY BiosPageListHead;
|
||||||
|
@ -54,6 +55,58 @@ MmCreateVirtualMappingUnsafe(struct _EPROCESS* Process,
|
||||||
|
|
||||||
/* FUNCTIONS *************************************************************/
|
/* FUNCTIONS *************************************************************/
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
MmGetLRUFirstUserPage(VOID)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY NextListEntry;
|
||||||
|
ULONG Next;
|
||||||
|
PHYSICAL_PAGE* PageDescriptor;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&PageListLock, &oldIrql);
|
||||||
|
NextListEntry = UsedPageListHeads[MC_USER].Flink;
|
||||||
|
if (NextListEntry == &UsedPageListHeads[MC_USER])
|
||||||
|
{
|
||||||
|
KeReleaseSpinLock(&PageListLock, oldIrql);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
|
||||||
|
Next = (ULONG)((ULONG)PageDescriptor - (ULONG)MmPageArray);
|
||||||
|
Next = (Next / sizeof(PHYSICAL_PAGE)) * PAGESIZE;
|
||||||
|
KeReleaseSpinLock(&PageListLock, oldIrql);
|
||||||
|
return((PVOID)Next);
|
||||||
|
}
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
MmGetLRUNextUserPage(PVOID PreviousPhysicalAddress)
|
||||||
|
{
|
||||||
|
ULONG Start = (ULONG)PreviousPhysicalAddress / PAGESIZE;
|
||||||
|
PLIST_ENTRY NextListEntry;
|
||||||
|
ULONG Next;
|
||||||
|
PHYSICAL_PAGE* PageDescriptor;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&PageListLock, &oldIrql);
|
||||||
|
if (!(MmPageArray[Start].Flags & MM_PHYSICAL_PAGE_USED))
|
||||||
|
{
|
||||||
|
NextListEntry = UsedPageListHeads[MC_USER].Flink;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NextListEntry = MmPageArray[Start].ListEntry.Flink;
|
||||||
|
}
|
||||||
|
if (NextListEntry == &UsedPageListHeads[MC_USER])
|
||||||
|
{
|
||||||
|
KeReleaseSpinLock(&PageListLock, oldIrql);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
|
||||||
|
Next = (ULONG)((ULONG)PageDescriptor - (ULONG)MmPageArray);
|
||||||
|
Next = (Next / sizeof(PHYSICAL_PAGE)) * PAGESIZE;
|
||||||
|
KeReleaseSpinLock(&PageListLock, oldIrql);
|
||||||
|
return((PVOID)Next);
|
||||||
|
}
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
MmGetContinuousPages(ULONG NumberOfBytes,
|
MmGetContinuousPages(ULONG NumberOfBytes,
|
||||||
PHYSICAL_ADDRESS HighestAcceptableAddress,
|
PHYSICAL_ADDRESS HighestAcceptableAddress,
|
||||||
|
@ -112,7 +165,7 @@ MmGetContinuousPages(ULONG NumberOfBytes,
|
||||||
MmPageArray[i].LockCount = 0;
|
MmPageArray[i].LockCount = 0;
|
||||||
MmPageArray[i].MapCount = 0;
|
MmPageArray[i].MapCount = 0;
|
||||||
MmPageArray[i].SavedSwapEntry = 0;
|
MmPageArray[i].SavedSwapEntry = 0;
|
||||||
InsertTailList(&UsedPageListHead, &MmPageArray[i].ListEntry);
|
InsertTailList(&UsedPageListHeads[MC_NPPOOL], &MmPageArray[i].ListEntry);
|
||||||
}
|
}
|
||||||
KeReleaseSpinLock(&PageListLock, oldIrql);
|
KeReleaseSpinLock(&PageListLock, oldIrql);
|
||||||
return((PVOID)(start * 4096));
|
return((PVOID)(start * 4096));
|
||||||
|
@ -229,7 +282,10 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
|
||||||
MemorySizeInPages,
|
MemorySizeInPages,
|
||||||
LastKernelAddress);
|
LastKernelAddress);
|
||||||
|
|
||||||
InitializeListHead(&UsedPageListHead);
|
for (i = 0; i < MC_MAXIMUM; i++)
|
||||||
|
{
|
||||||
|
InitializeListHead(&UsedPageListHeads[i]);
|
||||||
|
}
|
||||||
KeInitializeSpinLock(&PageListLock);
|
KeInitializeSpinLock(&PageListLock);
|
||||||
InitializeListHead(&FreeUnzeroedPageListHead);
|
InitializeListHead(&FreeUnzeroedPageListHead);
|
||||||
InitializeListHead(&FreeZeroedPageListHead);
|
InitializeListHead(&FreeZeroedPageListHead);
|
||||||
|
@ -306,7 +362,7 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
|
||||||
{
|
{
|
||||||
MmPageArray[i].Flags = MM_PHYSICAL_PAGE_USED;
|
MmPageArray[i].Flags = MM_PHYSICAL_PAGE_USED;
|
||||||
MmPageArray[i].ReferenceCount = 1;
|
MmPageArray[i].ReferenceCount = 1;
|
||||||
InsertTailList(&UsedPageListHead,
|
InsertTailList(&UsedPageListHeads[MC_NPPOOL],
|
||||||
&MmPageArray[i].ListEntry);
|
&MmPageArray[i].ListEntry);
|
||||||
}
|
}
|
||||||
MmStats.NrFreePages += ((0xa0000/PAGESIZE) - i);
|
MmStats.NrFreePages += ((0xa0000/PAGESIZE) - i);
|
||||||
|
@ -358,7 +414,7 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
|
||||||
{
|
{
|
||||||
MmPageArray[i].Flags = MM_PHYSICAL_PAGE_USED;
|
MmPageArray[i].Flags = MM_PHYSICAL_PAGE_USED;
|
||||||
MmPageArray[i].ReferenceCount = 1;
|
MmPageArray[i].ReferenceCount = 1;
|
||||||
InsertTailList(&UsedPageListHead,
|
InsertTailList(&UsedPageListHeads[MC_NPPOOL],
|
||||||
&MmPageArray[i].ListEntry);
|
&MmPageArray[i].ListEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,6 +453,22 @@ VOID MmSetFlagsPage(PVOID PhysicalAddress,
|
||||||
KeReleaseSpinLock(&PageListLock, oldIrql);
|
KeReleaseSpinLock(&PageListLock, oldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmSetRmapListHeadPage(PVOID PhysicalAddress, struct _MM_RMAP_ENTRY* ListHead)
|
||||||
|
{
|
||||||
|
ULONG Start = (ULONG)PhysicalAddress / PAGESIZE;
|
||||||
|
|
||||||
|
MmPageArray[Start].RmapListHead = ListHead;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _MM_RMAP_ENTRY*
|
||||||
|
MmGetRmapListHeadPage(PVOID PhysicalAddress)
|
||||||
|
{
|
||||||
|
ULONG Start = (ULONG)PhysicalAddress / PAGESIZE;
|
||||||
|
|
||||||
|
return(MmPageArray[Start].RmapListHead);
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
MmMarkPageMapped(PVOID PhysicalAddress)
|
MmMarkPageMapped(PVOID PhysicalAddress)
|
||||||
{
|
{
|
||||||
|
@ -559,6 +631,11 @@ VOID MmDereferencePage(PVOID PhysicalAddress)
|
||||||
MmStats.NrFreePages++;
|
MmStats.NrFreePages++;
|
||||||
MmStats.NrSystemPages--;
|
MmStats.NrSystemPages--;
|
||||||
RemoveEntryList(&MmPageArray[Start].ListEntry);
|
RemoveEntryList(&MmPageArray[Start].ListEntry);
|
||||||
|
if (MmPageArray[Start].RmapListHead != NULL)
|
||||||
|
{
|
||||||
|
DbgPrint("Freeing page with rmap entries.\n");
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
if (MmPageArray[Start].MapCount != 0)
|
if (MmPageArray[Start].MapCount != 0)
|
||||||
{
|
{
|
||||||
DbgPrint("Freeing mapped page (0x%x count %d)\n",
|
DbgPrint("Freeing mapped page (0x%x count %d)\n",
|
||||||
|
@ -659,7 +736,7 @@ VOID MmUnlockPage(PVOID PhysicalAddress)
|
||||||
|
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
MmAllocPage(SWAPENTRY SavedSwapEntry)
|
MmAllocPage(ULONG Consumer, SWAPENTRY SavedSwapEntry)
|
||||||
{
|
{
|
||||||
ULONG offset;
|
ULONG offset;
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
|
@ -703,7 +780,7 @@ MmAllocPage(SWAPENTRY SavedSwapEntry)
|
||||||
PageDescriptor->LockCount = 0;
|
PageDescriptor->LockCount = 0;
|
||||||
PageDescriptor->MapCount = 0;
|
PageDescriptor->MapCount = 0;
|
||||||
PageDescriptor->SavedSwapEntry = SavedSwapEntry;
|
PageDescriptor->SavedSwapEntry = SavedSwapEntry;
|
||||||
ExInterlockedInsertTailList(&UsedPageListHead, ListEntry, &PageListLock);
|
ExInterlockedInsertTailList(&UsedPageListHeads[Consumer], ListEntry, &PageListLock);
|
||||||
|
|
||||||
MmStats.NrSystemPages++;
|
MmStats.NrSystemPages++;
|
||||||
MmStats.NrFreePages--;
|
MmStats.NrFreePages--;
|
||||||
|
@ -717,33 +794,3 @@ MmAllocPage(SWAPENTRY SavedSwapEntry)
|
||||||
DPRINT("MmAllocPage() = %x\n",offset);
|
DPRINT("MmAllocPage() = %x\n",offset);
|
||||||
return((PVOID)offset);
|
return((PVOID)offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
PVOID
|
|
||||||
MmMustAllocPage(SWAPENTRY SavedSwapEntry)
|
|
||||||
{
|
|
||||||
PVOID Page;
|
|
||||||
|
|
||||||
Page = MmAllocPage(SavedSwapEntry);
|
|
||||||
if (Page == NULL)
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(Page);
|
|
||||||
}
|
|
||||||
|
|
||||||
PVOID
|
|
||||||
MmAllocPageMaybeSwap(SWAPENTRY SavedSwapEntry)
|
|
||||||
{
|
|
||||||
PVOID Page;
|
|
||||||
|
|
||||||
Page = MmAllocPage(SavedSwapEntry);
|
|
||||||
while (Page == NULL)
|
|
||||||
{
|
|
||||||
MmWaitForFreePages();
|
|
||||||
Page = MmAllocPage(SavedSwapEntry);
|
|
||||||
};
|
|
||||||
return(Page);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: page.c,v 1.29 2001/04/17 04:11:01 dwelch Exp $
|
/* $Id: page.c,v 1.30 2001/12/31 01:53:46 dwelch Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/mm/i386/page.c
|
* FILE: ntoskrnl/mm/i386/page.c
|
||||||
|
@ -239,10 +239,11 @@ NTSTATUS MmGetPageEntry2(PVOID PAddress, PULONG* Pte)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
npage = (ULONG)MmAllocPage(0);
|
NTSTATUS Status;
|
||||||
if (npage == 0)
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, (PVOID*)&npage);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return(STATUS_NO_MEMORY);
|
return(Status);
|
||||||
}
|
}
|
||||||
(*Pde) = npage | 0x7;
|
(*Pde) = npage | 0x7;
|
||||||
if (Address >= KERNEL_BASE)
|
if (Address >= KERNEL_BASE)
|
||||||
|
@ -335,6 +336,75 @@ ULONG MmGetPhysicalAddressForProcess(PEPROCESS Process,
|
||||||
return(PAGE_MASK(PageEntry));
|
return(PAGE_MASK(PageEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, ULONG* PhysicalAddr)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Delete a virtual mapping
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
ULONG Pte;
|
||||||
|
PULONG Pde;
|
||||||
|
PEPROCESS CurrentProcess = PsGetCurrentProcess();
|
||||||
|
BOOLEAN WasValid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we are setting a page in another process we need to be in its
|
||||||
|
* context.
|
||||||
|
*/
|
||||||
|
if (Process != NULL && Process != CurrentProcess)
|
||||||
|
{
|
||||||
|
KeAttachProcess(Process);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the page directory entry, we may have to copy the entry from
|
||||||
|
* the global page directory.
|
||||||
|
*/
|
||||||
|
Pde = ADDR_TO_PDE(Address);
|
||||||
|
if ((*Pde) == 0 &&
|
||||||
|
MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0)
|
||||||
|
{
|
||||||
|
(*Pde) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)];
|
||||||
|
FLUSH_TLB;
|
||||||
|
}
|
||||||
|
if ((*Pde) == 0)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Atomically set the entry to zero and get the old value.
|
||||||
|
*/
|
||||||
|
Pte = *ADDR_TO_PTE(Address);
|
||||||
|
*ADDR_TO_PTE(Address) = Pte & (~PA_PRESENT);
|
||||||
|
FLUSH_TLB;
|
||||||
|
WasValid = (PAGE_MASK(Pte) != 0);
|
||||||
|
if (!WasValid)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If necessary go back to the original context
|
||||||
|
*/
|
||||||
|
if (Process != NULL && Process != CurrentProcess)
|
||||||
|
{
|
||||||
|
KeDetachProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return some information to the caller
|
||||||
|
*/
|
||||||
|
if (WasDirty != NULL)
|
||||||
|
{
|
||||||
|
*WasDirty = Pte & PA_DIRTY;
|
||||||
|
}
|
||||||
|
if (PhysicalAddr != NULL)
|
||||||
|
{
|
||||||
|
*PhysicalAddr = PAGE_MASK(Pte);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
|
MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
|
||||||
BOOL* WasDirty, ULONG* PhysicalAddr)
|
BOOL* WasDirty, ULONG* PhysicalAddr)
|
||||||
|
@ -373,6 +443,14 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
|
||||||
{
|
{
|
||||||
KeDetachProcess();
|
KeDetachProcess();
|
||||||
}
|
}
|
||||||
|
if (WasDirty != NULL)
|
||||||
|
{
|
||||||
|
*WasDirty = FALSE;
|
||||||
|
}
|
||||||
|
if (PhysicalAddr != NULL)
|
||||||
|
{
|
||||||
|
*PhysicalAddr = 0;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +458,7 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
|
||||||
* Atomically set the entry to zero and get the old value.
|
* Atomically set the entry to zero and get the old value.
|
||||||
*/
|
*/
|
||||||
Pte = (ULONG)InterlockedExchange((PLONG)ADDR_TO_PTE(Address), 0);
|
Pte = (ULONG)InterlockedExchange((PLONG)ADDR_TO_PTE(Address), 0);
|
||||||
|
FLUSH_TLB;
|
||||||
WasValid = (PAGE_MASK(Pte) != 0);
|
WasValid = (PAGE_MASK(Pte) != 0);
|
||||||
if (WasValid)
|
if (WasValid)
|
||||||
{
|
{
|
||||||
|
@ -402,12 +481,10 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
|
||||||
Ptrc = Process->AddressSpace.PageTableRefCountTable;
|
Ptrc = Process->AddressSpace.PageTableRefCountTable;
|
||||||
|
|
||||||
Ptrc[ADDR_TO_PAGE_TABLE(Address)]--;
|
Ptrc[ADDR_TO_PAGE_TABLE(Address)]--;
|
||||||
#if 1
|
|
||||||
if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0)
|
if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0)
|
||||||
{
|
{
|
||||||
MmFreePageTable(Process, Address);
|
MmFreePageTable(Process, Address);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -481,14 +558,15 @@ NTSTATUS MmCreatePageTable(PVOID PAddress)
|
||||||
}
|
}
|
||||||
if ((*page_dir) == 0)
|
if ((*page_dir) == 0)
|
||||||
{
|
{
|
||||||
npage = (ULONG)MmAllocPage(0);
|
NTSTATUS Status;
|
||||||
if (npage == 0)
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, (PVOID*)&npage);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
return(STATUS_UNSUCCESSFUL);
|
{
|
||||||
}
|
return(Status);
|
||||||
(*page_dir) = npage | 0x7;
|
}
|
||||||
memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGESIZE);
|
(*page_dir) = npage | 0x7;
|
||||||
FLUSH_TLB;
|
memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGESIZE);
|
||||||
|
FLUSH_TLB;
|
||||||
}
|
}
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -515,14 +593,15 @@ PULONG MmGetPageEntry(PVOID PAddress)
|
||||||
}
|
}
|
||||||
if ((*page_dir) == 0)
|
if ((*page_dir) == 0)
|
||||||
{
|
{
|
||||||
npage = (ULONG)MmAllocPage(0);
|
NTSTATUS Status;
|
||||||
if (npage == 0)
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, (PVOID*)&npage);
|
||||||
{
|
if (!NT_SUCCESS(Status))
|
||||||
KeBugCheck(0);
|
{
|
||||||
}
|
KeBugCheck(0);
|
||||||
(*page_dir) = npage | 0x7;
|
}
|
||||||
memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGESIZE);
|
(*page_dir) = npage | 0x7;
|
||||||
FLUSH_TLB;
|
memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGESIZE);
|
||||||
|
FLUSH_TLB;
|
||||||
}
|
}
|
||||||
page_tlb = ADDR_TO_PTE(Address);
|
page_tlb = ADDR_TO_PTE(Address);
|
||||||
DPRINT("page_tlb %x\n",page_tlb);
|
DPRINT("page_tlb %x\n",page_tlb);
|
||||||
|
@ -578,6 +657,24 @@ VOID MmSetCleanPage(PEPROCESS Process, PVOID Address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address)
|
||||||
|
{
|
||||||
|
PULONG PageEntry;
|
||||||
|
PEPROCESS CurrentProcess = PsGetCurrentProcess();
|
||||||
|
|
||||||
|
if (Process != CurrentProcess)
|
||||||
|
{
|
||||||
|
KeAttachProcess(Process);
|
||||||
|
}
|
||||||
|
PageEntry = MmGetPageEntry(Address);
|
||||||
|
(*PageEntry) = (*PageEntry) | PA_PRESENT;
|
||||||
|
FLUSH_TLB;
|
||||||
|
if (Process != CurrentProcess)
|
||||||
|
{
|
||||||
|
KeDetachProcess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
|
BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
|
||||||
{
|
{
|
||||||
return((MmGetPageEntryForProcess1(Process, Address)) & PA_PRESENT);
|
return((MmGetPageEntryForProcess1(Process, Address)) & PA_PRESENT);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: kmap.c,v 1.12 2001/12/06 00:54:54 dwelch Exp $
|
/* $Id: kmap.c,v 1.13 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -51,9 +51,10 @@ PVOID
|
||||||
ExAllocatePage(VOID)
|
ExAllocatePage(VOID)
|
||||||
{
|
{
|
||||||
ULONG PhysPage;
|
ULONG PhysPage;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
PhysPage = (ULONG)MmAllocPage(0);
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, (PVOID*)&PhysPage);
|
||||||
if (PhysPage == 0)
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,7 +295,7 @@ MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
|
||||||
PVOID BaseAddress,
|
PVOID BaseAddress,
|
||||||
ULONG Length,
|
ULONG Length,
|
||||||
VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||||
ULONG PhysAddr),
|
ULONG PhysAddr, BOOLEAN Dirty),
|
||||||
PVOID FreePageContext)
|
PVOID FreePageContext)
|
||||||
{
|
{
|
||||||
MEMORY_AREA* MemoryArea;
|
MEMORY_AREA* MemoryArea;
|
||||||
|
@ -314,17 +314,15 @@ MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
|
||||||
for (i=0; i<(PAGE_ROUND_UP(MemoryArea->Length)/PAGESIZE); i++)
|
for (i=0; i<(PAGE_ROUND_UP(MemoryArea->Length)/PAGESIZE); i++)
|
||||||
{
|
{
|
||||||
ULONG PhysAddr;
|
ULONG PhysAddr;
|
||||||
|
BOOL Dirty;
|
||||||
|
|
||||||
PhysAddr =
|
MmDeleteVirtualMapping(AddressSpace->Process,
|
||||||
MmGetPhysicalAddressForProcess(AddressSpace->Process,
|
MemoryArea->BaseAddress + (i*PAGESIZE),
|
||||||
MemoryArea->BaseAddress + (i*PAGESIZE));
|
FALSE, &Dirty, &PhysAddr);
|
||||||
MmDeleteVirtualMapping(AddressSpace->Process,
|
if (FreePage != NULL)
|
||||||
MemoryArea->BaseAddress + (i*PAGESIZE),
|
|
||||||
FALSE, NULL, NULL);
|
|
||||||
if (FreePage != NULL)
|
|
||||||
{
|
{
|
||||||
FreePage(FreePageContext, MemoryArea,
|
FreePage(FreePageContext, MemoryArea,
|
||||||
MemoryArea->BaseAddress + (i * PAGESIZE), PhysAddr);
|
MemoryArea->BaseAddress + (i * PAGESIZE), PhysAddr, Dirty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: mm.c,v 1.51 2001/12/27 23:56:42 dwelch Exp $
|
/* $Id: mm.c,v 1.52 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top directory
|
* COPYRIGHT: See COPYING in the top directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -245,7 +245,14 @@ NTSTATUS MmAccessFault(KPROCESSOR_MODE Mode,
|
||||||
NTSTATUS MmCommitPagedPoolAddress(PVOID Address)
|
NTSTATUS MmCommitPagedPoolAddress(PVOID Address)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PVOID AllocatedPage = MmAllocPage(0);
|
PVOID AllocatedPage;
|
||||||
|
Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||||
|
Status = MmRequestPageMemoryConsumer(MC_PPOOL, TRUE, &AllocatedPage);
|
||||||
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||||
|
}
|
||||||
Status =
|
Status =
|
||||||
MmCreateVirtualMapping(NULL,
|
MmCreateVirtualMapping(NULL,
|
||||||
(PVOID)PAGE_ROUND_DOWN(Address),
|
(PVOID)PAGE_ROUND_DOWN(Address),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: mminit.c,v 1.28 2001/12/20 03:56:09 dwelch Exp $
|
/* $Id: mminit.c,v 1.29 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top directory
|
* COPYRIGHT: See COPYING in the top directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -180,7 +180,7 @@ VOID MmInitVirtualMemory(ULONG LastKernelAddress,
|
||||||
0,
|
0,
|
||||||
&kernel_shared_data_desc,
|
&kernel_shared_data_desc,
|
||||||
FALSE);
|
FALSE);
|
||||||
MmSharedDataPagePhysicalAddress = MmAllocPage(0);
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &MmSharedDataPagePhysicalAddress);
|
||||||
Status = MmCreateVirtualMapping(NULL,
|
Status = MmCreateVirtualMapping(NULL,
|
||||||
(PVOID)KERNEL_SHARED_DATA_BASE,
|
(PVOID)KERNEL_SHARED_DATA_BASE,
|
||||||
PAGE_READWRITE,
|
PAGE_READWRITE,
|
||||||
|
@ -191,6 +191,11 @@ VOID MmInitVirtualMemory(ULONG LastKernelAddress,
|
||||||
KeBugCheck(0);
|
KeBugCheck(0);
|
||||||
}
|
}
|
||||||
((PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE)->TickCountLow = 0xdeadbeef;
|
((PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE)->TickCountLow = 0xdeadbeef;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID MmInit1(ULONG FirstKrnlPhysAddr,
|
VOID MmInit1(ULONG FirstKrnlPhysAddr,
|
||||||
|
@ -345,6 +350,7 @@ VOID MmInit3(VOID)
|
||||||
{
|
{
|
||||||
MmInitPagerThread();
|
MmInitPagerThread();
|
||||||
MmCreatePhysicalMemorySection();
|
MmCreatePhysicalMemorySection();
|
||||||
|
MmInitializeRmapList();
|
||||||
|
|
||||||
/* FIXME: Read parameters from memory */
|
/* FIXME: Read parameters from memory */
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: mpw.c,v 1.6 2001/08/26 17:29:09 ekohl Exp $
|
/* $Id: mpw.c,v 1.7 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -24,70 +24,10 @@
|
||||||
static HANDLE MpwThreadHandle;
|
static HANDLE MpwThreadHandle;
|
||||||
static CLIENT_ID MpwThreadId;
|
static CLIENT_ID MpwThreadId;
|
||||||
static KEVENT MpwThreadEvent;
|
static KEVENT MpwThreadEvent;
|
||||||
static PEPROCESS LastProcess;
|
|
||||||
static volatile BOOLEAN MpwThreadShouldTerminate;
|
static volatile BOOLEAN MpwThreadShouldTerminate;
|
||||||
static ULONG CountToWrite;
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
VOID MmStartWritingPages(VOID)
|
|
||||||
{
|
|
||||||
CountToWrite = CountToWrite + MmStats.NrDirtyPages;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG MmWritePage(PMADDRESS_SPACE AddressSpace,
|
|
||||||
PVOID Address)
|
|
||||||
{
|
|
||||||
PMEMORY_AREA MArea;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
MArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
|
|
||||||
|
|
||||||
switch(MArea->Type)
|
|
||||||
{
|
|
||||||
case MEMORY_AREA_SYSTEM:
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
|
|
||||||
case MEMORY_AREA_SECTION_VIEW_COMMIT:
|
|
||||||
Status = MmWritePageSectionView(AddressSpace,
|
|
||||||
MArea,
|
|
||||||
Address);
|
|
||||||
return(Status);
|
|
||||||
|
|
||||||
case MEMORY_AREA_VIRTUAL_MEMORY:
|
|
||||||
Status = MmWritePageVirtualMemory(AddressSpace,
|
|
||||||
MArea,
|
|
||||||
Address);
|
|
||||||
return(Status);
|
|
||||||
|
|
||||||
}
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID MmWritePagesInProcess(PEPROCESS Process)
|
|
||||||
{
|
|
||||||
PVOID Address;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
MmLockAddressSpace(&Process->AddressSpace);
|
|
||||||
|
|
||||||
while ((Address = MmGetDirtyPagesFromWorkingSet(Process)) != NULL)
|
|
||||||
{
|
|
||||||
Status = MmWritePage(&Process->AddressSpace, Address);
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
CountToWrite = CountToWrite - 1;
|
|
||||||
if (CountToWrite == 0)
|
|
||||||
{
|
|
||||||
MmUnlockAddressSpace(&Process->AddressSpace);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MmUnlockAddressSpace(&Process->AddressSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
MmMpwThreadMain(PVOID Ignored)
|
MmMpwThreadMain(PVOID Ignored)
|
||||||
{
|
{
|
||||||
|
@ -111,18 +51,6 @@ MmMpwThreadMain(PVOID Ignored)
|
||||||
DbgPrint("MpwThread: Terminating\n");
|
DbgPrint("MpwThread: Terminating\n");
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
KeAttachProcess(LastProcess);
|
|
||||||
MmWritePagesInProcess(LastProcess);
|
|
||||||
KeDetachProcess();
|
|
||||||
if (CountToWrite != 0)
|
|
||||||
{
|
|
||||||
LastProcess = PsGetNextProcess(LastProcess);
|
|
||||||
}
|
|
||||||
} while (CountToWrite > 0 &&
|
|
||||||
LastProcess != PsInitialSystemProcess);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,8 +58,6 @@ NTSTATUS MmInitMpwThread(VOID)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
CountToWrite = 0;
|
|
||||||
LastProcess = PsInitialSystemProcess;
|
|
||||||
MpwThreadShouldTerminate = FALSE;
|
MpwThreadShouldTerminate = FALSE;
|
||||||
KeInitializeEvent(&MpwThreadEvent,
|
KeInitializeEvent(&MpwThreadEvent,
|
||||||
SynchronizationEvent,
|
SynchronizationEvent,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: ncache.c,v 1.12 2001/12/29 14:32:22 dwelch Exp $
|
/* $Id: ncache.c,v 1.13 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -75,7 +75,7 @@ MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
|
||||||
{
|
{
|
||||||
PVOID NPage;
|
PVOID NPage;
|
||||||
|
|
||||||
NPage = MmAllocPageMaybeSwap(0);
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &NPage);
|
||||||
MmCreateVirtualMapping (NULL,
|
MmCreateVirtualMapping (NULL,
|
||||||
Result + (i * PAGESIZE),
|
Result + (i * PAGESIZE),
|
||||||
Attributes,
|
Attributes,
|
||||||
|
@ -85,7 +85,8 @@ MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STATIC
|
VOID STATIC
|
||||||
MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr)
|
MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
|
||||||
|
BOOLEAN Dirty)
|
||||||
{
|
{
|
||||||
if (PhysAddr != 0)
|
if (PhysAddr != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: npool.c,v 1.51 2001/12/20 03:56:09 dwelch Exp $
|
/* $Id: npool.c,v 1.52 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -703,10 +703,16 @@ static BLOCK_HDR* grow_kernel_pool(unsigned int size, ULONG Tag, PVOID Caller)
|
||||||
|
|
||||||
for (i=0;i<nr_pages;i++)
|
for (i=0;i<nr_pages;i++)
|
||||||
{
|
{
|
||||||
Status = MmCreateVirtualMapping(NULL,
|
PVOID Page;
|
||||||
(PVOID)(start + (i*PAGESIZE)),
|
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &Page);
|
||||||
PAGE_READWRITE,
|
if (!NT_SUCCESS(Status))
|
||||||
(ULONG)MmAllocPage(0));
|
{
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
Status = MmCreateVirtualMapping(NULL,
|
||||||
|
(PVOID)(start + (i*PAGESIZE)),
|
||||||
|
PAGE_READWRITE,
|
||||||
|
(ULONG)Page);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DbgPrint("Unable to create virtual mapping\n");
|
DbgPrint("Unable to create virtual mapping\n");
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: pager.c,v 1.8 2001/08/26 17:29:09 ekohl Exp $
|
/* $Id: pager.c,v 1.9 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -24,44 +24,10 @@
|
||||||
static HANDLE PagerThreadHandle;
|
static HANDLE PagerThreadHandle;
|
||||||
static CLIENT_ID PagerThreadId;
|
static CLIENT_ID PagerThreadId;
|
||||||
static KEVENT PagerThreadEvent;
|
static KEVENT PagerThreadEvent;
|
||||||
static PEPROCESS LastProcess;
|
static BOOLEAN PagerThreadShouldTerminate;
|
||||||
static volatile BOOLEAN PagerThreadShouldTerminate;
|
|
||||||
static volatile ULONG PageCount;
|
|
||||||
static volatile ULONG WaiterCount;
|
|
||||||
static KEVENT FreedMemEvent;
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
VOID MmWaitForFreePages(VOID)
|
|
||||||
{
|
|
||||||
InterlockedIncrement((PULONG)&PageCount);
|
|
||||||
KeClearEvent(&FreedMemEvent);
|
|
||||||
KeSetEvent(&PagerThreadEvent,
|
|
||||||
IO_NO_INCREMENT,
|
|
||||||
FALSE);
|
|
||||||
InterlockedIncrement((PULONG)&WaiterCount);
|
|
||||||
KeWaitForSingleObject(&FreedMemEvent,
|
|
||||||
0,
|
|
||||||
KernelMode,
|
|
||||||
FALSE,
|
|
||||||
NULL);
|
|
||||||
InterlockedDecrement((PULONG)&WaiterCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID MmTryPageOutFromProcess(PEPROCESS Process)
|
|
||||||
{
|
|
||||||
ULONG P;
|
|
||||||
|
|
||||||
MmLockAddressSpace(&Process->AddressSpace);
|
|
||||||
P = MmTrimWorkingSet(Process, PageCount);
|
|
||||||
if (P > 0)
|
|
||||||
{
|
|
||||||
InterlockedExchangeAdd((PULONG)&PageCount, -P);
|
|
||||||
KeSetEvent(&FreedMemEvent, IO_NO_INCREMENT, FALSE);
|
|
||||||
}
|
|
||||||
MmUnlockAddressSpace(&Process->AddressSpace);
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS STDCALL
|
static NTSTATUS STDCALL
|
||||||
MmPagerThreadMain(PVOID Ignored)
|
MmPagerThreadMain(PVOID Ignored)
|
||||||
{
|
{
|
||||||
|
@ -84,22 +50,6 @@ MmPagerThreadMain(PVOID Ignored)
|
||||||
DbgPrint("PagerThread: Terminating\n");
|
DbgPrint("PagerThread: Terminating\n");
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (WaiterCount > 0)
|
|
||||||
{
|
|
||||||
while (PageCount > 0)
|
|
||||||
{
|
|
||||||
KeAttachProcess(LastProcess);
|
|
||||||
MmTryPageOutFromProcess(LastProcess);
|
|
||||||
KeDetachProcess();
|
|
||||||
if (PageCount != 0)
|
|
||||||
{
|
|
||||||
LastProcess = PsGetNextProcess(LastProcess);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DbgPrint("Out of memory\n");
|
|
||||||
KeSetEvent(&FreedMemEvent, IO_NO_INCREMENT, FALSE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,16 +57,10 @@ NTSTATUS MmInitPagerThread(VOID)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PageCount = 0;
|
|
||||||
WaiterCount = 0;
|
|
||||||
LastProcess = PsInitialSystemProcess;
|
|
||||||
PagerThreadShouldTerminate = FALSE;
|
PagerThreadShouldTerminate = FALSE;
|
||||||
KeInitializeEvent(&PagerThreadEvent,
|
KeInitializeEvent(&PagerThreadEvent,
|
||||||
SynchronizationEvent,
|
SynchronizationEvent,
|
||||||
FALSE);
|
FALSE);
|
||||||
KeInitializeEvent(&FreedMemEvent,
|
|
||||||
NotificationEvent,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
Status = PsCreateSystemThread(&PagerThreadHandle,
|
Status = PsCreateSystemThread(&PagerThreadHandle,
|
||||||
THREAD_ALL_ACCESS,
|
THREAD_ALL_ACCESS,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: ppool.c,v 1.5 2001/12/26 23:34:07 dwelch Exp $
|
/* $Id: ppool.c,v 1.6 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -122,7 +122,7 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
|
||||||
/*
|
/*
|
||||||
* Is there enough space to create a second block from the unused portion.
|
* Is there enough space to create a second block from the unused portion.
|
||||||
*/
|
*/
|
||||||
if ((BestBlock->Size - BlockSize) > sizeof(PMM_PPOOL_USED_BLOCK_HEADER))
|
if ((BestBlock->Size - BlockSize) > sizeof(MM_PPOOL_FREE_BLOCK_HEADER))
|
||||||
{
|
{
|
||||||
ULONG NewSize = BestBlock->Size - BlockSize;
|
ULONG NewSize = BestBlock->Size - BlockSize;
|
||||||
|
|
||||||
|
|
233
reactos/ntoskrnl/mm/rmap.c
Normal file
233
reactos/ntoskrnl/mm/rmap.c
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/* $Id: rmap.c,v 1.1 2001/12/31 01:53:45 dwelch Exp $
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: ntoskrnl/mm/rmap.c
|
||||||
|
* PURPOSE: kernel memory managment functions
|
||||||
|
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
* Created 27/12/01
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <internal/mm.h>
|
||||||
|
#include <internal/ps.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
/* TYPES ********************************************************************/
|
||||||
|
|
||||||
|
typedef struct _MM_RMAP_ENTRY
|
||||||
|
{
|
||||||
|
struct _MM_RMAP_ENTRY* Next;
|
||||||
|
PEPROCESS Process;
|
||||||
|
PVOID Address;
|
||||||
|
} MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
|
||||||
|
|
||||||
|
/* GLOBALS ******************************************************************/
|
||||||
|
|
||||||
|
static FAST_MUTEX RmapListLock;
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmInitializeRmapList(VOID)
|
||||||
|
{
|
||||||
|
ExInitializeFastMutex(&RmapListLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
MmPageOutPhysicalAddress(PVOID PhysicalAddress)
|
||||||
|
{
|
||||||
|
PMM_RMAP_ENTRY entry;
|
||||||
|
PMEMORY_AREA MemoryArea;
|
||||||
|
ULONG Type;
|
||||||
|
PVOID Address;
|
||||||
|
PEPROCESS Process;
|
||||||
|
PMM_PAGEOP PageOp;
|
||||||
|
LARGE_INTEGER Offset;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
|
entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||||
|
if (entry == NULL)
|
||||||
|
{
|
||||||
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
Process = entry->Process;
|
||||||
|
Address = entry->Address;
|
||||||
|
if ((((ULONG)Address) & 0xFFF) != 0)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
MmLockAddressSpace(&Process->AddressSpace);
|
||||||
|
MemoryArea = MmOpenMemoryAreaByAddress(&Process->AddressSpace, Address);
|
||||||
|
Type = MemoryArea->Type;
|
||||||
|
if (Type == MEMORY_AREA_SECTION_VIEW_COMMIT)
|
||||||
|
{
|
||||||
|
Offset.QuadPart = (ULONG)((Address - (ULONG)MemoryArea->BaseAddress) +
|
||||||
|
MemoryArea->Data.SectionData.ViewOffset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get or create a pageop
|
||||||
|
*/
|
||||||
|
PageOp = MmGetPageOp(MemoryArea, 0, 0, MemoryArea->Data.SectionData.Segment,
|
||||||
|
Offset.u.LowPart, MM_PAGEOP_PAGEOUT);
|
||||||
|
if (PageOp == NULL)
|
||||||
|
{
|
||||||
|
DPRINT1("MmGetPageOp failed\n");
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PageOp->Thread != PsGetCurrentThread())
|
||||||
|
{
|
||||||
|
MmReleasePageOp(PageOp);
|
||||||
|
MmUnlockAddressSpace(&Process->AddressSpace);
|
||||||
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Release locks now we have a page op.
|
||||||
|
*/
|
||||||
|
MmUnlockAddressSpace(&Process->AddressSpace);
|
||||||
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the actual page out work.
|
||||||
|
*/
|
||||||
|
Status = MmPageOutSectionView(&Process->AddressSpace, MemoryArea, Address, PageOp);
|
||||||
|
}
|
||||||
|
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
|
||||||
|
{
|
||||||
|
PageOp = MmGetPageOp(MemoryArea, Process->UniqueProcessId,
|
||||||
|
Address, NULL, 0, MM_PAGEOP_PAGEOUT);
|
||||||
|
if (PageOp->Thread != PsGetCurrentThread())
|
||||||
|
{
|
||||||
|
MmReleasePageOp(PageOp);
|
||||||
|
MmUnlockAddressSpace(&Process->AddressSpace);
|
||||||
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Release locks now we have a page op.
|
||||||
|
*/
|
||||||
|
MmUnlockAddressSpace(&Process->AddressSpace);
|
||||||
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the actual page out work.
|
||||||
|
*/
|
||||||
|
Status = MmPageOutVirtualMemory(&Process->AddressSpace, MemoryArea, Address, PageOp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmInsertRmap(PVOID PhysicalAddress, PEPROCESS Process, PVOID Address)
|
||||||
|
{
|
||||||
|
PMM_RMAP_ENTRY current_entry;
|
||||||
|
PMM_RMAP_ENTRY new_entry;
|
||||||
|
|
||||||
|
new_entry = ExAllocatePool(NonPagedPool, sizeof(MM_RMAP_ENTRY));
|
||||||
|
if (new_entry == NULL)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
new_entry->Address = Address;
|
||||||
|
new_entry->Process = Process;
|
||||||
|
|
||||||
|
if (MmGetPhysicalAddressForProcess(Process, Address)!= (ULONG)PhysicalAddress)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
|
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||||
|
new_entry->Next = current_entry;
|
||||||
|
MmSetRmapListHeadPage(PhysicalAddress, new_entry);
|
||||||
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmDeleteAllRmaps(PVOID PhysicalAddress, PVOID Context,
|
||||||
|
VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process, PVOID Address))
|
||||||
|
{
|
||||||
|
PMM_RMAP_ENTRY current_entry;
|
||||||
|
PMM_RMAP_ENTRY previous_entry;
|
||||||
|
|
||||||
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
|
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||||
|
while (current_entry != NULL)
|
||||||
|
{
|
||||||
|
previous_entry = current_entry;
|
||||||
|
current_entry = current_entry->Next;
|
||||||
|
if (DeleteMapping)
|
||||||
|
{
|
||||||
|
DeleteMapping(Context, previous_entry->Process, previous_entry->Address);
|
||||||
|
}
|
||||||
|
ExFreePool(previous_entry);
|
||||||
|
}
|
||||||
|
MmSetRmapListHeadPage(PhysicalAddress, NULL);
|
||||||
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmDeleteRmap(PVOID PhysicalAddress, PEPROCESS Process, PVOID Address)
|
||||||
|
{
|
||||||
|
PMM_RMAP_ENTRY current_entry, previous_entry;
|
||||||
|
|
||||||
|
ExAcquireFastMutex(&RmapListLock);
|
||||||
|
previous_entry = NULL;
|
||||||
|
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
|
||||||
|
while (current_entry != NULL)
|
||||||
|
{
|
||||||
|
if (current_entry->Process == Process && current_entry->Address == Address)
|
||||||
|
{
|
||||||
|
if (previous_entry == NULL)
|
||||||
|
{
|
||||||
|
MmSetRmapListHeadPage(PhysicalAddress, current_entry->Next);
|
||||||
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
|
ExFreePool(current_entry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
previous_entry->Next = current_entry->Next;
|
||||||
|
ExReleaseFastMutex(&RmapListLock);
|
||||||
|
ExFreePool(current_entry);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
previous_entry = current_entry;
|
||||||
|
current_entry = current_entry->Next;
|
||||||
|
}
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: section.c,v 1.69 2001/12/29 14:32:22 dwelch Exp $
|
/* $Id: section.c,v 1.70 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/mm/section.c
|
* FILE: ntoskrnl/mm/section.c
|
||||||
|
@ -41,6 +41,17 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
/* TYPES *********************************************************************/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PSECTION_OBJECT Section;
|
||||||
|
PMM_SECTION_SEGMENT Segment;
|
||||||
|
LARGE_INTEGER Offset;
|
||||||
|
BOOLEAN WasDirty;
|
||||||
|
BOOLEAN Private;
|
||||||
|
} MM_SECTION_PAGEOUT_CONTEXT;
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
POBJECT_TYPE EXPORTED MmSectionObjectType = NULL;
|
POBJECT_TYPE EXPORTED MmSectionObjectType = NULL;
|
||||||
|
@ -205,7 +216,7 @@ MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||||
return(Entry);
|
return(Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||||
ULONG Offset)
|
ULONG Offset)
|
||||||
{
|
{
|
||||||
|
@ -222,13 +233,15 @@ MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||||
DPRINT1("Maximum share count reached\n");
|
DPRINT1("Maximum share count reached\n");
|
||||||
KeBugCheck(0);
|
KeBugCheck(0);
|
||||||
}
|
}
|
||||||
Entry++;
|
Entry = (Entry & 0xFFFFF000) | (SHARE_COUNT(Entry) + 1);
|
||||||
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
|
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
BOOLEAN
|
||||||
MmUnsharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
|
||||||
ULONG Offset)
|
PMM_SECTION_SEGMENT Segment,
|
||||||
|
ULONG Offset,
|
||||||
|
BOOLEAN Dirty)
|
||||||
{
|
{
|
||||||
ULONG Entry;
|
ULONG Entry;
|
||||||
|
|
||||||
|
@ -243,8 +256,39 @@ MmUnsharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||||
DPRINT1("Zero share count for unshare\n");
|
DPRINT1("Zero share count for unshare\n");
|
||||||
KeBugCheck(0);
|
KeBugCheck(0);
|
||||||
}
|
}
|
||||||
Entry--;
|
Entry = (Entry & 0xFFFFF000) | (SHARE_COUNT(Entry) - 1);
|
||||||
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
|
/*
|
||||||
|
* If we reducing the share count of this entry to zero then set the entry to zero and
|
||||||
|
* tell the cache the page is no longer mapped.
|
||||||
|
*/
|
||||||
|
if (SHARE_COUNT(Entry) == 0)
|
||||||
|
{
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
PREACTOS_COMMON_FCB_HEADER Fcb;
|
||||||
|
|
||||||
|
MmSetPageEntrySectionSegment(Segment, Offset, 0);
|
||||||
|
FileObject = Section->FileObject;
|
||||||
|
if (FileObject != NULL)
|
||||||
|
{
|
||||||
|
Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
|
||||||
|
|
||||||
|
if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
|
||||||
|
(Offset % PAGESIZE) == 0)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
Status = CcRosUnmapCacheSegment(Fcb->Bcb, Offset, Dirty);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MmSetPageEntrySectionSegment(Segment, Offset, Entry);
|
||||||
|
}
|
||||||
|
return(SHARE_COUNT(Entry) > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -336,12 +380,7 @@ MiReadPage(PMEMORY_AREA MemoryArea,
|
||||||
* Allocate a page, this is rather complicated by the possibility
|
* Allocate a page, this is rather complicated by the possibility
|
||||||
* we might have to move other things out of memory
|
* we might have to move other things out of memory
|
||||||
*/
|
*/
|
||||||
(*Page) = MmAllocPage(0);
|
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, Page);
|
||||||
while ((*Page) == NULL)
|
|
||||||
{
|
|
||||||
MmWaitForFreePages();
|
|
||||||
(*Page) = MmAllocPage(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create an mdl to hold the page we are going to read data into.
|
* Create an mdl to hold the page we are going to read data into.
|
||||||
|
@ -471,7 +510,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
|
|
||||||
Page = (PVOID)(Entry & 0xFFFFF000);
|
Page = (PVOID)(Entry & 0xFFFFF000);
|
||||||
MmReferencePage(Page);
|
MmReferencePage(Page);
|
||||||
// MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart);
|
MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart);
|
||||||
|
|
||||||
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||||
Address,
|
Address,
|
||||||
|
@ -482,6 +521,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
DbgPrint("Unable to create virtual mapping\n");
|
DbgPrint("Unable to create virtual mapping\n");
|
||||||
KeBugCheck(0);
|
KeBugCheck(0);
|
||||||
}
|
}
|
||||||
|
MmInsertRmap(Page, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address));
|
||||||
}
|
}
|
||||||
if (Locked)
|
if (Locked)
|
||||||
{
|
{
|
||||||
|
@ -505,6 +545,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
Address,
|
Address,
|
||||||
MemoryArea->Attributes,
|
MemoryArea->Attributes,
|
||||||
Offset.QuadPart);
|
Offset.QuadPart);
|
||||||
|
/* Don't add an rmap entry since the page mapped could be for anything. */
|
||||||
if (Locked)
|
if (Locked)
|
||||||
{
|
{
|
||||||
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
||||||
|
@ -524,26 +565,25 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Map anonymous memory for BSS sections
|
* Map anonymous memory for BSS sections
|
||||||
*/
|
*/
|
||||||
if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS ||
|
if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS)
|
||||||
Segment->Flags & MM_PAGEFILE_SECTION)
|
|
||||||
{
|
{
|
||||||
Page = MmAllocPage(0);
|
Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
|
||||||
while (Page == NULL)
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
MmUnlockSectionSegment(Segment);
|
MmUnlockSectionSegment(Segment);
|
||||||
MmUnlockSection(Section);
|
MmUnlockSection(Section);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
MmWaitForFreePages();
|
MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
MmLockSection(Section);
|
MmLockSection(Section);
|
||||||
MmLockSectionSegment(Segment);
|
MmLockSectionSegment(Segment);
|
||||||
Page = MmAllocPage(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||||
Address,
|
Address,
|
||||||
MemoryArea->Attributes,
|
MemoryArea->Attributes,
|
||||||
(ULONG)Page);
|
(ULONG)Page);
|
||||||
|
MmInsertRmap(Page, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address));
|
||||||
if (Locked)
|
if (Locked)
|
||||||
{
|
{
|
||||||
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
||||||
|
@ -575,7 +615,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Get the entry corresponding to the offset within the section
|
* Get the entry corresponding to the offset within the section
|
||||||
*/
|
*/
|
||||||
Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
|
Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart) & 0xFFFFF000;
|
||||||
|
|
||||||
if (Entry == 0)
|
if (Entry == 0)
|
||||||
{
|
{
|
||||||
|
@ -591,7 +631,14 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
MmUnlockSection(Section);
|
MmUnlockSection(Section);
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
|
|
||||||
Status = MiReadPage(MemoryArea, &Offset, &Page);
|
if (Segment->Flags & MM_PAGEFILE_SECTION)
|
||||||
|
{
|
||||||
|
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = MiReadPage(MemoryArea, &Offset, &Page);
|
||||||
|
}
|
||||||
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
|
if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -620,7 +667,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
* Check the entry. No one should change the status of a page
|
* Check the entry. No one should change the status of a page
|
||||||
* that has a pending page-in.
|
* that has a pending page-in.
|
||||||
*/
|
*/
|
||||||
Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
|
Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) & 0xFFFFF000;
|
||||||
if (Entry != Entry1)
|
if (Entry != Entry1)
|
||||||
{
|
{
|
||||||
DbgPrint("Someone changed ppte entry while we slept\n");
|
DbgPrint("Someone changed ppte entry while we slept\n");
|
||||||
|
@ -633,12 +680,13 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
*/
|
*/
|
||||||
Entry = (ULONG)Page;
|
Entry = (ULONG)Page;
|
||||||
MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
|
MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
|
||||||
// MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
|
MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
|
||||||
|
|
||||||
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||||
Address,
|
Address,
|
||||||
Attributes,
|
Attributes,
|
||||||
(ULONG)Page);
|
(ULONG)Page);
|
||||||
|
MmInsertRmap(Page, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address));
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DbgPrint("Unable to create virtual mapping\n");
|
DbgPrint("Unable to create virtual mapping\n");
|
||||||
|
@ -665,12 +713,13 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
|
|
||||||
Page = (PVOID)Entry;
|
Page = (PVOID)Entry;
|
||||||
MmReferencePage(Page);
|
MmReferencePage(Page);
|
||||||
// MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
|
MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
|
||||||
|
|
||||||
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||||
Address,
|
Address,
|
||||||
Attributes,
|
Attributes,
|
||||||
(ULONG)Page);
|
(ULONG)Page);
|
||||||
|
MmInsertRmap(Page, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address));
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DbgPrint("Unable to create virtual mapping\n");
|
DbgPrint("Unable to create virtual mapping\n");
|
||||||
|
@ -794,12 +843,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Allocate a page
|
* Allocate a page
|
||||||
*/
|
*/
|
||||||
NewPage = MmAllocPage(0);
|
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
|
||||||
while (NewPage == NULL)
|
|
||||||
{
|
|
||||||
MmWaitForFreePages();
|
|
||||||
NewPage = MmAllocPage(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the old page
|
* Copy the old page
|
||||||
|
@ -818,6 +862,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
Address,
|
Address,
|
||||||
MemoryArea->Attributes,
|
MemoryArea->Attributes,
|
||||||
(ULONG)NewPage);
|
(ULONG)NewPage);
|
||||||
|
MmInsertRmap(NewPage, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address));
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DbgPrint("Unable to create virtual mapping\n");
|
DbgPrint("Unable to create virtual mapping\n");
|
||||||
|
@ -827,20 +872,288 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
{
|
{
|
||||||
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unshare the old page.
|
||||||
|
*/
|
||||||
|
MmUnsharePageEntrySectionSegment(Section, Segment, Offset.QuadPart, FALSE);
|
||||||
|
MmDeleteRmap((PVOID)OldPage, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address));
|
||||||
|
MmDereferencePage((PVOID)OldPage);
|
||||||
|
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
MmReleasePageOp(PageOp);
|
MmReleasePageOp(PageOp);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
VOID
|
||||||
|
MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
|
||||||
|
{
|
||||||
|
MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
|
||||||
|
BOOL WasDirty;
|
||||||
|
|
||||||
|
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
|
||||||
|
MmDeleteVirtualMapping(Process,
|
||||||
|
Address,
|
||||||
|
FALSE,
|
||||||
|
&WasDirty,
|
||||||
|
NULL);
|
||||||
|
PageOutContext->WasDirty = PageOutContext->WasDirty || WasDirty;
|
||||||
|
if (!PageOutContext->Private)
|
||||||
|
{
|
||||||
|
MmUnsharePageEntrySectionSegment(PageOutContext->Section,
|
||||||
|
PageOutContext->Segment,
|
||||||
|
PageOutContext->Offset.u.LowPart,
|
||||||
|
PageOutContext->WasDirty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
|
MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
MEMORY_AREA* MemoryArea,
|
MEMORY_AREA* MemoryArea,
|
||||||
PVOID Address,
|
PVOID Address,
|
||||||
PBOOLEAN Ul)
|
PMM_PAGEOP PageOp)
|
||||||
{
|
{
|
||||||
(*Ul) = FALSE;
|
LARGE_INTEGER Offset;
|
||||||
return(0);
|
PSECTION_OBJECT Section;
|
||||||
|
PMM_SECTION_SEGMENT Segment;
|
||||||
|
PVOID PhysicalAddress;
|
||||||
|
MM_SECTION_PAGEOUT_CONTEXT Context;
|
||||||
|
SWAPENTRY SwapEntry;
|
||||||
|
PMDL Mdl;
|
||||||
|
ULONG Entry;
|
||||||
|
BOOLEAN Private;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
PREACTOS_COMMON_FCB_HEADER Fcb;
|
||||||
|
BOOLEAN DirectMapped;
|
||||||
|
|
||||||
|
DPRINT("MmPageOutSection(Process %d, Address 0x%.8X)\n",
|
||||||
|
AddressSpace->Process->UniqueProcessId,
|
||||||
|
Address);
|
||||||
|
|
||||||
|
Address = (PVOID)PAGE_ROUND_DOWN(Address);
|
||||||
|
|
||||||
|
Offset.QuadPart = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) +
|
||||||
|
MemoryArea->Data.SectionData.ViewOffset;
|
||||||
|
|
||||||
|
FileObject = MemoryArea->Data.SectionData.Section->FileObject;
|
||||||
|
DirectMapped = FALSE;
|
||||||
|
if (FileObject != NULL)
|
||||||
|
{
|
||||||
|
Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the file system is letting us go directly to the cache and the
|
||||||
|
* memory area was mapped at an offset in the file which is page aligned
|
||||||
|
* then note this is a direct mapped page.
|
||||||
|
*/
|
||||||
|
if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ &&
|
||||||
|
(Offset.QuadPart % PAGESIZE) == 0)
|
||||||
|
{
|
||||||
|
DirectMapped = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the segment and section.
|
||||||
|
*/
|
||||||
|
Segment = MemoryArea->Data.SectionData.Segment;
|
||||||
|
Section = MemoryArea->Data.SectionData.Section;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This should never happen even mapping of the physical memory are never
|
||||||
|
* placed in the rmap lists.
|
||||||
|
*/
|
||||||
|
if (Segment->Flags & SO_PHYSICAL_MEMORY)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the section segment entry and the physical address.
|
||||||
|
*/
|
||||||
|
Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
|
||||||
|
PhysicalAddress = (PVOID)MmGetPhysicalAddressForProcess(AddressSpace->Process,
|
||||||
|
Address);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare the context structure for the rmap delete call.
|
||||||
|
*/
|
||||||
|
Context.Section = Section;
|
||||||
|
Context.Segment = Segment;
|
||||||
|
Context.Offset = Offset;
|
||||||
|
Context.WasDirty = FALSE;
|
||||||
|
Context.Private = Private = ((PVOID)(Entry & 0xFFFFF000) != PhysicalAddress);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Paging only data mapped read-only is easy.
|
||||||
|
*/
|
||||||
|
if (MemoryArea->Attributes & PAGE_READONLY ||
|
||||||
|
MemoryArea->Attributes & PAGE_EXECUTE_READ)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Delete all mappings of this page.
|
||||||
|
*/
|
||||||
|
MmDeleteAllRmaps(PhysicalAddress, (PVOID)&Context, MmPageOutDeleteMapping);
|
||||||
|
if (Context.WasDirty)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* If this page wasn't direct mapped then we have a private copy so release
|
||||||
|
* back to the system; otherwise the cache manager will have handled freeing
|
||||||
|
* the cache segment which we mapped from.
|
||||||
|
*/
|
||||||
|
if (!DirectMapped)
|
||||||
|
{
|
||||||
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
MmReleasePageOp(PageOp);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Otherwise we have read-write data.
|
||||||
|
*/
|
||||||
|
MmDeleteAllRmaps(PhysicalAddress, (PVOID)&Context, MmPageOutDeleteMapping);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this wasn't a private page then we should have reduced the entry to
|
||||||
|
* zero by deleting all the rmaps.
|
||||||
|
*/
|
||||||
|
if (!Private && MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) != 0)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the page wasn't dirty then we can just free it as for a readonly page.
|
||||||
|
* Since we unmapped all the mappings above we know it will not suddenly
|
||||||
|
* become dirty.
|
||||||
|
*/
|
||||||
|
if (!Context.WasDirty)
|
||||||
|
{
|
||||||
|
if (!DirectMapped)
|
||||||
|
{
|
||||||
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
MmReleasePageOp(PageOp);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this page was direct mapped from the cache then the cache manager
|
||||||
|
* will already have taken care of writing it back.
|
||||||
|
*/
|
||||||
|
if (DirectMapped)
|
||||||
|
{
|
||||||
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
MmReleasePageOp(PageOp);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If necessary, allocate an entry in the paging file for this page
|
||||||
|
*/
|
||||||
|
SwapEntry = MmGetSavedSwapEntryPage((PVOID)PhysicalAddress);
|
||||||
|
if (SwapEntry == 0)
|
||||||
|
{
|
||||||
|
SwapEntry = MmAllocSwapPage();
|
||||||
|
if (SwapEntry == 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* For private pages restore the old mappings.
|
||||||
|
*/
|
||||||
|
if (Private)
|
||||||
|
{
|
||||||
|
Status = MmCreateVirtualMapping(MemoryArea->Process,
|
||||||
|
Address,
|
||||||
|
MemoryArea->Attributes,
|
||||||
|
(ULONG)PhysicalAddress);
|
||||||
|
MmInsertRmap(PhysicalAddress,
|
||||||
|
MemoryArea->Process,
|
||||||
|
Address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* For non-private pages if the page wasn't direct mapped then
|
||||||
|
* set it back into section segment entry so we don't loose our
|
||||||
|
* copy. Otherwise it will be handled by the cache manager.
|
||||||
|
*/
|
||||||
|
if (!DirectMapped)
|
||||||
|
{
|
||||||
|
MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, (ULONG)PhysicalAddress);
|
||||||
|
MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PageOp->Status = STATUS_UNSUCCESSFUL;
|
||||||
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
MmReleasePageOp(PageOp);
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the page to the pagefile
|
||||||
|
*/
|
||||||
|
Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
|
||||||
|
MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress);
|
||||||
|
Status = MmWriteToSwapPage(SwapEntry, Mdl);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("MM: Failed to write to swap page\n");
|
||||||
|
/*
|
||||||
|
* As above: undo our actions.
|
||||||
|
* FIXME: Also free the swap page.
|
||||||
|
*/
|
||||||
|
if (Private)
|
||||||
|
{
|
||||||
|
Status = MmCreateVirtualMapping(MemoryArea->Process,
|
||||||
|
Address,
|
||||||
|
MemoryArea->Attributes,
|
||||||
|
(ULONG)PhysicalAddress);
|
||||||
|
MmInsertRmap(PhysicalAddress,
|
||||||
|
MemoryArea->Process,
|
||||||
|
Address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!DirectMapped)
|
||||||
|
{
|
||||||
|
MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, (ULONG)PhysicalAddress);
|
||||||
|
MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PageOp->Status = STATUS_UNSUCCESSFUL;
|
||||||
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
MmReleasePageOp(PageOp);
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Otherwise we have succeeded.
|
||||||
|
*/
|
||||||
|
if (!DirectMapped)
|
||||||
|
{
|
||||||
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
MmReleasePageOp(PageOp);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
|
@ -1852,7 +2165,8 @@ NtMapViewOfSection(HANDLE SectionHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STATIC
|
VOID STATIC
|
||||||
MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr)
|
MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
|
||||||
|
BOOLEAN Dirty)
|
||||||
{
|
{
|
||||||
PMEMORY_AREA MArea;
|
PMEMORY_AREA MArea;
|
||||||
ULONG Entry;
|
ULONG Entry;
|
||||||
|
@ -1873,16 +2187,18 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG P
|
||||||
* Just dereference private pages
|
* Just dereference private pages
|
||||||
*/
|
*/
|
||||||
if (PhysAddr != (Entry & 0xFFFFF000))
|
if (PhysAddr != (Entry & 0xFFFFF000))
|
||||||
{
|
{
|
||||||
|
MmDeleteRmap((PVOID)PhysAddr, MArea->Process, Address);
|
||||||
MmDereferencePage((PVOID)PhysAddr);
|
MmDereferencePage((PVOID)PhysAddr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if 0
|
MmUnsharePageEntrySectionSegment(MArea->Data.SectionData.Section,
|
||||||
MmUnsharePageEntrySectionSegment(MArea->Data.SectionData.Segment,
|
MArea->Data.SectionData.Segment,
|
||||||
Offset);
|
Offset,
|
||||||
|
Dirty);
|
||||||
|
MmDeleteRmap((PVOID)PhysAddr, MArea->Process, Address);
|
||||||
MmDereferencePage((PVOID)PhysAddr);
|
MmDereferencePage((PVOID)PhysAddr);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: virtual.c,v 1.50 2001/12/29 14:32:22 dwelch Exp $
|
/* $Id: virtual.c,v 1.51 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top directory
|
* COPYRIGHT: See COPYING in the top directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -95,67 +95,56 @@ MmWritePageVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
NTSTATUS
|
||||||
PMEMORY_AREA MemoryArea,
|
MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
||||||
PVOID Address,
|
PMEMORY_AREA MemoryArea,
|
||||||
PBOOLEAN Ul)
|
PVOID Address,
|
||||||
|
PMM_PAGEOP PageOp)
|
||||||
{
|
{
|
||||||
ULONG PhysicalAddress;
|
PVOID PhysicalAddress;
|
||||||
BOOL WasDirty;
|
BOOL WasDirty;
|
||||||
SWAPENTRY SwapEntry;
|
SWAPENTRY SwapEntry;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
PMM_PAGEOP PageOp;
|
|
||||||
|
|
||||||
/*
|
DPRINT("MmPageOutVirtualMemory(Address 0x%.8X) PID %d\n",
|
||||||
* Get or create a pageop
|
Address, MemoryArea->Process->UniqueProcessId);
|
||||||
*/
|
|
||||||
PageOp = MmGetPageOp(MemoryArea, AddressSpace->Process->UniqueProcessId,
|
|
||||||
(PVOID)PAGE_ROUND_DOWN(Address), NULL, 0,
|
|
||||||
MM_PAGEOP_PAGEOUT);
|
|
||||||
if (PageOp->Thread != PsGetCurrentThread())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* On the assumption that handling pageouts speedly rather than
|
|
||||||
* in strict order is better abandon this one.
|
|
||||||
*/
|
|
||||||
(*Ul) = FALSE;
|
|
||||||
MmReleasePageOp(PageOp);
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Paging out code or readonly data is easy.
|
* Paging out code or readonly data is easy.
|
||||||
*/
|
*/
|
||||||
if ((MemoryArea->Attributes & PAGE_READONLY) ||
|
if ((MemoryArea->Attributes & PAGE_READONLY) ||
|
||||||
(MemoryArea->Attributes & PAGE_EXECUTE_READ))
|
(MemoryArea->Attributes & PAGE_EXECUTE_READ))
|
||||||
{
|
{
|
||||||
MmRemovePageFromWorkingSet(AddressSpace->Process, Address);
|
MmDeleteVirtualMapping(MemoryArea->Process, Address, FALSE,
|
||||||
MmDeleteVirtualMapping(PsGetCurrentProcess(), Address, FALSE,
|
NULL, (PULONG)&PhysicalAddress);
|
||||||
NULL, &PhysicalAddress);
|
MmDeleteAllRmaps(PhysicalAddress, NULL, NULL);
|
||||||
MmDereferencePage((PVOID)PhysicalAddress);
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
|
|
||||||
*Ul = TRUE;
|
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
MmReleasePageOp(PageOp);
|
MmReleasePageOp(PageOp);
|
||||||
return(1);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise this is read-write data
|
* Otherwise this is read-write data
|
||||||
*/
|
*/
|
||||||
MmDeleteVirtualMapping(PsGetCurrentProcess(), Address, FALSE,
|
MmDisableVirtualMapping(MemoryArea->Process, Address,
|
||||||
&WasDirty, &PhysicalAddress);
|
&WasDirty, (PULONG)&PhysicalAddress);
|
||||||
|
if (PhysicalAddress == 0)
|
||||||
|
{
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
if (!WasDirty)
|
if (!WasDirty)
|
||||||
{
|
{
|
||||||
MmRemovePageFromWorkingSet(AddressSpace->Process, Address);
|
MmDeleteVirtualMapping(MemoryArea->Process, Address, FALSE, NULL, NULL);
|
||||||
MmDereferencePage((PVOID)PhysicalAddress);
|
MmDeleteAllRmaps(PhysicalAddress, NULL, NULL);
|
||||||
*Ul = TRUE;
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
MmReleasePageOp(PageOp);
|
MmReleasePageOp(PageOp);
|
||||||
return(1);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -167,15 +156,12 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
||||||
SwapEntry = MmAllocSwapPage();
|
SwapEntry = MmAllocSwapPage();
|
||||||
if (SwapEntry == 0)
|
if (SwapEntry == 0)
|
||||||
{
|
{
|
||||||
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
DPRINT("MM: Out of swap space.\n");
|
||||||
Address,
|
MmEnableVirtualMapping(MemoryArea->Process, Address);
|
||||||
MemoryArea->Attributes,
|
|
||||||
PhysicalAddress);
|
|
||||||
*Ul = FALSE;
|
|
||||||
PageOp->Status = STATUS_UNSUCCESSFUL;
|
PageOp->Status = STATUS_UNSUCCESSFUL;
|
||||||
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
MmReleasePageOp(PageOp);
|
MmReleasePageOp(PageOp);
|
||||||
return(0);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,32 +169,28 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
||||||
* Write the page to the pagefile
|
* Write the page to the pagefile
|
||||||
*/
|
*/
|
||||||
Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
|
Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
|
||||||
MmBuildMdlFromPages(Mdl, &PhysicalAddress);
|
MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress);
|
||||||
Status = MmWriteToSwapPage(SwapEntry, Mdl);
|
Status = MmWriteToSwapPage(SwapEntry, Mdl);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("MM: Failed to write to swap page\n");
|
DPRINT1("MM: Failed to write to swap page\n");
|
||||||
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
MmEnableVirtualMapping(MemoryArea->Process, Address);
|
||||||
Address,
|
|
||||||
MemoryArea->Attributes,
|
|
||||||
PhysicalAddress);
|
|
||||||
*Ul = FALSE;
|
|
||||||
PageOp->Status = STATUS_UNSUCCESSFUL;
|
PageOp->Status = STATUS_UNSUCCESSFUL;
|
||||||
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
MmReleasePageOp(PageOp);
|
MmReleasePageOp(PageOp);
|
||||||
return(0);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise we have succeeded, free the page
|
* Otherwise we have succeeded, free the page
|
||||||
*/
|
*/
|
||||||
MmRemovePageFromWorkingSet(AddressSpace->Process, Address);
|
MmDeleteVirtualMapping(MemoryArea->Process, Address, FALSE, NULL, NULL);
|
||||||
MmDereferencePage((PVOID)PhysicalAddress);
|
MmDeleteAllRmaps(PhysicalAddress, NULL, NULL);
|
||||||
*Ul = TRUE;
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
|
||||||
MmReleasePageOp(PageOp);
|
MmReleasePageOp(PageOp);
|
||||||
return(1);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -324,20 +306,13 @@ MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Try to allocate a page
|
* Try to allocate a page
|
||||||
*/
|
*/
|
||||||
Page = MmAllocPage(0);
|
Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
|
||||||
while (Page == NULL)
|
if (Status == STATUS_NO_MEMORY)
|
||||||
{
|
{
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
MmWaitForFreePages();
|
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
Page = MmAllocPage(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Add the page to the process's working set
|
|
||||||
*/
|
|
||||||
MmAddPageToWorkingSet(PsGetCurrentProcess(),
|
|
||||||
(PVOID)PAGE_ROUND_DOWN(Address));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the page. If we fail because we are out of memory then
|
* Set the page. If we fail because we are out of memory then
|
||||||
|
@ -350,7 +325,7 @@ MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
||||||
while (Status == STATUS_NO_MEMORY)
|
while (Status == STATUS_NO_MEMORY)
|
||||||
{
|
{
|
||||||
MmUnlockAddressSpace(AddressSpace);
|
MmUnlockAddressSpace(AddressSpace);
|
||||||
MmWaitForFreePages();
|
KeBugCheck(0);
|
||||||
MmLockAddressSpace(AddressSpace);
|
MmLockAddressSpace(AddressSpace);
|
||||||
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||||
Address,
|
Address,
|
||||||
|
@ -364,6 +339,11 @@ MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the page to the process's working set
|
||||||
|
*/
|
||||||
|
MmInsertRmap(Page, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finish the operation
|
* Finish the operation
|
||||||
*/
|
*/
|
||||||
|
@ -407,8 +387,8 @@ MmModifyAttributes(PMADDRESS_SPACE AddressSpace,
|
||||||
FALSE, NULL, NULL);
|
FALSE, NULL, NULL);
|
||||||
if (PhysicalAddr.u.LowPart != 0)
|
if (PhysicalAddr.u.LowPart != 0)
|
||||||
{
|
{
|
||||||
MmRemovePageFromWorkingSet(AddressSpace->Process,
|
MmDeleteRmap((PVOID)PhysicalAddr.u.LowPart, AddressSpace->Process,
|
||||||
BaseAddress + (i*PAGESIZE));
|
BaseAddress + (i * PAGESIZE));
|
||||||
MmDereferencePage((PVOID)(ULONG)(PhysicalAddr.u.LowPart));
|
MmDereferencePage((PVOID)(ULONG)(PhysicalAddr.u.LowPart));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1025,13 +1005,14 @@ VOID STATIC
|
||||||
MmFreeVirtualMemoryPage(PVOID Context,
|
MmFreeVirtualMemoryPage(PVOID Context,
|
||||||
MEMORY_AREA* MemoryArea,
|
MEMORY_AREA* MemoryArea,
|
||||||
PVOID Address,
|
PVOID Address,
|
||||||
ULONG PhysicalAddr)
|
ULONG PhysicalAddr,
|
||||||
|
BOOLEAN Dirty)
|
||||||
{
|
{
|
||||||
PEPROCESS Process = (PEPROCESS)Context;
|
PEPROCESS Process = (PEPROCESS)Context;
|
||||||
|
|
||||||
if (PhysicalAddr != 0)
|
if (PhysicalAddr != 0)
|
||||||
{
|
{
|
||||||
MmRemovePageFromWorkingSet(Process, Address);
|
MmDeleteRmap((PVOID)PhysicalAddr, Process, Address);
|
||||||
MmDereferencePage((PVOID)PhysicalAddr);
|
MmDereferencePage((PVOID)PhysicalAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: wset.c,v 1.10 2001/08/03 09:36:19 ei Exp $
|
/* $Id: wset.c,v 1.11 2001/12/31 01:53:45 dwelch Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/mm/wset.c
|
* FILE: ntoskrnl/mm/wset.c
|
||||||
|
@ -33,338 +33,34 @@
|
||||||
#include <internal/ps.h>
|
#include <internal/ps.h>
|
||||||
#include <ntos/minmax.h>
|
#include <ntos/minmax.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
VOID
|
NTSTATUS
|
||||||
KiInitializeCircularQueue(PKCIRCULAR_QUEUE Queue, ULONG MaximumSize,
|
MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
|
||||||
PVOID* Mem)
|
|
||||||
{
|
{
|
||||||
Queue->MaximumSize = MaximumSize;
|
PVOID CurrentPhysicalAddress;
|
||||||
Queue->CurrentSize = 0;
|
PVOID NextPhysicalAddress;
|
||||||
Queue->First = Queue->Last = 0;
|
|
||||||
Queue->Mem = Mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
KiInsertItemCircularQueue(PKCIRCULAR_QUEUE Queue, PVOID Item)
|
|
||||||
{
|
|
||||||
Queue->Mem[Queue->Last] = Item;
|
|
||||||
Queue->Last = (Queue->Last + 1) % Queue->MaximumSize;
|
|
||||||
Queue->CurrentSize++;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
KiRemoveItemCircularQueue(PKCIRCULAR_QUEUE Queue, PVOID Item)
|
|
||||||
{
|
|
||||||
ULONG i, j;
|
|
||||||
|
|
||||||
j = Queue->First;
|
|
||||||
for (i = 0; i < Queue->CurrentSize; i++)
|
|
||||||
{
|
|
||||||
if (Queue->Mem[j] == Item)
|
|
||||||
{
|
|
||||||
if (j != Queue->First)
|
|
||||||
{
|
|
||||||
if (j > 0 && Queue->First <= j)
|
|
||||||
{
|
|
||||||
memmove(&Queue->Mem[Queue->First + 1],
|
|
||||||
&Queue->Mem[Queue->First],
|
|
||||||
sizeof(PVOID) * (j - Queue->First));
|
|
||||||
}
|
|
||||||
else if (j > 0 && Queue->First > j)
|
|
||||||
{
|
|
||||||
memmove(&Queue->Mem[1], &Queue->Mem[0],
|
|
||||||
sizeof(PVOID) * j);
|
|
||||||
Queue->Mem[0] = Queue->Mem[Queue->MaximumSize - 1];
|
|
||||||
memmove(&Queue[Queue->First + 1], &Queue[Queue->First],
|
|
||||||
sizeof(PVOID) *
|
|
||||||
((Queue->MaximumSize - 1) - Queue->First));
|
|
||||||
}
|
|
||||||
else if (j == 0)
|
|
||||||
{
|
|
||||||
Queue->Mem[0] = Queue->Mem[Queue->MaximumSize];
|
|
||||||
memmove(&Queue[Queue->First + 1], &Queue[Queue->First],
|
|
||||||
sizeof(PVOID) *
|
|
||||||
((Queue->MaximumSize - 1) - Queue->First));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Queue->First = (Queue->First + 1) % Queue->MaximumSize;
|
|
||||||
Queue->CurrentSize--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
j = (j + 1) % Queue->MaximumSize;
|
|
||||||
}
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
PVOID
|
|
||||||
MmGetDirtyPagesFromWorkingSet(struct _EPROCESS* Process)
|
|
||||||
{
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MmLockWorkingSet(PEPROCESS Process)
|
|
||||||
{
|
|
||||||
(VOID)KeWaitForMutexObject(&Process->WorkingSetLock,
|
|
||||||
0,
|
|
||||||
KernelMode,
|
|
||||||
FALSE,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID MmUnlockWorkingSet(PEPROCESS Process)
|
|
||||||
{
|
|
||||||
KeReleaseMutex(&Process->WorkingSetLock, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MmInitializeWorkingSet(PEPROCESS Process, PMADDRESS_SPACE AddressSpace)
|
|
||||||
{
|
|
||||||
PVOID BaseAddress;
|
|
||||||
ULONG MaximumLength;
|
|
||||||
PVOID FirstPage;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
/*
|
(*NrFreedPages) = 0;
|
||||||
* The maximum number of pages in the working set is the maximum
|
|
||||||
* of the size of physical memory and the size of the user address space.
|
|
||||||
* In either case the maximum size is 3Mb.
|
|
||||||
*/
|
|
||||||
MaximumLength = MmStats.NrTotalPages - MmStats.NrReservedPages;
|
|
||||||
MaximumLength = min(MaximumLength, KERNEL_BASE / PAGESIZE);
|
|
||||||
MaximumLength = PAGE_ROUND_UP(MaximumLength * sizeof(ULONG));
|
|
||||||
|
|
||||||
FirstPage = MmAllocPageMaybeSwap(0);
|
|
||||||
if (FirstPage == NULL)
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
|
||||||
BaseAddress = NULL;
|
|
||||||
Status = MmCreateMemoryArea(NULL,
|
|
||||||
MmGetKernelAddressSpace(),
|
|
||||||
MEMORY_AREA_WORKING_SET,
|
|
||||||
&BaseAddress,
|
|
||||||
MaximumLength,
|
|
||||||
0,
|
|
||||||
&AddressSpace->WorkingSetArea,
|
|
||||||
FALSE);
|
|
||||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
KiInitializeCircularQueue(&Process->AddressSpace.WSQueue,
|
|
||||||
MaximumLength,
|
|
||||||
(PVOID*)BaseAddress);
|
|
||||||
KeInitializeMutex(&Process->WorkingSetLock, 1);
|
|
||||||
Process->WorkingSetPage = BaseAddress;
|
|
||||||
Status = MmCreateVirtualMapping(NULL,
|
|
||||||
Process->WorkingSetPage,
|
|
||||||
PAGE_READWRITE,
|
|
||||||
(ULONG)FirstPage);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
memset(Process->WorkingSetPage, 0, 4096);
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG
|
CurrentPhysicalAddress = MmGetLRUFirstUserPage();
|
||||||
MmPageOutPage(PMADDRESS_SPACE AddressSpace,
|
while (CurrentPhysicalAddress != NULL && Target > 0)
|
||||||
PMEMORY_AREA MArea,
|
|
||||||
PVOID Address,
|
|
||||||
PBOOLEAN Ul)
|
|
||||||
{
|
|
||||||
ULONG Count;
|
|
||||||
|
|
||||||
switch(MArea->Type)
|
|
||||||
{
|
|
||||||
case MEMORY_AREA_SYSTEM:
|
|
||||||
*Ul = FALSE;
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
case MEMORY_AREA_SECTION_VIEW_COMMIT:
|
|
||||||
Count = MmPageOutSectionView(AddressSpace,
|
|
||||||
MArea,
|
|
||||||
Address,
|
|
||||||
Ul);
|
|
||||||
return(Count);
|
|
||||||
|
|
||||||
case MEMORY_AREA_VIRTUAL_MEMORY:
|
|
||||||
Count = MmPageOutVirtualMemory(AddressSpace,
|
|
||||||
MArea,
|
|
||||||
Address,
|
|
||||||
Ul);
|
|
||||||
return(Count);
|
|
||||||
|
|
||||||
}
|
|
||||||
*Ul = FALSE;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MmLruAdjustWorkingSet(PEPROCESS Process)
|
|
||||||
{
|
|
||||||
ULONG i, j;
|
|
||||||
PVOID CurrentAddress;
|
|
||||||
|
|
||||||
MmLockWorkingSet(Process);
|
|
||||||
|
|
||||||
j = Process->AddressSpace.WSQueue.First;
|
|
||||||
for (i = 0; i < Process->AddressSpace.WSQueue.CurrentSize; i++)
|
|
||||||
{
|
{
|
||||||
CurrentAddress = Process->AddressSpace.WSQueue.Mem[j];
|
NextPhysicalAddress = MmGetLRUNextUserPage(CurrentPhysicalAddress);
|
||||||
if (MmIsAccessedAndResetAccessPage(Process, CurrentAddress))
|
|
||||||
|
Status = MmPageOutPhysicalAddress(CurrentPhysicalAddress);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DbgPrint("L");
|
DPRINT("Succeeded\n");
|
||||||
KiRemoveItemCircularQueue(&Process->AddressSpace.WSQueue,
|
Target--;
|
||||||
CurrentAddress);
|
(*NrFreedPages)++;
|
||||||
KiInsertItemCircularQueue(&Process->AddressSpace.WSQueue,
|
|
||||||
CurrentAddress);
|
|
||||||
}
|
}
|
||||||
j = (j + 1) % Process->AddressSpace.WSQueue.MaximumSize;
|
|
||||||
|
CurrentPhysicalAddress = NextPhysicalAddress;
|
||||||
}
|
}
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
MmUnlockWorkingSet(Process);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
|
||||||
MmTrimWorkingSet(PEPROCESS Process, ULONG ReduceHint)
|
|
||||||
/*
|
|
||||||
* Reduce the size of the working set of a process
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
ULONG i, j;
|
|
||||||
PMADDRESS_SPACE AddressSpace;
|
|
||||||
ULONG Count;
|
|
||||||
BOOLEAN Ul;
|
|
||||||
|
|
||||||
MmLockWorkingSet(Process);
|
|
||||||
|
|
||||||
AddressSpace = &Process->AddressSpace;
|
|
||||||
|
|
||||||
Count = 0;
|
|
||||||
j = AddressSpace->WSQueue.First;
|
|
||||||
|
|
||||||
for (i = 0; i < AddressSpace->WSQueue.CurrentSize; )
|
|
||||||
{
|
|
||||||
PVOID Address;
|
|
||||||
PMEMORY_AREA MArea;
|
|
||||||
|
|
||||||
Address = AddressSpace->WSQueue.Mem[j];
|
|
||||||
|
|
||||||
MArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
|
|
||||||
if (MArea == NULL)
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Count = Count + MmPageOutPage(AddressSpace, MArea, Address, &Ul);
|
|
||||||
|
|
||||||
if (Ul)
|
|
||||||
{
|
|
||||||
MmLockWorkingSet(Process);
|
|
||||||
|
|
||||||
j = AddressSpace->WSQueue.First;
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
j = (j + 1) % AddressSpace->WSQueue.MaximumSize;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Count == ReduceHint)
|
|
||||||
{
|
|
||||||
MmUnlockWorkingSet(Process);
|
|
||||||
return(Count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MmUnlockWorkingSet(Process);
|
|
||||||
return(Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MmRemovePageFromWorkingSet(PEPROCESS Process, PVOID Address)
|
|
||||||
/*
|
|
||||||
* Remove a page from a process's working set.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
MmLockWorkingSet(Process);
|
|
||||||
|
|
||||||
KiRemoveItemCircularQueue(&Process->AddressSpace.WSQueue, Address);
|
|
||||||
|
|
||||||
MmUnlockWorkingSet(Process);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MmAddPageToWorkingSet(PEPROCESS Process, PVOID Address)
|
|
||||||
/*
|
|
||||||
* insert a page into a process's working set
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
PMADDRESS_SPACE AddressSpace;
|
|
||||||
PVOID NextAddress;
|
|
||||||
|
|
||||||
AddressSpace = &Process->AddressSpace;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This can't happen unless there is a bug.
|
|
||||||
*/
|
|
||||||
if (AddressSpace->WSQueue.CurrentSize == AddressSpace->WSQueue.MaximumSize)
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* lock the working set
|
|
||||||
*/
|
|
||||||
MmLockWorkingSet(Process);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if we are growing the working set then check to see if we need
|
|
||||||
* to allocate a page
|
|
||||||
*/
|
|
||||||
NextAddress =
|
|
||||||
(PVOID)PAGE_ROUND_DOWN((PVOID)&
|
|
||||||
AddressSpace->WSQueue.Mem[AddressSpace->WSQueue.Last]);
|
|
||||||
if (!MmIsPagePresent(NULL, NextAddress))
|
|
||||||
{
|
|
||||||
PVOID Page;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
/* FIXME: This isn't correct */
|
|
||||||
Page = MmAllocPageMaybeSwap(0);
|
|
||||||
if (Page == 0)
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = MmCreateVirtualMapping(NULL,
|
|
||||||
NextAddress,
|
|
||||||
PAGE_READWRITE,
|
|
||||||
(ULONG)Page);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Insert the page in the working set
|
|
||||||
*/
|
|
||||||
KiInsertItemCircularQueue(&AddressSpace->WSQueue, Address);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* And unlock
|
|
||||||
*/
|
|
||||||
MmUnlockWorkingSet(Process);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue