indent using astyle v1.15.3: astyle --style=ansi -c -s3 -S --convert-tabs %1

svn path=/trunk/; revision=9077
This commit is contained in:
Gunnar Dalsnes
2004-04-10 22:36:07 +00:00
parent 4a875cac12
commit dbb520a63f
29 changed files with 9925 additions and 9777 deletions
File diff suppressed because it is too large Load Diff
+40 -40
View File
@@ -1,4 +1,4 @@
/* $Id: aspace.c,v 1.16 2004/03/04 00:07:01 navaraf Exp $
/* $Id: aspace.c,v 1.17 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -26,30 +26,30 @@ STATIC MADDRESS_SPACE KernelAddressSpace;
/* FUNCTIONS *****************************************************************/
VOID
VOID
MmLockAddressSpace(PMADDRESS_SPACE AddressSpace)
{
/*
* Don't bother with locking if we are the first thread.
*/
if (KeGetCurrentThread() == NULL)
{
/*
* Don't bother with locking if we are the first thread.
*/
if (KeGetCurrentThread() == NULL)
{
return;
}
ExAcquireFastMutex(&AddressSpace->Lock);
}
ExAcquireFastMutex(&AddressSpace->Lock);
}
VOID
VOID
MmUnlockAddressSpace(PMADDRESS_SPACE AddressSpace)
{
/*
* Don't bother locking if we are the first thread.
*/
if (KeGetCurrentThread() == NULL)
{
/*
* Don't bother locking if we are the first thread.
*/
if (KeGetCurrentThread() == NULL)
{
return;
}
ExReleaseFastMutex(&AddressSpace->Lock);
}
ExReleaseFastMutex(&AddressSpace->Lock);
}
VOID INIT_FUNCTION
@@ -68,44 +68,44 @@ PMADDRESS_SPACE MmGetKernelAddressSpace(VOID)
return(&KernelAddressSpace);
}
NTSTATUS
NTSTATUS
MmInitializeAddressSpace(PEPROCESS Process,
PMADDRESS_SPACE AddressSpace)
PMADDRESS_SPACE AddressSpace)
{
InitializeListHead(&AddressSpace->MAreaListHead);
ExInitializeFastMutex(&AddressSpace->Lock);
if (Process != NULL)
{
AddressSpace->LowestAddress = MM_LOWEST_USER_ADDRESS;
}
{
AddressSpace->LowestAddress = MM_LOWEST_USER_ADDRESS;
}
else
{
AddressSpace->LowestAddress = KERNEL_BASE;
}
{
AddressSpace->LowestAddress = KERNEL_BASE;
}
AddressSpace->Process = Process;
if (Process != NULL)
{
AddressSpace->PageTableRefCountTable =
ExAllocatePoolWithTag(NonPagedPool, 768 * sizeof(USHORT),
TAG_PTRC);
RtlZeroMemory(AddressSpace->PageTableRefCountTable, 768 * sizeof(USHORT));
AddressSpace->PageTableRefCountTableSize = 768;
}
{
AddressSpace->PageTableRefCountTable =
ExAllocatePoolWithTag(NonPagedPool, 768 * sizeof(USHORT),
TAG_PTRC);
RtlZeroMemory(AddressSpace->PageTableRefCountTable, 768 * sizeof(USHORT));
AddressSpace->PageTableRefCountTableSize = 768;
}
else
{
AddressSpace->PageTableRefCountTable = NULL;
AddressSpace->PageTableRefCountTableSize = 0;
}
{
AddressSpace->PageTableRefCountTable = NULL;
AddressSpace->PageTableRefCountTableSize = 0;
}
return(STATUS_SUCCESS);
}
NTSTATUS
NTSTATUS
MmDestroyAddressSpace(PMADDRESS_SPACE AddressSpace)
{
if (AddressSpace->PageTableRefCountTable != NULL)
{
if (AddressSpace->PageTableRefCountTable != NULL)
{
ExFreePool(AddressSpace->PageTableRefCountTable);
}
}
return(STATUS_SUCCESS);
}
+278 -260
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: balance.c,v 1.26 2004/03/05 11:31:59 hbirr Exp $
/* $Id: balance.c,v 1.27 2004/04/10 22:35:25 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/balance.c
@@ -39,17 +39,19 @@
typedef struct _MM_MEMORY_CONSUMER
{
ULONG PagesUsed;
ULONG PagesTarget;
NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed);
} MM_MEMORY_CONSUMER, *PMM_MEMORY_CONSUMER;
ULONG PagesUsed;
ULONG PagesTarget;
NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed);
}
MM_MEMORY_CONSUMER, *PMM_MEMORY_CONSUMER;
typedef struct _MM_ALLOCATION_REQUEST
{
PHYSICAL_ADDRESS Page;
LIST_ENTRY ListEntry;
KEVENT Event;
} MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST;
PHYSICAL_ADDRESS Page;
LIST_ENTRY ListEntry;
KEVENT Event;
}
MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST;
/* GLOBALS ******************************************************************/
@@ -72,381 +74,397 @@ static LONG MiBalancerWork = 0;
VOID MmPrintMemoryStatistic(VOID)
{
DbgPrint("MC_CACHE %d, MC_USER %d, MC_PPOOL %d, MC_NPPOOL %d, MiNrAvailablePages %d\n",
MiMemoryConsumers[MC_CACHE].PagesUsed, MiMemoryConsumers[MC_USER].PagesUsed,
MiMemoryConsumers[MC_PPOOL].PagesUsed, MiMemoryConsumers[MC_NPPOOL].PagesUsed,
MiNrAvailablePages);
DbgPrint("MC_CACHE %d, MC_USER %d, MC_PPOOL %d, MC_NPPOOL %d, MiNrAvailablePages %d\n",
MiMemoryConsumers[MC_CACHE].PagesUsed, MiMemoryConsumers[MC_USER].PagesUsed,
MiMemoryConsumers[MC_PPOOL].PagesUsed, MiMemoryConsumers[MC_NPPOOL].PagesUsed,
MiNrAvailablePages);
}
VOID INIT_FUNCTION
MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
{
memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
InitializeListHead(&AllocationListHead);
KeInitializeSpinLock(&AllocationListLock);
memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
InitializeListHead(&AllocationListHead);
KeInitializeSpinLock(&AllocationListLock);
MiNrAvailablePages = MiNrTotalPages = NrAvailablePages;
MiNrAvailablePages = MiNrTotalPages = NrAvailablePages;
/* Set up targets. */
MiMinimumAvailablePages = 64;
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 2;
MiMemoryConsumers[MC_USER].PagesTarget =
NrAvailablePages - MiMinimumAvailablePages;
MiMemoryConsumers[MC_PPOOL].PagesTarget = NrAvailablePages / 2;
MiMemoryConsumers[MC_NPPOOL].PagesTarget = 0xFFFFFFFF;
MiMemoryConsumers[MC_NPPOOL].PagesUsed = NrSystemPages;
/* Set up targets. */
MiMinimumAvailablePages = 64;
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 2;
MiMemoryConsumers[MC_USER].PagesTarget =
NrAvailablePages - MiMinimumAvailablePages;
MiMemoryConsumers[MC_PPOOL].PagesTarget = NrAvailablePages / 2;
MiMemoryConsumers[MC_NPPOOL].PagesTarget = 0xFFFFFFFF;
MiMemoryConsumers[MC_NPPOOL].PagesUsed = NrSystemPages;
}
VOID INIT_FUNCTION
MmInitializeMemoryConsumer(ULONG Consumer,
NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
PULONG NrFreed))
MmInitializeMemoryConsumer(ULONG Consumer,
NTSTATUS (*Trim)(ULONG Target, ULONG Priority,
PULONG NrFreed))
{
MiMemoryConsumers[Consumer].Trim = Trim;
MiMemoryConsumers[Consumer].Trim = Trim;
}
NTSTATUS
MmReleasePageMemoryConsumer(ULONG Consumer, PHYSICAL_ADDRESS Page)
{
PMM_ALLOCATION_REQUEST Request;
PLIST_ENTRY Entry;
KIRQL oldIrql;
ULONG OldAvailable;
PMM_ALLOCATION_REQUEST Request;
PLIST_ENTRY Entry;
KIRQL oldIrql;
ULONG OldAvailable;
#if defined(__GNUC__)
if (Page.QuadPart == 0LL)
if (Page.QuadPart == 0LL)
#else
if (Page.QuadPart == 0)
if (Page.QuadPart == 0)
#endif
{
{
DPRINT1("Tried to release page zero.\n");
KEBUGCHECK(0);
}
}
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
if (MmGetReferenceCountPage(Page) == 1)
{
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
if (MmGetReferenceCountPage(Page) == 1)
{
InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
OldAvailable = InterlockedIncrement((LONG *)&MiNrAvailablePages);
if (IsListEmpty(&AllocationListHead) || OldAvailable + 1 < MiMinimumAvailablePages)
{
KeReleaseSpinLock(&AllocationListLock, oldIrql);
MmDereferencePage(Page);
}
{
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);
}
}
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);
}
}
else
{
KeReleaseSpinLock(&AllocationListLock, oldIrql);
MmDereferencePage(Page);
}
}
return(STATUS_SUCCESS);
return(STATUS_SUCCESS);
}
VOID
MiTrimMemoryConsumer(ULONG Consumer)
{
LONG Target;
ULONG NrFreedPages;
LONG Target;
ULONG NrFreedPages;
Target = MiMemoryConsumers[Consumer].PagesUsed -
MiMemoryConsumers[Consumer].PagesTarget;
if (Target < 1)
{
Target = MiMemoryConsumers[Consumer].PagesUsed -
MiMemoryConsumers[Consumer].PagesTarget;
if (Target < 1)
{
Target = 1;
}
}
if (MiMemoryConsumers[Consumer].Trim != NULL)
{
if (MiMemoryConsumers[Consumer].Trim != NULL)
{
MiMemoryConsumers[Consumer].Trim(Target, 0, &NrFreedPages);
}
}
}
VOID
MmRebalanceMemoryConsumers(VOID)
{
LONG Target;
ULONG i;
ULONG NrFreedPages;
NTSTATUS Status;
LONG Target;
ULONG i;
ULONG NrFreedPages;
NTSTATUS Status;
Target = (MiMinimumAvailablePages - MiNrAvailablePages) + MiPagesRequired;
Target = max(Target, (LONG) MiMinimumPagesPerRun);
Target = (MiMinimumAvailablePages - MiNrAvailablePages) + MiPagesRequired;
Target = max(Target, (LONG) MiMinimumPagesPerRun);
for (i = 0; i < MC_MAXIMUM && Target > 0; i++)
{
for (i = 0; i < MC_MAXIMUM && Target > 0; i++)
{
if (MiMemoryConsumers[i].Trim != NULL)
{
Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
Target = Target - NrFreedPages;
}
}
{
Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
Target = Target - NrFreedPages;
}
}
}
static BOOLEAN
MiIsBalancerThread(VOID)
{
return MiBalancerThreadHandle != NULL &&
PsGetCurrentThread() == MiBalancerThreadId.UniqueThread;
return MiBalancerThreadHandle != NULL &&
PsGetCurrentThread() == MiBalancerThreadId.UniqueThread;
}
NTSTATUS
MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
PHYSICAL_ADDRESS* AllocatedPage)
MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
PHYSICAL_ADDRESS* AllocatedPage)
{
ULONG OldUsed;
ULONG OldAvailable;
PHYSICAL_ADDRESS Page;
KIRQL oldIrql;
/*
* Make sure we don't exceed our individual target.
*/
OldUsed = InterlockedIncrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) &&
!MiIsBalancerThread())
{
if (!CanWait)
{
InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
return(STATUS_NO_MEMORY);
}
MiTrimMemoryConsumer(Consumer);
}
ULONG OldUsed;
ULONG OldAvailable;
PHYSICAL_ADDRESS Page;
KIRQL oldIrql;
OldAvailable = InterlockedDecrement((LONG *)&MiNrAvailablePages);
/*
* Allocate always memory for the non paged pool and for the pager thread.
*/
if (Consumer == MC_NPPOOL || MiIsBalancerThread())
{
/*
* Make sure we don't exceed our individual target.
*/
OldUsed = InterlockedIncrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) &&
!MiIsBalancerThread())
{
if (!CanWait)
{
InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
return(STATUS_NO_MEMORY);
}
MiTrimMemoryConsumer(Consumer);
}
OldAvailable = InterlockedDecrement((LONG *)&MiNrAvailablePages);
/*
* Allocate always memory for the non paged pool and for the pager thread.
*/
if (Consumer == MC_NPPOOL || MiIsBalancerThread())
{
Page = MmAllocPage(Consumer, 0);
#if defined(__GNUC__)
if (Page.QuadPart == 0LL)
#else
if (Page.QuadPart == 0)
#endif
{
KEBUGCHECK(0);
}
{
KEBUGCHECK(0);
}
*AllocatedPage = Page;
if (OldAvailable < MiMinimumAvailablePages &&
MiBalancerThreadHandle != NULL)
{
KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
}
MiBalancerThreadHandle != NULL)
{
KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
}
return(STATUS_SUCCESS);
}
}
/*
* Make sure we don't exceed global targets.
*/
if (OldAvailable < MiMinimumAvailablePages)
{
/*
* Make sure we don't exceed global targets.
*/
if (OldAvailable < MiMinimumAvailablePages)
{
MM_ALLOCATION_REQUEST Request;
if (!CanWait)
{
InterlockedIncrement((LONG *)&MiNrAvailablePages);
InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
return(STATUS_NO_MEMORY);
}
{
InterlockedIncrement((LONG *)&MiNrAvailablePages);
InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
return(STATUS_NO_MEMORY);
}
/* Insert an allocation request. */
#if defined(__GNUC__)
Request.Page.QuadPart = 0LL;
#else
Request.Page.QuadPart = 0;
#endif
KeInitializeEvent(&Request.Event, NotificationEvent, FALSE);
InterlockedIncrement((LONG *)&MiPagesRequired);
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
KeAcquireSpinLock(&AllocationListLock, &oldIrql);
if (MiBalancerThreadHandle != NULL)
{
KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
}
{
KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
}
InsertTailList(&AllocationListHead, &Request.ListEntry);
KeReleaseSpinLock(&AllocationListLock, oldIrql);
KeWaitForSingleObject(&Request.Event,
0,
KernelMode,
FALSE,
NULL);
0,
KernelMode,
FALSE,
NULL);
Page = Request.Page;
#if defined(__GNUC__)
if (Page.QuadPart == 0LL)
#else
if (Page.QuadPart == 0)
#endif
{
KEBUGCHECK(0);
}
{
KEBUGCHECK(0);
}
MmTransferOwnershipPage(Page, Consumer);
*AllocatedPage = Page;
InterlockedDecrement((LONG *)&MiPagesRequired);
return(STATUS_SUCCESS);
}
/*
* Actually allocate the page.
*/
Page = MmAllocPage(Consumer, 0);
#if defined(__GNUC__)
if (Page.QuadPart == 0LL)
#else
if (Page.QuadPart == 0)
#endif
{
KEBUGCHECK(0);
}
*AllocatedPage = Page;
}
return(STATUS_SUCCESS);
/*
* Actually allocate the page.
*/
Page = MmAllocPage(Consumer, 0);
#if defined(__GNUC__)
if (Page.QuadPart == 0LL)
#else
if (Page.QuadPart == 0)
#endif
{
KEBUGCHECK(0);
}
*AllocatedPage = Page;
return(STATUS_SUCCESS);
}
VOID STDCALL
MiBalancerThread(PVOID Unused)
{
PVOID WaitObjects[2];
NTSTATUS Status;
ULONG i;
ULONG NrFreedPages;
ULONG NrPagesUsed;
ULONG Target;
BOOLEAN ShouldRun;
PVOID WaitObjects[2];
NTSTATUS Status;
ULONG i;
ULONG NrFreedPages;
ULONG NrPagesUsed;
ULONG Target;
BOOLEAN ShouldRun;
WaitObjects[0] = &MiBalancerEvent;
WaitObjects[1] = &MiBalancerTimer;
WaitObjects[0] = &MiBalancerEvent;
WaitObjects[1] = &MiBalancerTimer;
while (1)
{
while (1)
{
Status = KeWaitForMultipleObjects(2,
WaitObjects,
WaitAny,
Executive,
KernelMode,
FALSE,
NULL,
NULL);
WaitObjects,
WaitAny,
Executive,
KernelMode,
FALSE,
NULL,
NULL);
if (Status == STATUS_SUCCESS)
{
/* MiBalancerEvent */
CHECKPOINT;
while (MiNrAvailablePages < MiMinimumAvailablePages + 5)
{
for (i = 0; i < MC_MAXIMUM; i++)
{
if (MiMemoryConsumers[i].Trim != NULL)
{
NrFreedPages = 0;
Status = MiMemoryConsumers[i].Trim(MiMinimumPagesPerRun, 0, &NrFreedPages);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
}
}
}
InterlockedExchange(&MiBalancerWork, 0);
CHECKPOINT;
}
{
/* MiBalancerEvent */
CHECKPOINT;
while (MiNrAvailablePages < MiMinimumAvailablePages + 5)
{
for (i = 0; i < MC_MAXIMUM; i++)
{
if (MiMemoryConsumers[i].Trim != NULL)
{
NrFreedPages = 0;
Status = MiMemoryConsumers[i].Trim(MiMinimumPagesPerRun, 0, &NrFreedPages);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
}
}
}
InterlockedExchange(&MiBalancerWork, 0);
CHECKPOINT;
}
else if (Status == STATUS_SUCCESS + 1)
{
/* MiBalancerTimer */
ShouldRun = MiNrAvailablePages < MiMinimumAvailablePages + 5 ? TRUE : FALSE;
for (i = 0; i < MC_MAXIMUM; i++)
{
if (MiMemoryConsumers[i].Trim != NULL)
{
NrPagesUsed = MiMemoryConsumers[i].PagesUsed;
if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget || ShouldRun)
{
if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget)
{
Target = max (NrPagesUsed - MiMemoryConsumers[i].PagesTarget,
MiMinimumPagesPerRun);
}
else
{
Target = MiMinimumPagesPerRun;
}
NrFreedPages = 0;
Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
}
}
}
}
{
/* MiBalancerTimer */
ShouldRun = MiNrAvailablePages < MiMinimumAvailablePages + 5 ? TRUE : FALSE;
for (i = 0; i < MC_MAXIMUM; i++)
{
if (MiMemoryConsumers[i].Trim != NULL)
{
NrPagesUsed = MiMemoryConsumers[i].PagesUsed;
if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget || ShouldRun)
{
if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget)
{
Target = max (NrPagesUsed - MiMemoryConsumers[i].PagesTarget,
MiMinimumPagesPerRun);
}
else
{
Target = MiMinimumPagesPerRun;
}
NrFreedPages = 0;
Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
}
}
}
}
else
{
DPRINT1("KeWaitForMultipleObjects failt, status = %x\n", Status);
KEBUGCHECK(0);
}
}
{
DPRINT1("KeWaitForMultipleObjects failt, status = %x\n", Status);
KEBUGCHECK(0);
}
}
}
VOID INIT_FUNCTION
MiInitBalancerThread(VOID)
{
KPRIORITY Priority;
NTSTATUS Status;
KPRIORITY Priority;
NTSTATUS Status;
#if !defined(__GNUC__)
LARGE_INTEGER dummyJunkNeeded;
dummyJunkNeeded.QuadPart = -20000000; /* 2 sec */;
LARGE_INTEGER dummyJunkNeeded;
dummyJunkNeeded.QuadPart = -20000000; /* 2 sec */
;
#endif
CHECKPOINT;
CHECKPOINT;
KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
KeSetTimerEx(&MiBalancerTimer,
KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE);
KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer);
KeSetTimerEx(&MiBalancerTimer,
#if defined(__GNUC__)
(LARGE_INTEGER)(LONGLONG)-20000000LL, /* 2 sec */
(LARGE_INTEGER)(LONGLONG)-20000000LL, /* 2 sec */
#else
dummyJunkNeeded,
dummyJunkNeeded,
#endif
2000, /* 2 sec */
NULL);
2000, /* 2 sec */
NULL);
Status = PsCreateSystemThread(&MiBalancerThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&MiBalancerThreadId,
(PKSTART_ROUTINE) MiBalancerThread,
NULL);
if (!NT_SUCCESS(Status))
{
Status = PsCreateSystemThread(&MiBalancerThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&MiBalancerThreadId,
(PKSTART_ROUTINE) MiBalancerThread,
NULL);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
Priority = LOW_REALTIME_PRIORITY + 1;
NtSetInformationThread(MiBalancerThreadHandle,
ThreadPriority,
&Priority,
sizeof(Priority));
}
Priority = LOW_REALTIME_PRIORITY + 1;
NtSetInformationThread(MiBalancerThreadHandle,
ThreadPriority,
&Priority,
sizeof(Priority));
}
+152 -148
View File
@@ -1,4 +1,4 @@
/* $Id: cont.c,v 1.30 2003/12/31 05:33:03 jfilby Exp $
/* $Id: cont.c,v 1.31 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -20,24 +20,24 @@
/* FUNCTIONS *****************************************************************/
VOID STATIC
MmFreeContinuousPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
BOOLEAN Dirty)
MmFreeContinuousPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
BOOLEAN Dirty)
{
assert(SwapEntry == 0);
if (PhysAddr.QuadPart != 0)
{
assert(SwapEntry == 0);
if (PhysAddr.QuadPart != 0)
{
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr);
}
}
}
PVOID STDCALL
MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes,
IN PHYSICAL_ADDRESS LowestAcceptableAddress OPTIONAL,
IN PHYSICAL_ADDRESS HighestAcceptableAddress,
IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL,
IN MEMORY_CACHING_TYPE CacheType OPTIONAL,
IN ULONG Alignment)
IN PHYSICAL_ADDRESS LowestAcceptableAddress OPTIONAL,
IN PHYSICAL_ADDRESS HighestAcceptableAddress,
IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL,
IN MEMORY_CACHING_TYPE CacheType OPTIONAL,
IN ULONG Alignment)
{
PMEMORY_AREA MArea;
NTSTATUS Status;
@@ -45,7 +45,7 @@ MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes,
PHYSICAL_ADDRESS PBase;
ULONG Attributes;
ULONG i;
Attributes = PAGE_EXECUTE_READWRITE | PAGE_SYSTEM;
if (CacheType == MmNonCached || CacheType == MmWriteCombined)
{
@@ -55,227 +55,231 @@ MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes,
{
Attributes |= PAGE_WRITECOMBINE;
}
MmLockAddressSpace(MmGetKernelAddressSpace());
Status = MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_CONTINUOUS_MEMORY,
&BaseAddress,
NumberOfBytes,
0,
&MArea,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_CONTINUOUS_MEMORY,
&BaseAddress,
NumberOfBytes,
0,
&MArea,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
if (!NT_SUCCESS(Status))
{
return(NULL);
}
{
return(NULL);
}
DPRINT( "Base = %x\n", BaseAddress );
PBase = MmGetContinuousPages(NumberOfBytes,
LowestAcceptableAddress,
HighestAcceptableAddress,
Alignment);
LowestAcceptableAddress,
HighestAcceptableAddress,
Alignment);
#if defined(__GNUC__)
if (PBase.QuadPart == 0LL)
#else
if (PBase.QuadPart == 0)
#endif
{
MmLockAddressSpace(MmGetKernelAddressSpace());
MmFreeMemoryArea(MmGetKernelAddressSpace(),
BaseAddress,
0,
NULL,
NULL);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
return(NULL);
}
{
MmLockAddressSpace(MmGetKernelAddressSpace());
MmFreeMemoryArea(MmGetKernelAddressSpace(),
BaseAddress,
0,
NULL,
NULL);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
return(NULL);
}
for (i = 0; i < (PAGE_ROUND_UP(NumberOfBytes) / 4096); i++)
{
{
#if !defined(__GNUC__)
LARGE_INTEGER dummyJunkNeeded;
dummyJunkNeeded.QuadPart = PBase.QuadPart + (i * 4096);
LARGE_INTEGER dummyJunkNeeded;
dummyJunkNeeded.QuadPart = PBase.QuadPart + (i * 4096);
#endif
MmCreateVirtualMapping(NULL,
(char*)BaseAddress + (i * 4096),
Attributes,
MmCreateVirtualMapping(NULL,
(char*)BaseAddress + (i * 4096),
Attributes,
#if defined(__GNUC__)
(LARGE_INTEGER)(PBase.QuadPart + (i * 4096)),
(LARGE_INTEGER)(PBase.QuadPart + (i * 4096)),
#else
dummyJunkNeeded,
dummyJunkNeeded,
#endif
TRUE);
}
TRUE);
}
return(BaseAddress);
}
/**********************************************************************
* NAME EXPORTED
* MmAllocateContiguousMemory@12
* NAME EXPORTED
* MmAllocateContiguousMemory@12
*
* DESCRIPTION
* Allocates a range of physically contiguous cache aligned
* memory from the non-paged pool.
*
* Allocates a range of physically contiguous cache aligned
* memory from the non-paged pool.
*
* ARGUMENTS
* NumberOfBytes
* Size of the memory block to allocate;
*
* HighestAcceptableAddress
* Highest address valid for the caller.
*
* NumberOfBytes
* Size of the memory block to allocate;
*
* HighestAcceptableAddress
* Highest address valid for the caller.
*
* RETURN VALUE
* The virtual address of the memory block on success;
* NULL on error.
* The virtual address of the memory block on success;
* NULL on error.
*
* NOTE
* Description taken from include/ddk/mmfuncs.h.
* Code taken from ntoskrnl/mm/special.c.
* Description taken from include/ddk/mmfuncs.h.
* Code taken from ntoskrnl/mm/special.c.
*
* REVISIONS
*
* @implemented
*/
PVOID STDCALL
PVOID STDCALL
MmAllocateContiguousMemory (IN ULONG NumberOfBytes,
IN PHYSICAL_ADDRESS HighestAcceptableAddress)
IN PHYSICAL_ADDRESS HighestAcceptableAddress)
{
PHYSICAL_ADDRESS LowestAcceptableAddress;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
LowestAcceptableAddress.QuadPart = 0;
BoundaryAddressMultiple.QuadPart = 0;
return(MmAllocateContiguousAlignedMemory(NumberOfBytes,
LowestAcceptableAddress,
HighestAcceptableAddress,
BoundaryAddressMultiple,
MmCached,
PAGE_SIZE));
PHYSICAL_ADDRESS LowestAcceptableAddress;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
LowestAcceptableAddress.QuadPart = 0;
BoundaryAddressMultiple.QuadPart = 0;
return(MmAllocateContiguousAlignedMemory(NumberOfBytes,
LowestAcceptableAddress,
HighestAcceptableAddress,
BoundaryAddressMultiple,
MmCached,
PAGE_SIZE));
}
/**********************************************************************
* NAME EXPORTED
* MmFreeContiguousMemory@4
* NAME EXPORTED
* MmFreeContiguousMemory@4
*
* DESCRIPTION
* Releases a range of physically contiguous memory allocated
* with MmAllocateContiguousMemory.
*
* Releases a range of physically contiguous memory allocated
* with MmAllocateContiguousMemory.
*
* ARGUMENTS
* BaseAddress
* Virtual address of the memory to be freed.
* BaseAddress
* Virtual address of the memory to be freed.
*
* RETURN VALUE
* None.
* None.
*
* NOTE
* Description taken from include/ddk/mmfuncs.h.
* Code taken from ntoskrnl/mm/special.c.
* Description taken from include/ddk/mmfuncs.h.
* Code taken from ntoskrnl/mm/special.c.
*
* REVISIONS
*
* @implemented
*/
VOID STDCALL
VOID STDCALL
MmFreeContiguousMemory(IN PVOID BaseAddress)
{
MmLockAddressSpace(MmGetKernelAddressSpace());
MmFreeMemoryArea(MmGetKernelAddressSpace(),
BaseAddress,
0,
MmFreeContinuousPage,
NULL);
BaseAddress,
0,
MmFreeContinuousPage,
NULL);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
}
/**********************************************************************
* NAME EXPORTED
* MmAllocateContiguousMemorySpecifyCache@32
* NAME EXPORTED
* MmAllocateContiguousMemorySpecifyCache@32
*
* DESCRIPTION
* Allocates a range of physically contiguous memory
* with a cache parameter.
*
* Allocates a range of physically contiguous memory
* with a cache parameter.
*
* ARGUMENTS
* NumberOfBytes
* Size of the memory block to allocate;
*
* LowestAcceptableAddress
* Lowest address valid for the caller.
*
* HighestAcceptableAddress
* Highest address valid for the caller.
*
* BoundaryAddressMultiple
* Address multiple not to be crossed by allocated buffer (optional).
*
* CacheType
* Type of caching to use.
*
* NumberOfBytes
* Size of the memory block to allocate;
*
* LowestAcceptableAddress
* Lowest address valid for the caller.
*
* HighestAcceptableAddress
* Highest address valid for the caller.
*
* BoundaryAddressMultiple
* Address multiple not to be crossed by allocated buffer (optional).
*
* CacheType
* Type of caching to use.
*
* RETURN VALUE
* The virtual address of the memory block on success;
* NULL on error.
* The virtual address of the memory block on success;
* NULL on error.
*
* REVISIONS
*
* @implemented
*/
PVOID STDCALL
PVOID STDCALL
MmAllocateContiguousMemorySpecifyCache (IN ULONG NumberOfBytes,
IN PHYSICAL_ADDRESS LowestAcceptableAddress,
IN PHYSICAL_ADDRESS HighestAcceptableAddress,
IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL,
IN MEMORY_CACHING_TYPE CacheType)
IN PHYSICAL_ADDRESS LowestAcceptableAddress,
IN PHYSICAL_ADDRESS HighestAcceptableAddress,
IN PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL,
IN MEMORY_CACHING_TYPE CacheType)
{
return(MmAllocateContiguousAlignedMemory(NumberOfBytes,
LowestAcceptableAddress,
HighestAcceptableAddress,
BoundaryAddressMultiple,
CacheType,
PAGE_SIZE));
return(MmAllocateContiguousAlignedMemory(NumberOfBytes,
LowestAcceptableAddress,
HighestAcceptableAddress,
BoundaryAddressMultiple,
CacheType,
PAGE_SIZE));
}
/**********************************************************************
* NAME EXPORTED
* MmFreeContiguousMemorySpecifyCache@12
* NAME EXPORTED
* MmFreeContiguousMemorySpecifyCache@12
*
* DESCRIPTION
* Releases a range of physically contiguous memory allocated
* with MmAllocateContiguousMemorySpecifyCache.
*
* Releases a range of physically contiguous memory allocated
* with MmAllocateContiguousMemorySpecifyCache.
*
* ARGUMENTS
* BaseAddress
* Virtual address of the memory to be freed.
* BaseAddress
* Virtual address of the memory to be freed.
*
* NumberOfBytes
* Size of the memory block to free.
*
* CacheType
* Type of caching used.
*
* NumberOfBytes
* Size of the memory block to free.
*
* CacheType
* Type of caching used.
*
* RETURN VALUE
* None.
* None.
*
* REVISIONS
*
* @implemented
*/
VOID STDCALL
VOID STDCALL
MmFreeContiguousMemorySpecifyCache(IN PVOID BaseAddress,
IN ULONG NumberOfBytes,
IN MEMORY_CACHING_TYPE CacheType)
IN ULONG NumberOfBytes,
IN MEMORY_CACHING_TYPE CacheType)
{
MmLockAddressSpace(MmGetKernelAddressSpace());
MmFreeMemoryArea(MmGetKernelAddressSpace(),
BaseAddress,
NumberOfBytes,
MmFreeContinuousPage,
NULL);
BaseAddress,
NumberOfBytes,
MmFreeContinuousPage,
NULL);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
}
+16 -19
View File
@@ -1,4 +1,4 @@
/* $Id: drvlck.c,v 1.4 2003/07/10 21:05:03 royce Exp $
/* $Id: drvlck.c,v 1.5 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -30,8 +30,8 @@ MmUnlockPagableImageSection(IN PVOID ImageSectionHandle)
* MmLockPagableDataSection
*/
{
// MmUnlockMemoryArea((MEMORY_AREA *)ImageSectionHandle);
UNIMPLEMENTED;
// MmUnlockMemoryArea((MEMORY_AREA *)ImageSectionHandle);
UNIMPLEMENTED;
}
#endif
@@ -42,8 +42,8 @@ MmUnlockPagableImageSection(IN PVOID ImageSectionHandle)
VOID STDCALL
MmLockPagableSectionByHandle(IN PVOID ImageSectionHandle)
{
// MmLockMemoryArea((MEMORY_AREA *)ImageSectionHandle);
UNIMPLEMENTED;
// MmLockMemoryArea((MEMORY_AREA *)ImageSectionHandle);
UNIMPLEMENTED;
}
@@ -51,10 +51,10 @@ MmLockPagableSectionByHandle(IN PVOID ImageSectionHandle)
PVOID
MmLockPagableCodeSection(IN PVOID AddressWithinSection)
{
PVOID Handle;
Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection);
MmLockPagableSectionByHandle(Handle);
return(Handle);
PVOID Handle;
Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection);
MmLockPagableSectionByHandle(Handle);
return(Handle);
}
#endif
@@ -65,10 +65,10 @@ MmLockPagableCodeSection(IN PVOID AddressWithinSection)
PVOID STDCALL
MmLockPagableDataSection(IN PVOID AddressWithinSection)
{
PVOID Handle;
Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection);
MmLockPagableSectionByHandle(Handle);
return(Handle);
PVOID Handle;
Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection);
MmLockPagableSectionByHandle(Handle);
return(Handle);
}
@@ -77,8 +77,7 @@ MmLockPagableDataSection(IN PVOID AddressWithinSection)
*/
VOID STDCALL
MmUnlockPagableImageSection(IN PVOID ImageSectionHandle)
{
}
{}
/*
@@ -86,8 +85,7 @@ MmUnlockPagableImageSection(IN PVOID ImageSectionHandle)
*/
VOID STDCALL
MmPageEntireDriver(IN PVOID AddressWithinSection)
{
}
{}
/*
@@ -95,7 +93,6 @@ MmPageEntireDriver(IN PVOID AddressWithinSection)
*/
VOID STDCALL
MmResetDriverPaging(IN PVOID AddressWithinSection)
{
}
{}
/* EOF */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+46 -46
View File
@@ -28,68 +28,68 @@ extern VOID MmSafeCopyToUserRestart(VOID);
extern ULONG MmGlobalKernelPageDirectory[1024];
BOOLEAN
BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID Address);
/* FUNCTIONS *****************************************************************/
NTSTATUS MmPageFault(ULONG Cs,
PULONG Eip,
PULONG Eax,
ULONG Cr2,
ULONG ErrorCode)
PULONG Eip,
PULONG Eax,
ULONG Cr2,
ULONG ErrorCode)
{
KPROCESSOR_MODE Mode;
NTSTATUS Status;
DPRINT("MmPageFault(Eip %x, Cr2 %x, ErrorCode %x)\n",
Eip, Cr2, ErrorCode);
Eip, Cr2, ErrorCode);
if (ErrorCode & 0x4)
{
Mode = UserMode;
}
{
Mode = UserMode;
}
else
{
Mode = KernelMode;
}
if (Mode == KernelMode && Cr2 >= KERNEL_BASE &&
Mmi386MakeKernelPageTableGlobal((PVOID)Cr2))
{
return(STATUS_SUCCESS);
}
{
Mode = KernelMode;
}
if (Mode == KernelMode && Cr2 >= KERNEL_BASE &&
Mmi386MakeKernelPageTableGlobal((PVOID)Cr2))
{
return(STATUS_SUCCESS);
}
if (ErrorCode & 0x1)
{
Status = MmAccessFault(Mode, Cr2, FALSE);
}
{
Status = MmAccessFault(Mode, Cr2, FALSE);
}
else
{
Status = MmNotPresentFault(Mode, Cr2, FALSE);
}
{
Status = MmNotPresentFault(Mode, Cr2, FALSE);
}
if (KeGetCurrentThread() != NULL &&
KeGetCurrentThread()->Alerted[1] != 0 &&
Cs != KERNEL_CS)
{
KiDeliverNormalApc();
}
KeGetCurrentThread()->Alerted[1] != 0 &&
Cs != KERNEL_CS)
{
KiDeliverNormalApc();
}
if (!NT_SUCCESS(Status) && (Mode == KernelMode) &&
((*Eip) >= (ULONG)MmSafeCopyFromUserUnsafeStart) &&
((*Eip) <= (ULONG)MmSafeCopyFromUserRestart))
{
(*Eip) = (ULONG)MmSafeCopyFromUserRestart;
(*Eax) = STATUS_ACCESS_VIOLATION;
return(STATUS_SUCCESS);
}
((*Eip) >= (ULONG)MmSafeCopyFromUserUnsafeStart) &&
((*Eip) <= (ULONG)MmSafeCopyFromUserRestart))
{
(*Eip) = (ULONG)MmSafeCopyFromUserRestart;
(*Eax) = STATUS_ACCESS_VIOLATION;
return(STATUS_SUCCESS);
}
if (!NT_SUCCESS(Status) && (Mode == KernelMode) &&
((*Eip) >= (ULONG)MmSafeCopyToUserUnsafeStart) &&
((*Eip) <= (ULONG)MmSafeCopyToUserRestart))
{
(*Eip) = (ULONG)MmSafeCopyToUserRestart;
(*Eax) = STATUS_ACCESS_VIOLATION;
return(STATUS_SUCCESS);
}
((*Eip) >= (ULONG)MmSafeCopyToUserUnsafeStart) &&
((*Eip) <= (ULONG)MmSafeCopyToUserRestart))
{
(*Eip) = (ULONG)MmSafeCopyToUserRestart;
(*Eax) = STATUS_ACCESS_VIOLATION;
return(STATUS_SUCCESS);
}
return(Status);
}
+85 -82
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: iospace.c,v 1.25 2004/01/09 22:52:30 gvg Exp $
/* $Id: iospace.c,v 1.26 2004/04/10 22:35:25 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/iospace.c
@@ -38,37 +38,37 @@
/* FUNCTIONS *****************************************************************/
/**********************************************************************
* NAME EXPORTED
* MmMapIoSpace@16
* NAME EXPORTED
* MmMapIoSpace@16
*
* DESCRIPTION
* Maps a physical memory range into system space.
*
* Maps a physical memory range into system space.
*
* ARGUMENTS
* PhysicalAddress
* First physical address to map;
*
* NumberOfBytes
* Number of bytes to map;
*
* CacheEnable
* TRUE if the range can be cached.
* PhysicalAddress
* First physical address to map;
*
* NumberOfBytes
* Number of bytes to map;
*
* CacheEnable
* TRUE if the range can be cached.
*
* RETURN VALUE
* The base virtual address which maps the region.
* The base virtual address which maps the region.
*
* NOTE
* Description moved here from include/ddk/mmfuncs.h.
* Code taken from ntoskrnl/mm/special.c.
* Description moved here from include/ddk/mmfuncs.h.
* Code taken from ntoskrnl/mm/special.c.
*
* REVISIONS
*
* @implemented
*/
PVOID STDCALL
PVOID STDCALL
MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG NumberOfBytes,
IN BOOLEAN CacheEnable)
IN ULONG NumberOfBytes,
IN BOOLEAN CacheEnable)
{
PVOID Result;
MEMORY_AREA* marea;
@@ -83,110 +83,113 @@ MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress,
MmLockAddressSpace(MmGetKernelAddressSpace());
Result = NULL;
Status = MmCreateMemoryArea (NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_IO_MAPPING,
&Result,
NumberOfBytes,
0,
&marea,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_IO_MAPPING,
&Result,
NumberOfBytes,
0,
&marea,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
if (!NT_SUCCESS(Status))
{
DPRINT("MmMapIoSpace failed (%lx)\n", Status);
return (NULL);
}
{
DPRINT("MmMapIoSpace failed (%lx)\n", Status);
return (NULL);
}
Attributes = PAGE_EXECUTE_READWRITE | PAGE_SYSTEM;
if (!CacheEnable)
{
Attributes |= (PAGE_NOCACHE | PAGE_WRITETHROUGH);
}
{
Attributes |= (PAGE_NOCACHE | PAGE_WRITETHROUGH);
}
for (i = 0; (i < (PAGE_ROUND_UP(NumberOfBytes) / PAGE_SIZE)); i++)
{
{
#if !defined(__GNUC__)
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = PhysicalAddress.QuadPart + (i * PAGE_SIZE);
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = PhysicalAddress.QuadPart + (i * PAGE_SIZE);
#endif
Status =
MmCreateVirtualMappingForKernel((char*)Result + (i * PAGE_SIZE),
Attributes,
Status =
MmCreateVirtualMappingForKernel((char*)Result + (i * PAGE_SIZE),
Attributes,
#if defined(__GNUC__)
(PHYSICAL_ADDRESS)
(PhysicalAddress.QuadPart +
(i * PAGE_SIZE))
(PHYSICAL_ADDRESS)
(PhysicalAddress.QuadPart +
(i * PAGE_SIZE))
#else
dummyJunkNeeded
dummyJunkNeeded
#endif
);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KEBUGCHECK(0);
}
);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KEBUGCHECK(0);
}
#if defined(__GNUC__)
MmMarkPageMapped((PHYSICAL_ADDRESS) (PhysicalAddress.QuadPart +
(i * PAGE_SIZE)));
MmMarkPageMapped((PHYSICAL_ADDRESS) (PhysicalAddress.QuadPart +
(i * PAGE_SIZE)));
#else
MmMarkPageMapped(dummyJunkNeeded);
MmMarkPageMapped(dummyJunkNeeded);
#endif
}
}
return ((PVOID)((char*)Result + PhysicalAddress.QuadPart % PAGE_SIZE));
}
/**********************************************************************
* NAME EXPORTED
* MmUnmapIoSpace@8
* NAME EXPORTED
* MmUnmapIoSpace@8
*
* DESCRIPTION
* Unmaps a physical memory range from system space.
*
* Unmaps a physical memory range from system space.
*
* ARGUMENTS
* BaseAddress
* The base virtual address which maps the region;
*
* NumberOfBytes
* Number of bytes to unmap.
* BaseAddress
* The base virtual address which maps the region;
*
* NumberOfBytes
* Number of bytes to unmap.
*
* RETURN VALUE
* None.
* None.
*
* NOTE
* Code taken from ntoskrnl/mm/special.c.
* Code taken from ntoskrnl/mm/special.c.
*
* REVISIONS
*
* @implemented
*/
VOID STDCALL
VOID STDCALL
MmUnmapIoSpace (IN PVOID BaseAddress,
IN ULONG NumberOfBytes)
IN ULONG NumberOfBytes)
{
MmLockAddressSpace(MmGetKernelAddressSpace());
MmFreeMemoryArea(MmGetKernelAddressSpace(),
(PVOID)(((ULONG)BaseAddress / PAGE_SIZE) * PAGE_SIZE),
NumberOfBytes,
NULL,
NULL);
(PVOID)(((ULONG)BaseAddress / PAGE_SIZE) * PAGE_SIZE),
NumberOfBytes,
NULL,
NULL);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
}
/**********************************************************************
* NAME EXPORTED
* MmMapVideoDisplay@16
* NAME EXPORTED
* MmMapVideoDisplay@16
*
* @implemented
*/
PVOID STDCALL
MmMapVideoDisplay (IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG NumberOfBytes,
IN MEMORY_CACHING_TYPE CacheType)
MmMapVideoDisplay (IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG NumberOfBytes,
IN MEMORY_CACHING_TYPE CacheType)
{
return MmMapIoSpace (PhysicalAddress, NumberOfBytes, (BOOLEAN)CacheType);
return MmMapIoSpace (PhysicalAddress, NumberOfBytes, (BOOLEAN)CacheType);
}
@@ -194,10 +197,10 @@ MmMapVideoDisplay (IN PHYSICAL_ADDRESS PhysicalAddress,
* @implemented
*/
VOID STDCALL
MmUnmapVideoDisplay (IN PVOID BaseAddress,
IN ULONG NumberOfBytes)
MmUnmapVideoDisplay (IN PVOID BaseAddress,
IN ULONG NumberOfBytes)
{
MmUnmapIoSpace (BaseAddress, NumberOfBytes);
MmUnmapIoSpace (BaseAddress, NumberOfBytes);
}
+52 -52
View File
@@ -1,4 +1,4 @@
/* $Id: kmap.c,v 1.31 2004/01/05 14:28:21 weiden Exp $
/* $Id: kmap.c,v 1.32 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -36,64 +36,64 @@ extern ULONG MiKernelMapLength;
/* FUNCTIONS ***************************************************************/
VOID
VOID
ExUnmapPage(PVOID Addr)
{
KIRQL oldIrql;
ULONG Base = ((char*)Addr - (char*)MiKernelMapStart) / PAGE_SIZE;
DPRINT("ExUnmapPage(Addr %x)\n",Addr);
MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE, NULL, NULL);
KeAcquireSpinLock(&AllocMapLock, &oldIrql);
KeAcquireSpinLock(&AllocMapLock, &oldIrql);
RtlClearBits(&AllocMap, Base, 1);
AllocMapHint = min(AllocMapHint, Base);
KeReleaseSpinLock(&AllocMapLock, oldIrql);
}
PVOID
PVOID
ExAllocatePage(VOID)
{
PHYSICAL_ADDRESS PhysPage;
NTSTATUS Status;
PHYSICAL_ADDRESS PhysPage;
NTSTATUS Status;
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &PhysPage);
if (!NT_SUCCESS(Status))
{
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &PhysPage);
if (!NT_SUCCESS(Status))
{
return(NULL);
}
}
return(ExAllocatePageWithPhysPage(PhysPage));
return(ExAllocatePageWithPhysPage(PhysPage));
}
NTSTATUS
MiZeroPage(PHYSICAL_ADDRESS PhysPage)
{
PVOID TempAddress;
PVOID TempAddress;
TempAddress = ExAllocatePageWithPhysPage(PhysPage);
if (TempAddress == NULL)
{
TempAddress = ExAllocatePageWithPhysPage(PhysPage);
if (TempAddress == NULL)
{
return(STATUS_NO_MEMORY);
}
memset(TempAddress, 0, PAGE_SIZE);
ExUnmapPage(TempAddress);
return(STATUS_SUCCESS);
}
memset(TempAddress, 0, PAGE_SIZE);
ExUnmapPage(TempAddress);
return(STATUS_SUCCESS);
}
NTSTATUS
MiCopyFromUserPage(PHYSICAL_ADDRESS DestPhysPage, PVOID SourceAddress)
{
PVOID TempAddress;
PVOID TempAddress;
TempAddress = ExAllocatePageWithPhysPage(DestPhysPage);
if (TempAddress == NULL)
{
TempAddress = ExAllocatePageWithPhysPage(DestPhysPage);
if (TempAddress == NULL)
{
return(STATUS_NO_MEMORY);
}
memcpy(TempAddress, SourceAddress, PAGE_SIZE);
ExUnmapPage(TempAddress);
return(STATUS_SUCCESS);
}
memcpy(TempAddress, SourceAddress, PAGE_SIZE);
ExUnmapPage(TempAddress);
return(STATUS_SUCCESS);
}
PVOID
@@ -111,15 +111,15 @@ ExAllocatePageWithPhysPage(PHYSICAL_ADDRESS PhysPage)
AllocMapHint = Base + 1;
KeReleaseSpinLock(&AllocMapLock, oldlvl);
Addr = (char*)MiKernelMapStart + Base * PAGE_SIZE;
Status = MmCreateVirtualMapping(NULL,
Addr,
PAGE_READWRITE | PAGE_SYSTEM,
PhysPage,
TRUE);
Status = MmCreateVirtualMapping(NULL,
Addr,
PAGE_READWRITE | PAGE_SYSTEM,
PhysPage,
TRUE);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KEBUGCHECK(0);
DbgPrint("Unable to create virtual mapping\n");
KEBUGCHECK(0);
}
return Addr;
}
@@ -138,22 +138,22 @@ MiInitKernelMap(VOID)
VOID
MiFreeNonPagedPoolRegion(PVOID Addr, ULONG Count, BOOLEAN Free)
{
ULONG i;
ULONG Base = ((char*)Addr - (char*)MiKernelMapStart) / PAGE_SIZE;
KIRQL oldlvl;
for (i = 0; i < Count; i++)
{
MmDeleteVirtualMapping(NULL,
(char*)Addr + (i * PAGE_SIZE),
Free,
NULL,
NULL);
}
KeAcquireSpinLock(&AllocMapLock, &oldlvl);
RtlClearBits(&AllocMap, Base, Count);
AllocMapHint = min(AllocMapHint, Base);
KeReleaseSpinLock(&AllocMapLock, oldlvl);
ULONG i;
ULONG Base = ((char*)Addr - (char*)MiKernelMapStart) / PAGE_SIZE;
KIRQL oldlvl;
for (i = 0; i < Count; i++)
{
MmDeleteVirtualMapping(NULL,
(char*)Addr + (i * PAGE_SIZE),
Free,
NULL,
NULL);
}
KeAcquireSpinLock(&AllocMapLock, &oldlvl);
RtlClearBits(&AllocMap, Base, Count);
AllocMapHint = min(AllocMapHint, Base);
KeReleaseSpinLock(&AllocMapLock, oldlvl);
}
PVOID
+352 -348
View File
@@ -45,163 +45,163 @@ VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead)
{
PLIST_ENTRY current_entry;
MEMORY_AREA* current;
DbgPrint("MmDumpMemoryAreas()\n");
current_entry = ListHead->Flink;
while (current_entry!=ListHead)
{
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n",
current->BaseAddress,current->Length,
(char*)current->BaseAddress+current->Length,current->Attributes,
current->Entry.Flink);
current_entry = current_entry->Flink;
}
{
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n",
current->BaseAddress,current->Length,
(char*)current->BaseAddress+current->Length,current->Attributes,
current->Entry.Flink);
current_entry = current_entry->Flink;
}
DbgPrint("Finished MmDumpMemoryAreas()\n");
}
MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace,
PVOID Address)
PVOID Address)
{
PLIST_ENTRY current_entry;
MEMORY_AREA* current;
PLIST_ENTRY previous_entry;
DPRINT("MmOpenMemoryAreaByAddress(AddressSpace %x, Address %x)\n",
AddressSpace, Address);
AddressSpace, Address);
previous_entry = &AddressSpace->MAreaListHead;
current_entry = AddressSpace->MAreaListHead.Flink;
while (current_entry != &AddressSpace->MAreaListHead)
{
current = CONTAINING_RECORD(current_entry,
MEMORY_AREA,
Entry);
assert(current_entry->Blink->Flink == current_entry);
assert(current_entry->Flink->Blink == current_entry);
assert(previous_entry->Flink == current_entry);
if (current->BaseAddress <= Address &&
(PVOID)((char*)current->BaseAddress + current->Length) > Address)
{
DPRINT("%s() = %x\n",__FUNCTION__,current);
return(current);
}
if (current->BaseAddress > Address)
{
DPRINT("%s() = NULL\n",__FUNCTION__);
return(NULL);
}
previous_entry = current_entry;
current_entry = current_entry->Flink;
}
{
current = CONTAINING_RECORD(current_entry,
MEMORY_AREA,
Entry);
assert(current_entry->Blink->Flink == current_entry);
assert(current_entry->Flink->Blink == current_entry);
assert(previous_entry->Flink == current_entry);
if (current->BaseAddress <= Address &&
(PVOID)((char*)current->BaseAddress + current->Length) > Address)
{
DPRINT("%s() = %x\n",__FUNCTION__,current);
return(current);
}
if (current->BaseAddress > Address)
{
DPRINT("%s() = NULL\n",__FUNCTION__);
return(NULL);
}
previous_entry = current_entry;
current_entry = current_entry->Flink;
}
DPRINT("%s() = NULL\n",__FUNCTION__);
return(NULL);
}
MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
PVOID Address,
ULONG Length)
MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
PVOID Address,
ULONG Length)
{
PLIST_ENTRY current_entry;
MEMORY_AREA* current;
ULONG Extent;
DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n",
AddressSpace, Address, Length);
AddressSpace, Address, Length);
current_entry = AddressSpace->MAreaListHead.Flink;
while (current_entry != &AddressSpace->MAreaListHead)
{
current = CONTAINING_RECORD(current_entry,
MEMORY_AREA,
Entry);
DPRINT("current->BaseAddress %x current->Length %x\n",
current->BaseAddress,current->Length);
if (current->BaseAddress >= Address &&
current->BaseAddress < (PVOID)((char*)Address+Length))
{
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
current);
return(current);
}
Extent = (ULONG)current->BaseAddress + current->Length;
if (Extent > (ULONG)Address &&
Extent < (ULONG)((char*)Address+Length))
{
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
current);
return(current);
}
if (current->BaseAddress <= Address &&
Extent >= (ULONG)((char*)Address+Length))
{
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
current);
return(current);
}
if (current->BaseAddress >= (PVOID)((char*)Address+Length))
{
DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
return(NULL);
}
current_entry = current_entry->Flink;
}
{
current = CONTAINING_RECORD(current_entry,
MEMORY_AREA,
Entry);
DPRINT("current->BaseAddress %x current->Length %x\n",
current->BaseAddress,current->Length);
if (current->BaseAddress >= Address &&
current->BaseAddress < (PVOID)((char*)Address+Length))
{
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
current);
return(current);
}
Extent = (ULONG)current->BaseAddress + current->Length;
if (Extent > (ULONG)Address &&
Extent < (ULONG)((char*)Address+Length))
{
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
current);
return(current);
}
if (current->BaseAddress <= Address &&
Extent >= (ULONG)((char*)Address+Length))
{
DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
current);
return(current);
}
if (current->BaseAddress >= (PVOID)((char*)Address+Length))
{
DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
return(NULL);
}
current_entry = current_entry->Flink;
}
DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0);
return(NULL);
}
static VOID MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace,
MEMORY_AREA* marea)
MEMORY_AREA* marea)
{
PLIST_ENTRY ListHead;
PLIST_ENTRY current_entry;
PLIST_ENTRY inserted_entry = &marea->Entry;
MEMORY_AREA* current;
MEMORY_AREA* next;
MEMORY_AREA* next;
DPRINT("MmInsertMemoryArea(marea %x)\n", marea);
DPRINT("marea->BaseAddress %x\n", marea->BaseAddress);
DPRINT("marea->Length %x\n", marea->Length);
ListHead = &AddressSpace->MAreaListHead;
current_entry = ListHead->Flink;
if (IsListEmpty(ListHead))
{
InsertHeadList(ListHead,&marea->Entry);
return;
}
{
InsertHeadList(ListHead,&marea->Entry);
return;
}
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
if (current->BaseAddress > marea->BaseAddress)
{
InsertHeadList(ListHead,&marea->Entry);
return;
}
{
InsertHeadList(ListHead,&marea->Entry);
return;
}
while (current_entry->Flink!=ListHead)
{
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
if (current->BaseAddress < marea->BaseAddress &&
current->Entry.Flink==ListHead)
{
current_entry->Flink = inserted_entry;
inserted_entry->Flink=ListHead;
inserted_entry->Blink=current_entry;
ListHead->Blink = inserted_entry;
return;
}
if (current->BaseAddress < marea->BaseAddress &&
next->BaseAddress > marea->BaseAddress)
{
inserted_entry->Flink = current_entry->Flink;
inserted_entry->Blink = current_entry;
inserted_entry->Flink->Blink = inserted_entry;
current_entry->Flink=inserted_entry;
return;
}
current_entry = current_entry->Flink;
}
{
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
if (current->BaseAddress < marea->BaseAddress &&
current->Entry.Flink==ListHead)
{
current_entry->Flink = inserted_entry;
inserted_entry->Flink=ListHead;
inserted_entry->Blink=current_entry;
ListHead->Blink = inserted_entry;
return;
}
if (current->BaseAddress < marea->BaseAddress &&
next->BaseAddress > marea->BaseAddress)
{
inserted_entry->Flink = current_entry->Flink;
inserted_entry->Blink = current_entry;
inserted_entry->Flink->Blink = inserted_entry;
current_entry->Flink=inserted_entry;
return;
}
current_entry = current_entry->Flink;
}
InsertTailList(ListHead,inserted_entry);
}
@@ -214,136 +214,136 @@ PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length)
MEMORY_AREA* next;
ULONG Gap;
PVOID Address;
DPRINT("MmFindGapBottomUp(Length %x)\n",Length);
ListHead = &AddressSpace->MAreaListHead;
current_entry = ListHead->Flink;
while (current_entry->Flink!=ListHead)
{
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
Gap = (char*)next->BaseAddress - ((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length));
if (Gap >= Length)
{
return((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length));
}
current_entry = current_entry->Flink;
}
{
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
Gap = (char*)next->BaseAddress - ((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length));
if (Gap >= Length)
{
return((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length));
}
current_entry = current_entry->Flink;
}
if (current_entry == ListHead)
{
Address = (PVOID)AddressSpace->LowestAddress;
}
{
Address = (PVOID)AddressSpace->LowestAddress;
}
else
{
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
Address = (char*)current->BaseAddress + PAGE_ROUND_UP(current->Length);
}
{
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
Address = (char*)current->BaseAddress + PAGE_ROUND_UP(current->Length);
}
/* Check if enough space for the block */
if (AddressSpace->LowestAddress < KERNEL_BASE)
{
if ((ULONG)Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG)Address)
{
return NULL;
}
}
{
if ((ULONG)Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG)Address)
{
return NULL;
}
}
else
{
if (Length >= 0xFFFFFFFF - (ULONG)Address)
{
return NULL;
}
}
{
if (Length >= 0xFFFFFFFF - (ULONG)Address)
{
return NULL;
}
}
return Address;
}
PVOID MmFindGapTopDown(PMADDRESS_SPACE AddressSpace, ULONG Length)
{
PLIST_ENTRY ListHead;
PLIST_ENTRY current_entry;
MEMORY_AREA* current;
ULONG Gap;
PVOID Address;
PVOID TopAddress;
PVOID BottomAddress;
PVOID HighestAddress;
PLIST_ENTRY ListHead;
PLIST_ENTRY current_entry;
MEMORY_AREA* current;
ULONG Gap;
PVOID Address;
PVOID TopAddress;
PVOID BottomAddress;
PVOID HighestAddress;
DPRINT("MmFindGapTopDown(Length %lx)\n",Length);
DPRINT("MmFindGapTopDown(Length %lx)\n",Length);
if (AddressSpace->LowestAddress < KERNEL_BASE) //(ULONG_PTR)MmSystemRangeStart)
{
if (AddressSpace->LowestAddress < KERNEL_BASE) //(ULONG_PTR)MmSystemRangeStart)
{
HighestAddress = MmHighestUserAddress;
}
else
{
}
else
{
HighestAddress = (PVOID)0xFFFFFFFF;
}
}
TopAddress = HighestAddress;
TopAddress = HighestAddress;
ListHead = &AddressSpace->MAreaListHead;
current_entry = ListHead->Blink;
while (current_entry->Blink != ListHead)
{
ListHead = &AddressSpace->MAreaListHead;
current_entry = ListHead->Blink;
while (current_entry->Blink != ListHead)
{
current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
BottomAddress = (char*)current->BaseAddress + PAGE_ROUND_UP(current->Length);
DPRINT("Base %p Length %lx\n", current->BaseAddress, PAGE_ROUND_UP(current->Length));
if (BottomAddress < HighestAddress)
{
Gap = (char*)TopAddress - (char*)BottomAddress + 1;
DPRINT("Bottom %p Top %p Gap %lx\n", BottomAddress, TopAddress, Gap);
if (Gap >= Length)
{
DPRINT("Found gap at %p\n", (char*)TopAddress - Length);
return((char*)TopAddress - Length + 1);
}
TopAddress = (char*)current->BaseAddress - 1;
}
{
Gap = (char*)TopAddress - (char*)BottomAddress + 1;
DPRINT("Bottom %p Top %p Gap %lx\n", BottomAddress, TopAddress, Gap);
if (Gap >= Length)
{
DPRINT("Found gap at %p\n", (char*)TopAddress - Length);
return((char*)TopAddress - Length + 1);
}
TopAddress = (char*)current->BaseAddress - 1;
}
current_entry = current_entry->Blink;
}
}
if (current_entry == ListHead)
{
if (current_entry == ListHead)
{
Address = (char*)HighestAddress - Length + 1;
}
else
{
Address = (char*)TopAddress - Length + 1;
}
/* Check if enough space for the block */
if (AddressSpace->LowestAddress < KERNEL_BASE)
{
if ((ULONG)Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG)Address)
{
DPRINT("Failed to find gap\n");
return NULL;
}
}
}
else
{
if (Length >= 0xFFFFFFFF - (ULONG)Address)
{
DPRINT("Failed to find gap\n");
return NULL;
}
}
{
Address = (char*)TopAddress - Length + 1;
}
DPRINT("Found gap at %p\n", Address);
return Address;
/* Check if enough space for the block */
if (AddressSpace->LowestAddress < KERNEL_BASE)
{
if ((ULONG)Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG)Address)
{
DPRINT("Failed to find gap\n");
return NULL;
}
}
else
{
if (Length >= 0xFFFFFFFF - (ULONG)Address)
{
DPRINT("Failed to find gap\n");
return NULL;
}
}
DPRINT("Found gap at %p\n", Address);
return Address;
}
PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, BOOL TopDown)
{
if (TopDown)
return MmFindGapTopDown(AddressSpace, Length);
if (TopDown)
return MmFindGapTopDown(AddressSpace, Length);
return MmFindGapBottomUp(AddressSpace, Length);
return MmFindGapBottomUp(AddressSpace, Length);
}
@@ -357,92 +357,94 @@ MmInitMemoryAreas(VOID)
return(STATUS_SUCCESS);
}
NTSTATUS
NTSTATUS
MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
PVOID BaseAddress,
ULONG Length,
VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea,
PVOID Address, PHYSICAL_ADDRESS PhysAddr,
SWAPENTRY SwapEntry, BOOLEAN Dirty),
PVOID FreePageContext)
PVOID BaseAddress,
ULONG Length,
VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea,
PVOID Address, PHYSICAL_ADDRESS PhysAddr,
SWAPENTRY SwapEntry, BOOLEAN Dirty),
PVOID FreePageContext)
{
MEMORY_AREA* MemoryArea;
ULONG i;
PEPROCESS CurrentProcess = PsGetCurrentProcess();
DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x,"
"FreePageContext %d)\n",AddressSpace,BaseAddress,Length,
FreePageContext);
"FreePageContext %d)\n",AddressSpace,BaseAddress,Length,
FreePageContext);
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
BaseAddress);
BaseAddress);
if (MemoryArea == NULL)
{
KEBUGCHECK(0);
return(STATUS_UNSUCCESSFUL);
}
if (AddressSpace->Process != NULL &&
AddressSpace->Process != CurrentProcess)
{
KeAttachProcess(AddressSpace->Process);
}
for (i=0; i<(PAGE_ROUND_UP(MemoryArea->Length)/PAGE_SIZE); i++)
{
#if defined(__GNUC__)
PHYSICAL_ADDRESS PhysAddr = (PHYSICAL_ADDRESS)0LL;
#else
PHYSICAL_ADDRESS PhysAddr = { 0 };
#endif
BOOL Dirty = FALSE;
SWAPENTRY SwapEntry = 0;
if (MmIsPageSwapEntry(AddressSpace->Process,
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE)))
{
MmDeletePageFileMapping(AddressSpace->Process,
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE),
&SwapEntry);
}
else
{
MmDeleteVirtualMapping(AddressSpace->Process,
(char*)MemoryArea->BaseAddress + (i*PAGE_SIZE),
FALSE, &Dirty, &PhysAddr);
}
if (FreePage != NULL)
{
FreePage(FreePageContext, MemoryArea,
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE), PhysAddr,
SwapEntry, (BOOLEAN)Dirty);
}
}
{
KEBUGCHECK(0);
return(STATUS_UNSUCCESSFUL);
}
if (AddressSpace->Process != NULL &&
AddressSpace->Process != CurrentProcess)
{
KeDetachProcess();
}
AddressSpace->Process != CurrentProcess)
{
KeAttachProcess(AddressSpace->Process);
}
for (i=0; i<(PAGE_ROUND_UP(MemoryArea->Length)/PAGE_SIZE); i++)
{
#if defined(__GNUC__)
PHYSICAL_ADDRESS PhysAddr = (PHYSICAL_ADDRESS)0LL;
#else
PHYSICAL_ADDRESS PhysAddr = { 0 };
#endif
BOOL Dirty = FALSE;
SWAPENTRY SwapEntry = 0;
if (MmIsPageSwapEntry(AddressSpace->Process,
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE)))
{
MmDeletePageFileMapping(AddressSpace->Process,
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE),
&SwapEntry);
}
else
{
MmDeleteVirtualMapping(AddressSpace->Process,
(char*)MemoryArea->BaseAddress + (i*PAGE_SIZE),
FALSE, &Dirty, &PhysAddr);
}
if (FreePage != NULL)
{
FreePage(FreePageContext, MemoryArea,
(char*)MemoryArea->BaseAddress + (i * PAGE_SIZE), PhysAddr,
SwapEntry, (BOOLEAN)Dirty);
}
}
if (AddressSpace->Process != NULL &&
AddressSpace->Process != CurrentProcess)
{
KeDetachProcess();
}
RemoveEntryList(&MemoryArea->Entry);
ExFreePool(MemoryArea);
DPRINT("MmFreeMemoryArea() succeeded\n");
return(STATUS_SUCCESS);
}
PMEMORY_AREA MmSplitMemoryArea(PEPROCESS Process,
PMADDRESS_SPACE AddressSpace,
PMEMORY_AREA OriginalMemoryArea,
PVOID BaseAddress,
ULONG Length,
ULONG NewType,
ULONG NewAttributes)
PMADDRESS_SPACE AddressSpace,
PMEMORY_AREA OriginalMemoryArea,
PVOID BaseAddress,
ULONG Length,
ULONG NewType,
ULONG NewAttributes)
{
PMEMORY_AREA Result;
PMEMORY_AREA Split;
Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
TAG_MAREA);
Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
TAG_MAREA);
RtlZeroMemory(Result,sizeof(MEMORY_AREA));
Result->Type = NewType;
Result->BaseAddress = BaseAddress;
@@ -450,45 +452,45 @@ PMEMORY_AREA MmSplitMemoryArea(PEPROCESS Process,
Result->Attributes = NewAttributes;
Result->LockCount = 0;
Result->Process = Process;
if (BaseAddress == OriginalMemoryArea->BaseAddress)
{
OriginalMemoryArea->BaseAddress = (char*)BaseAddress + Length;
OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
MmInsertMemoryArea(AddressSpace, Result);
return(Result);
}
if (((char*)BaseAddress + Length) ==
((char*)OriginalMemoryArea->BaseAddress + OriginalMemoryArea->Length))
{
OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
MmInsertMemoryArea(AddressSpace, Result);
return(Result);
}
if (BaseAddress == OriginalMemoryArea->BaseAddress)
{
OriginalMemoryArea->BaseAddress = (char*)BaseAddress + Length;
OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
MmInsertMemoryArea(AddressSpace, Result);
return(Result);
}
if (((char*)BaseAddress + Length) ==
((char*)OriginalMemoryArea->BaseAddress + OriginalMemoryArea->Length))
{
OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
MmInsertMemoryArea(AddressSpace, Result);
return(Result);
}
Split = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
TAG_MAREA);
TAG_MAREA);
RtlCopyMemory(Split,OriginalMemoryArea,sizeof(MEMORY_AREA));
Split->BaseAddress = (char*)BaseAddress + Length;
Split->Length = OriginalMemoryArea->Length - (((ULONG)BaseAddress)
+ Length);
Split->Length = OriginalMemoryArea->Length - (((ULONG)BaseAddress)
+ Length);
OriginalMemoryArea->Length = (char*)BaseAddress - (char*)OriginalMemoryArea->BaseAddress;
return(Split);
}
NTSTATUS MmCreateMemoryArea(PEPROCESS Process,
PMADDRESS_SPACE AddressSpace,
ULONG Type,
PVOID* BaseAddress,
ULONG Length,
ULONG Attributes,
MEMORY_AREA** Result,
BOOL FixedAddress,
BOOL TopDown,
PHYSICAL_ADDRESS BoundaryAddressMultiple)
PMADDRESS_SPACE AddressSpace,
ULONG Type,
PVOID* BaseAddress,
ULONG Length,
ULONG Attributes,
MEMORY_AREA** Result,
BOOL FixedAddress,
BOOL TopDown,
PHYSICAL_ADDRESS BoundaryAddressMultiple)
/*
* FUNCTION: Create a memory area
* ARGUMENTS:
@@ -505,64 +507,66 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process,
PVOID EndAddress;
ULONG tmpLength;
DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x,"
"*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
Type,BaseAddress,*BaseAddress,Length,Attributes,Result);
"*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
Type,BaseAddress,*BaseAddress,Length,Attributes,Result);
if ((*BaseAddress) == 0 && !FixedAddress)
{
tmpLength = PAGE_ROUND_UP(Length);
*BaseAddress = MmFindGap(AddressSpace,
PAGE_ROUND_UP(Length) +(PAGE_SIZE*2),
TopDown);
if ((*BaseAddress) == 0)
{
DPRINT("No suitable gap\n");
return(STATUS_NO_MEMORY);
}
{
tmpLength = PAGE_ROUND_UP(Length);
*BaseAddress = MmFindGap(AddressSpace,
PAGE_ROUND_UP(Length) +(PAGE_SIZE*2),
TopDown);
if ((*BaseAddress) == 0)
{
DPRINT("No suitable gap\n");
return(STATUS_NO_MEMORY);
}
#if defined(__GNUC__)
(*BaseAddress)=(*BaseAddress)+PAGE_SIZE;
(*BaseAddress)=(*BaseAddress)+PAGE_SIZE;
#else
{
char* pTemp = *BaseAddress;
pTemp += PAGE_SIZE;
*BaseAddress = pTemp;
}
{
char* pTemp = *BaseAddress;
pTemp += PAGE_SIZE;
*BaseAddress = pTemp;
}
#endif
}
}
else
{
tmpLength = (ULONG)*BaseAddress + Length - PAGE_ROUND_DOWN((*BaseAddress));
(*BaseAddress) = (PVOID)PAGE_ROUND_DOWN((*BaseAddress));
{
tmpLength = (ULONG)*BaseAddress + Length - PAGE_ROUND_DOWN((*BaseAddress));
(*BaseAddress) = (PVOID)PAGE_ROUND_DOWN((*BaseAddress));
if (AddressSpace->LowestAddress == KERNEL_BASE &&
(*BaseAddress) < (PVOID)KERNEL_BASE)
{
return STATUS_ACCESS_VIOLATION;
}
if (AddressSpace->LowestAddress == KERNEL_BASE &&
(*BaseAddress) < (PVOID)KERNEL_BASE)
{
return STATUS_ACCESS_VIOLATION;
}
if (AddressSpace->LowestAddress < KERNEL_BASE &&
(PVOID)((char*)(*BaseAddress) + tmpLength) > (PVOID)KERNEL_BASE)
{
return STATUS_ACCESS_VIOLATION;
}
if (AddressSpace->LowestAddress < KERNEL_BASE &&
(PVOID)((char*)(*BaseAddress) + tmpLength) > (PVOID)KERNEL_BASE)
{
return STATUS_ACCESS_VIOLATION;
}
if (BoundaryAddressMultiple.QuadPart != 0)
{
EndAddress = ((char*)(*BaseAddress)) + tmpLength-1;
assert(((DWORD_PTR)*BaseAddress/BoundaryAddressMultiple.QuadPart) == ((DWORD_PTR)EndAddress/BoundaryAddressMultiple.QuadPart));
}
if (BoundaryAddressMultiple.QuadPart != 0)
{
EndAddress = ((char*)(*BaseAddress)) + tmpLength-1;
assert(((DWORD_PTR)*BaseAddress/BoundaryAddressMultiple.QuadPart) == ((DWORD_PTR)EndAddress/BoundaryAddressMultiple.QuadPart));
}
if (MmOpenMemoryAreaByRegion(AddressSpace,
*BaseAddress,
tmpLength)!=NULL)
{
DPRINT("Memory area already occupied\n");
return(STATUS_CONFLICTING_ADDRESSES);
}
}
if (MmOpenMemoryAreaByRegion(AddressSpace,
*BaseAddress,
tmpLength)!=NULL)
{
DPRINT("Memory area already occupied\n");
return(STATUS_CONFLICTING_ADDRESSES);
}
}
*Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
TAG_MAREA);
TAG_MAREA);
RtlZeroMemory(*Result,sizeof(MEMORY_AREA));
(*Result)->Type = Type;
(*Result)->BaseAddress = *BaseAddress;
@@ -572,9 +576,9 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process,
(*Result)->Process = Process;
(*Result)->PageOpCount = 0;
(*Result)->DeleteInProgress = FALSE;
MmInsertMemoryArea(AddressSpace, *Result);
DPRINT("MmCreateMemoryArea() succeeded\n");
return(STATUS_SUCCESS);
}
+314 -301
View File
@@ -1,4 +1,4 @@
/* $Id: mdl.c,v 1.60 2004/03/13 19:14:16 dwelch Exp $
/* $Id: mdl.c,v 1.61 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -36,55 +36,55 @@ static KSPIN_LOCK MiMdlMappingRegionLock;
VOID INIT_FUNCTION
MmInitializeMdlImplementation(VOID)
{
MEMORY_AREA* Result;
NTSTATUS Status;
PVOID Buffer;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
MEMORY_AREA* Result;
NTSTATUS Status;
PVOID Buffer;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
BoundaryAddressMultiple.QuadPart = 0;
MiMdlMappingRegionHint = 0;
MiMdlMappingRegionBase = NULL;
BoundaryAddressMultiple.QuadPart = 0;
MiMdlMappingRegionHint = 0;
MiMdlMappingRegionBase = NULL;
MmLockAddressSpace(MmGetKernelAddressSpace());
Status = MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_MDL_MAPPING,
&MiMdlMappingRegionBase,
MI_MDL_MAPPING_REGION_SIZE,
0,
&Result,
FALSE,
FALSE,
BoundaryAddressMultiple);
if (!NT_SUCCESS(Status))
{
MmLockAddressSpace(MmGetKernelAddressSpace());
Status = MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_MDL_MAPPING,
&MiMdlMappingRegionBase,
MI_MDL_MAPPING_REGION_SIZE,
0,
&Result,
FALSE,
FALSE,
BoundaryAddressMultiple);
if (!NT_SUCCESS(Status))
{
MmUnlockAddressSpace(MmGetKernelAddressSpace());
KEBUGCHECK(0);
}
MmUnlockAddressSpace(MmGetKernelAddressSpace());
}
MmUnlockAddressSpace(MmGetKernelAddressSpace());
Buffer = ExAllocatePool(NonPagedPool, MI_MDL_MAPPING_REGION_SIZE / (PAGE_SIZE * 8));
Buffer = ExAllocatePool(NonPagedPool, MI_MDL_MAPPING_REGION_SIZE / (PAGE_SIZE * 8));
RtlInitializeBitMap(&MiMdlMappingRegionAllocMap, Buffer, MI_MDL_MAPPING_REGION_SIZE / PAGE_SIZE);
RtlClearAllBits(&MiMdlMappingRegionAllocMap);
RtlInitializeBitMap(&MiMdlMappingRegionAllocMap, Buffer, MI_MDL_MAPPING_REGION_SIZE / PAGE_SIZE);
RtlClearAllBits(&MiMdlMappingRegionAllocMap);
KeInitializeSpinLock(&MiMdlMappingRegionLock);
KeInitializeSpinLock(&MiMdlMappingRegionLock);
}
PVOID
PVOID
MmGetMdlPageAddress(PMDL Mdl, PVOID Offset)
{
PULONG MdlPages;
MdlPages = (PULONG)(Mdl + 1);
return((PVOID)MdlPages[((ULONG)Offset) / PAGE_SIZE]);
}
/*
* @unimplemented
*/
VOID STDCALL
VOID STDCALL
MmUnlockPages(PMDL Mdl)
/*
* FUNCTION: Unlocks the physical pages described by a given MDL
@@ -97,37 +97,39 @@ MmUnlockPages(PMDL Mdl)
{
ULONG i;
PULONG MdlPages;
/*
/*
* FIXME: I don't know whether this right, but it looks sensible
*/
if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) ||
(Mdl->MdlFlags & MDL_IO_PAGE_READ))
{
return;
}
(Mdl->MdlFlags & MDL_IO_PAGE_READ))
{
return;
}
/*
* FIXME: Seems sensible
*/
if (!(Mdl->MdlFlags & MDL_PAGES_LOCKED))
{
return;
}
{
return;
}
MdlPages = (PULONG)(Mdl + 1);
for (i=0; i<(PAGE_ROUND_UP(Mdl->ByteCount+Mdl->ByteOffset)/PAGE_SIZE); i++)
{
{
#if defined(__GNUC__)
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
MmDereferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
MmDereferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
#else
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[i];
MmUnlockPage(dummyJunkNeeded);
MmDereferencePage(dummyJunkNeeded);
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[i];
MmUnlockPage(dummyJunkNeeded);
MmDereferencePage(dummyJunkNeeded);
#endif
}
}
Mdl->MdlFlags = Mdl->MdlFlags & (~MDL_PAGES_LOCKED);
}
@@ -157,103 +159,105 @@ MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode)
DPRINT("MmMapLockedPages(Mdl %x, AccessMode %x)\n", Mdl, AccessMode);
if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) && AccessMode != UserMode)
{
return(Mdl->MappedSystemVa);
}
{
return(Mdl->MappedSystemVa);
}
/* Calculate the number of pages required. */
RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE;
if (AccessMode == UserMode)
{
MEMORY_AREA *Result;
LARGE_INTEGER BoundaryAddressMultiple;
NTSTATUS Status;
{
MEMORY_AREA *Result;
LARGE_INTEGER BoundaryAddressMultiple;
NTSTATUS Status;
BoundaryAddressMultiple.QuadPart = 0;
Base = NULL;
BoundaryAddressMultiple.QuadPart = 0;
Base = NULL;
CurrentProcess = OldProcess = PsGetCurrentProcess();
if (Mdl->Process != CurrentProcess)
{
KeAttachProcess(Mdl->Process);
CurrentProcess = Mdl->Process;
}
CurrentProcess = OldProcess = PsGetCurrentProcess();
if (Mdl->Process != CurrentProcess)
{
KeAttachProcess(Mdl->Process);
CurrentProcess = Mdl->Process;
}
MmLockAddressSpace(&CurrentProcess->AddressSpace);
Status = MmCreateMemoryArea(CurrentProcess,
&CurrentProcess->AddressSpace,
MEMORY_AREA_MDL_MAPPING,
&Base,
RegionSize * PAGE_SIZE,
0, /* PAGE_READWRITE? */
&Result,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmUnlockAddressSpace(&CurrentProcess->AddressSpace);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
/* FIXME: handle this? */
}
}
MmLockAddressSpace(&CurrentProcess->AddressSpace);
Status = MmCreateMemoryArea(CurrentProcess,
&CurrentProcess->AddressSpace,
MEMORY_AREA_MDL_MAPPING,
&Base,
RegionSize * PAGE_SIZE,
0, /* PAGE_READWRITE? */
&Result,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmUnlockAddressSpace(&CurrentProcess->AddressSpace);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
/* FIXME: handle this? */
}
}
else
{
CurrentProcess = OldProcess = NULL;
{
CurrentProcess = OldProcess = NULL;
/* Allocate that number of pages from the mdl mapping region. */
KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql);
/* Allocate that number of pages from the mdl mapping region. */
KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql);
StartingOffset = RtlFindClearBitsAndSet(&MiMdlMappingRegionAllocMap, RegionSize, MiMdlMappingRegionHint);
StartingOffset = RtlFindClearBitsAndSet(&MiMdlMappingRegionAllocMap, RegionSize, MiMdlMappingRegionHint);
if (StartingOffset == 0xffffffff)
{
DPRINT1("Out of MDL mapping space\n");
KEBUGCHECK(0);
}
if (StartingOffset == 0xffffffff)
{
DPRINT1("Out of MDL mapping space\n");
KEBUGCHECK(0);
}
Base = (char*)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE;
Base = (char*)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE;
if (MiMdlMappingRegionHint == StartingOffset)
{
MiMdlMappingRegionHint +=RegionSize;
}
if (MiMdlMappingRegionHint == StartingOffset)
{
MiMdlMappingRegionHint +=RegionSize;
}
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
}
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
}
/* Set the virtual mappings for the MDL pages. */
MdlPages = (PULONG)(Mdl + 1);
for (i = 0; i < RegionSize; i++)
{
NTSTATUS Status;
{
NTSTATUS Status;
#if !defined(__GNUC__)
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[i];
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[i];
#endif
Status = MmCreateVirtualMapping(CurrentProcess,
(PVOID)((ULONG)Base+(i*PAGE_SIZE)),
PAGE_READWRITE,
Status = MmCreateVirtualMapping(CurrentProcess,
(PVOID)((ULONG)Base+(i*PAGE_SIZE)),
PAGE_READWRITE,
#if defined(__GNUC__)
(LARGE_INTEGER)(LONGLONG)MdlPages[i],
(LARGE_INTEGER)(LONGLONG)MdlPages[i],
#else
dummyJunkNeeded,
dummyJunkNeeded,
#endif
FALSE);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KEBUGCHECK(0);
}
}
FALSE);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KEBUGCHECK(0);
}
}
if (AccessMode == UserMode && CurrentProcess != OldProcess)
{
KeDetachProcess();
}
{
KeDetachProcess();
}
/* Mark the MDL has having being mapped. */
Mdl->MdlFlags = Mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
@@ -273,62 +277,64 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl)
* MemoryDescriptorList = MDL describing the mapped pages
*/
{
KIRQL oldIrql;
ULONG i;
ULONG RegionSize;
ULONG Base;
PEPROCESS CurrentProcess, OldProcess;
KIRQL oldIrql;
ULONG i;
ULONG RegionSize;
ULONG Base;
PEPROCESS CurrentProcess, OldProcess;
DPRINT("MmUnmapLockedPages(BaseAddress %x, Mdl %x)\n", BaseAddress, Mdl);
DPRINT("MmUnmapLockedPages(BaseAddress %x, Mdl %x)\n", BaseAddress, Mdl);
/*
* In this case, the MDL has the same system address as the base address
* so there is no need to free it
*/
if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) &&
((ULONG_PTR)BaseAddress >= KERNEL_BASE))
{
/*
* In this case, the MDL has the same system address as the base address
* so there is no need to free it
*/
if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) &&
((ULONG_PTR)BaseAddress >= KERNEL_BASE))
{
return;
}
}
if ((ULONG_PTR)BaseAddress >= KERNEL_BASE)
{
if ((ULONG_PTR)BaseAddress >= KERNEL_BASE)
{
CurrentProcess = OldProcess = NULL;
}
else
{
}
else
{
CurrentProcess = OldProcess = PsGetCurrentProcess();
if (Mdl->Process != CurrentProcess)
{
KeAttachProcess(Mdl->Process);
CurrentProcess = Mdl->Process;
}
}
{
KeAttachProcess(Mdl->Process);
CurrentProcess = Mdl->Process;
}
}
/* Calculate the number of pages we mapped. */
RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE;
/* Calculate the number of pages we mapped. */
RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE;
#if defined(__GNUC__)
BaseAddress -= Mdl->ByteOffset;
BaseAddress -= Mdl->ByteOffset;
#else
{
char* pTemp = BaseAddress;
pTemp -= Mdl->ByteOffset;
BaseAddress = pTemp;
}
{
char* pTemp = BaseAddress;
pTemp -= Mdl->ByteOffset;
BaseAddress = pTemp;
}
#endif
/* Unmap all the pages. */
for (i = 0; i < RegionSize; i++)
{
/* Unmap all the pages. */
for (i = 0; i < RegionSize; i++)
{
MmDeleteVirtualMapping(NULL,
(char*)BaseAddress + (i * PAGE_SIZE),
FALSE,
NULL,
NULL);
}
(char*)BaseAddress + (i * PAGE_SIZE),
FALSE,
NULL,
NULL);
}
if ((DWORD)BaseAddress >= KERNEL_BASE)
{
if ((DWORD)BaseAddress >= KERNEL_BASE)
{
KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql);
/* Deallocate all the pages used. */
Base = (ULONG)((char*)BaseAddress - (char*)MiMdlMappingRegionBase) / PAGE_SIZE;
@@ -338,55 +344,55 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl)
MiMdlMappingRegionHint = min (MiMdlMappingRegionHint, Base);
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
}
else
{
}
else
{
MEMORY_AREA *Marea;
Marea = MmOpenMemoryAreaByAddress( &CurrentProcess->AddressSpace, BaseAddress );
if (Marea == NULL)
{
DPRINT1( "Couldn't open memory area when unmapping user-space pages!\n" );
KEBUGCHECK(0);
}
{
DPRINT1( "Couldn't open memory area when unmapping user-space pages!\n" );
KEBUGCHECK(0);
}
MmFreeMemoryArea( &CurrentProcess->AddressSpace, Marea->BaseAddress, 0, NULL, NULL );
if (CurrentProcess != OldProcess)
{
KeDetachProcess();
}
}
{
KeDetachProcess();
}
}
/* Reset the MDL state. */
Mdl->MdlFlags = Mdl->MdlFlags & ~MDL_MAPPED_TO_SYSTEM_VA;
Mdl->MappedSystemVa = NULL;
/* Reset the MDL state. */
Mdl->MdlFlags = Mdl->MdlFlags & ~MDL_MAPPED_TO_SYSTEM_VA;
Mdl->MappedSystemVa = NULL;
}
VOID
VOID
MmBuildMdlFromPages(PMDL Mdl, PULONG Pages)
{
ULONG i;
PULONG MdlPages;
Mdl->MdlFlags = Mdl->MdlFlags |
(MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
Mdl->MdlFlags = Mdl->MdlFlags |
(MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
MdlPages = (PULONG)(Mdl + 1);
for (i=0;i<(PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGE_SIZE);i++)
{
MdlPages[i] = Pages[i];
}
{
MdlPages[i] = Pages[i];
}
}
/*
* @unimplemented
*/
VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
KPROCESSOR_MODE AccessMode,
LOCK_OPERATION Operation)
KPROCESSOR_MODE AccessMode,
LOCK_OPERATION Operation)
/*
* FUNCTION: Probes the specified pages, makes them resident and locks them
* ARGUMENTS:
@@ -403,106 +409,113 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
PEPROCESS CurrentProcess = NULL;
DPRINT("MmProbeAndLockPages(Mdl %x)\n", Mdl);
/*
* FIXME: Check behaviour against NT
*/
if (Mdl->MdlFlags & MDL_PAGES_LOCKED)
{
return;
}
{
return;
}
if (Mdl->StartVa >= (PVOID)KERNEL_BASE)
{
Mode = KernelMode;
}
{
Mode = KernelMode;
}
else
{
Mode = UserMode;
CurrentProcess = PsGetCurrentProcess();
if (Mdl->Process != CurrentProcess)
{
KeAttachProcess(Mdl->Process);
}
}
{
Mode = UserMode;
CurrentProcess = PsGetCurrentProcess();
if (Mdl->Process != CurrentProcess)
{
KeAttachProcess(Mdl->Process);
}
}
/*
* Lock the pages
*/
MmLockAddressSpace(&Mdl->Process->AddressSpace);
MdlPages = (ULONG *)(Mdl + 1);
MdlPages = (ULONG *)(Mdl + 1);
NrPages = PAGE_ROUND_UP(Mdl->ByteOffset + Mdl->ByteCount) / PAGE_SIZE;
for (i = 0; i < NrPages; i++)
{
PVOID Address;
Address = (char*)Mdl->StartVa + (i*PAGE_SIZE);
if (!MmIsPagePresent(NULL, Address))
{
Status = MmNotPresentFault(Mode, (ULONG)Address, TRUE);
if (!NT_SUCCESS(Status))
{
for (j = 0; j < i; j++)
{
{
PVOID Address;
Address = (char*)Mdl->StartVa + (i*PAGE_SIZE);
if (!MmIsPagePresent(NULL, Address))
{
Status = MmNotPresentFault(Mode, (ULONG)Address, TRUE);
if (!NT_SUCCESS(Status))
{
for (j = 0; j < i; j++)
{
#if defined(__GNUC__)
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
MmDereferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
MmDereferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
#else
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[j];
MmUnlockPage(dummyJunkNeeded);
MmDereferencePage(dummyJunkNeeded);
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[j];
MmUnlockPage(dummyJunkNeeded);
MmDereferencePage(dummyJunkNeeded);
#endif
}
ExRaiseStatus(Status);
}
}
else
{
MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
}
if ((Operation == IoWriteAccess || Operation == IoModifyAccess) &&
(!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE)))
{
Status = MmAccessFault(Mode, (ULONG)Address, TRUE);
if (!NT_SUCCESS(Status))
{
for (j = 0; j < i; j++)
{
}
ExRaiseStatus(Status);
}
}
else
{
MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address));
}
if ((Operation == IoWriteAccess || Operation == IoModifyAccess) &&
(!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE)))
{
Status = MmAccessFault(Mode, (ULONG)Address, TRUE);
if (!NT_SUCCESS(Status))
{
for (j = 0; j < i; j++)
{
#if defined(__GNUC__)
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
MmDereferencePage(
(LARGE_INTEGER)(LONGLONG)MdlPages[j]);
MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[j]);
MmDereferencePage(
(LARGE_INTEGER)(LONGLONG)MdlPages[j]);
#else
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[j];
MmUnlockPage(dummyJunkNeeded);
MmDereferencePage(dummyJunkNeeded);
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[j];
MmUnlockPage(dummyJunkNeeded);
MmDereferencePage(dummyJunkNeeded);
#endif
}
ExRaiseStatus(Status);
}
}
MdlPages[i] = MmGetPhysicalAddressForProcess(NULL, Address).u.LowPart;
}
ExRaiseStatus(Status);
}
}
MdlPages[i] = MmGetPhysicalAddressForProcess(NULL, Address).u.LowPart;
#if defined(__GNUC__)
MmReferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
MmReferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[i]);
#else
{
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[i];
MmReferencePage(dummyJunkNeeded);
}
{
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[i];
MmReferencePage(dummyJunkNeeded);
}
#endif
}
}
MmUnlockAddressSpace(&Mdl->Process->AddressSpace);
if (Mode == UserMode && Mdl->Process != CurrentProcess)
{
KeDetachProcess();
}
{
KeDetachProcess();
}
Mdl->MdlFlags = Mdl->MdlFlags | MDL_PAGES_LOCKED;
}
@@ -510,8 +523,8 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
/*
* @implemented
*/
ULONG STDCALL MmSizeOfMdl (PVOID Base,
ULONG Length)
ULONG STDCALL MmSizeOfMdl (PVOID Base,
ULONG Length)
/*
* FUNCTION: Returns the number of bytes to allocate for an MDL describing
* the given address range
@@ -521,9 +534,9 @@ ULONG STDCALL MmSizeOfMdl (PVOID Base,
*/
{
ULONG len;
len = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base,Length);
return(sizeof(MDL)+(len*sizeof(ULONG)));
}
@@ -531,8 +544,8 @@ ULONG STDCALL MmSizeOfMdl (PVOID Base,
/*
* @implemented
*/
VOID STDCALL
MmBuildMdlForNonPagedPool (PMDL Mdl)
VOID STDCALL
MmBuildMdlForNonPagedPool (PMDL Mdl)
/*
* FUNCTION: Fills in the corresponding physical page array of a given
* MDL for a buffer in nonpaged system space
@@ -542,13 +555,13 @@ MmBuildMdlForNonPagedPool (PMDL Mdl)
*/
{
ULONG va;
Mdl->MdlFlags = Mdl->MdlFlags |
(MDL_SOURCE_IS_NONPAGED_POOL | MDL_PAGES_LOCKED);
Mdl->MdlFlags = Mdl->MdlFlags |
(MDL_SOURCE_IS_NONPAGED_POOL | MDL_PAGES_LOCKED);
for (va=0; va < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); va++)
{
((PULONG)(Mdl + 1))[va] =
(MmGetPhysicalAddress((char*)Mdl->StartVa + (va * PAGE_SIZE))).u.LowPart;
}
{
((PULONG)(Mdl + 1))[va] =
(MmGetPhysicalAddress((char*)Mdl->StartVa + (va * PAGE_SIZE))).u.LowPart;
}
Mdl->MappedSystemVa = (char*)Mdl->StartVa + Mdl->ByteOffset;
}
@@ -556,10 +569,10 @@ MmBuildMdlForNonPagedPool (PMDL Mdl)
/*
* @implemented
*/
PMDL STDCALL
MmCreateMdl (PMDL MemoryDescriptorList,
PVOID Base,
ULONG Length)
PMDL STDCALL
MmCreateMdl (PMDL MemoryDescriptorList,
PVOID Base,
ULONG Length)
/*
* FUNCTION: Allocates and initalizes an MDL
* ARGUMENTS:
@@ -571,17 +584,17 @@ MmCreateMdl (PMDL MemoryDescriptorList,
*/
{
if (MemoryDescriptorList == NULL)
{
ULONG Size;
Size = MmSizeOfMdl(Base,Length);
MemoryDescriptorList =
(PMDL)ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MDL);
if (MemoryDescriptorList == NULL)
{
return(NULL);
}
}
{
ULONG Size;
Size = MmSizeOfMdl(Base,Length);
MemoryDescriptorList =
(PMDL)ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MDL);
if (MemoryDescriptorList == NULL)
{
return(NULL);
}
}
MmInitializeMdl(MemoryDescriptorList, (char*)Base, Length);
@@ -591,8 +604,8 @@ MmCreateMdl (PMDL MemoryDescriptorList,
/*
* @unimplemented
*/
VOID STDCALL
MmMapMemoryDumpMdl (PVOID Unknown0)
VOID STDCALL
MmMapMemoryDumpMdl (PVOID Unknown0)
/*
* FIXME: Has something to do with crash dumps. Do we want to implement
* this?
@@ -603,30 +616,30 @@ MmMapMemoryDumpMdl (PVOID Unknown0)
PMDL STDCALL
MmAllocatePagesForMdl ( IN PHYSICAL_ADDRESS LowAddress,
IN PHYSICAL_ADDRESS HighAddress,
IN PHYSICAL_ADDRESS SkipBytes,
IN SIZE_T Totalbytes )
IN PHYSICAL_ADDRESS HighAddress,
IN PHYSICAL_ADDRESS SkipBytes,
IN SIZE_T Totalbytes )
{
DPRINT1("MmAllocatePagesForMdl(): Unimplemented.\n");
return(NULL);
DPRINT1("MmAllocatePagesForMdl(): Unimplemented.\n");
return(NULL);
}
VOID STDCALL
MmFreePagesFromMdl ( IN PMDL Mdl )
{
DPRINT1("MmFreePagesFromMdl(): Unimplemented.\n");
DPRINT1("MmFreePagesFromMdl(): Unimplemented.\n");
}
PVOID STDCALL
MmMapLockedPagesSpecifyCache ( IN PMDL Mdl,
IN KPROCESSOR_MODE AccessMode,
IN MEMORY_CACHING_TYPE CacheType,
IN PVOID BaseAddress,
IN ULONG BugCheckOnFailure,
IN ULONG Priority )
IN KPROCESSOR_MODE AccessMode,
IN MEMORY_CACHING_TYPE CacheType,
IN PVOID BaseAddress,
IN ULONG BugCheckOnFailure,
IN ULONG Priority )
{
DPRINT1("MmMapLockedPagesSpecifyCache(): Ignoring extra parameters.\n");
return MmMapLockedPages (Mdl, AccessMode);
DPRINT1("MmMapLockedPagesSpecifyCache(): Ignoring extra parameters.\n");
return MmMapLockedPages (Mdl, AccessMode);
}
/* EOF */
+262 -262
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: mm.c,v 1.72 2004/04/08 20:49:15 jfilby Exp $
/* $Id: mm.c,v 1.73 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel
@@ -53,41 +53,41 @@ MM_STATS MmStats;
NTSTATUS MmReleaseMemoryArea(PEPROCESS Process, PMEMORY_AREA Marea)
{
NTSTATUS Status;
DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process,Marea);
DPRINT("Releasing %x between %x %x (type %d)\n",
Marea, Marea->BaseAddress, (char*)Marea->BaseAddress + Marea->Length,
Marea->Type);
Marea, Marea->BaseAddress, (char*)Marea->BaseAddress + Marea->Length,
Marea->Type);
switch (Marea->Type)
{
case MEMORY_AREA_SECTION_VIEW:
Status = MmUnmapViewOfSection(Process, Marea->BaseAddress);
assert(Status == STATUS_SUCCESS);
return(STATUS_SUCCESS);
{
case MEMORY_AREA_SECTION_VIEW:
Status = MmUnmapViewOfSection(Process, Marea->BaseAddress);
assert(Status == STATUS_SUCCESS);
return(STATUS_SUCCESS);
case MEMORY_AREA_VIRTUAL_MEMORY:
MmFreeVirtualMemory(Process, Marea);
break;
case MEMORY_AREA_VIRTUAL_MEMORY:
MmFreeVirtualMemory(Process, Marea);
break;
case MEMORY_AREA_SHARED_DATA:
case MEMORY_AREA_NO_ACCESS:
Status = MmFreeMemoryArea(&Process->AddressSpace,
Marea->BaseAddress,
0,
NULL,
NULL);
break;
case MEMORY_AREA_SHARED_DATA:
case MEMORY_AREA_NO_ACCESS:
Status = MmFreeMemoryArea(&Process->AddressSpace,
Marea->BaseAddress,
0,
NULL,
NULL);
break;
case MEMORY_AREA_MDL_MAPPING:
KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES);
break;
case MEMORY_AREA_MDL_MAPPING:
KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES);
break;
default:
KEBUGCHECK(0);
}
default:
KEBUGCHECK(0);
}
return(STATUS_SUCCESS);
}
@@ -95,24 +95,24 @@ NTSTATUS MmReleaseMmInfo(PEPROCESS Process)
{
PLIST_ENTRY CurrentEntry;
PMEMORY_AREA Current;
DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process,
Process->ImageFileName);
Process->ImageFileName);
MmLockAddressSpace(&Process->AddressSpace);
while(!IsListEmpty(&Process->AddressSpace.MAreaListHead))
{
CurrentEntry = Process->AddressSpace.MAreaListHead.Flink;
Current = CONTAINING_RECORD(CurrentEntry, MEMORY_AREA, Entry);
MmReleaseMemoryArea(Process, Current);
}
{
CurrentEntry = Process->AddressSpace.MAreaListHead.Flink;
Current = CONTAINING_RECORD(CurrentEntry, MEMORY_AREA, Entry);
MmReleaseMemoryArea(Process, Current);
}
Mmi386ReleaseMmInfo(Process);
MmUnlockAddressSpace(&Process->AddressSpace);
MmDestroyAddressSpace(&Process->AddressSpace);
DPRINT("Finished MmReleaseMmInfo()\n");
return(STATUS_SUCCESS);
}
@@ -142,282 +142,282 @@ BOOLEAN STDCALL MmIsAddressValid(PVOID VirtualAddress)
{
MEMORY_AREA* MemoryArea;
PMADDRESS_SPACE AddressSpace;
if ((ULONG)VirtualAddress >= KERNEL_BASE)
{
AddressSpace = MmGetKernelAddressSpace();
}
{
AddressSpace = MmGetKernelAddressSpace();
}
else
{
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
}
{
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
}
MmLockAddressSpace(AddressSpace);
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
VirtualAddress);
VirtualAddress);
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
MmUnlockAddressSpace(AddressSpace);
return(FALSE);
}
{
MmUnlockAddressSpace(AddressSpace);
return(FALSE);
}
MmUnlockAddressSpace(AddressSpace);
return(TRUE);
}
NTSTATUS MmAccessFault(KPROCESSOR_MODE Mode,
ULONG Address,
BOOLEAN FromMdl)
ULONG Address,
BOOLEAN FromMdl)
{
PMADDRESS_SPACE AddressSpace;
MEMORY_AREA* MemoryArea;
NTSTATUS Status;
BOOLEAN Locked = FromMdl;
DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
{
DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
return(STATUS_UNSUCCESSFUL);
}
{
DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
return(STATUS_UNSUCCESSFUL);
}
if (PsGetCurrentProcess() == NULL)
{
DbgPrint("No current process\n");
return(STATUS_UNSUCCESSFUL);
}
{
DbgPrint("No current process\n");
return(STATUS_UNSUCCESSFUL);
}
/*
* Find the memory area for the faulting address
*/
if (Address >= KERNEL_BASE)
{
/*
* Check permissions
*/
if (Mode != KernelMode)
{
DbgPrint("%s:%d\n",__FILE__,__LINE__);
return(STATUS_UNSUCCESSFUL);
}
AddressSpace = MmGetKernelAddressSpace();
}
{
/*
* Check permissions
*/
if (Mode != KernelMode)
{
DbgPrint("%s:%d\n",__FILE__,__LINE__);
return(STATUS_UNSUCCESSFUL);
}
AddressSpace = MmGetKernelAddressSpace();
}
else
{
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
}
{
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
}
if (!FromMdl)
{
MmLockAddressSpace(AddressSpace);
}
{
MmLockAddressSpace(AddressSpace);
}
do
{
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address);
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
if (!FromMdl)
{
MmUnlockAddressSpace(AddressSpace);
}
return (STATUS_UNSUCCESSFUL);
}
switch (MemoryArea->Type)
{
case MEMORY_AREA_SYSTEM:
Status = STATUS_UNSUCCESSFUL;
break;
{
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address);
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
if (!FromMdl)
{
MmUnlockAddressSpace(AddressSpace);
}
return (STATUS_UNSUCCESSFUL);
}
case MEMORY_AREA_PAGED_POOL:
Status = STATUS_SUCCESS;
break;
switch (MemoryArea->Type)
{
case MEMORY_AREA_SYSTEM:
Status = STATUS_UNSUCCESSFUL;
break;
case MEMORY_AREA_SECTION_VIEW:
Status = MmAccessFaultSectionView(AddressSpace,
MemoryArea,
(PVOID)Address,
Locked);
break;
case MEMORY_AREA_PAGED_POOL:
Status = STATUS_SUCCESS;
break;
case MEMORY_AREA_VIRTUAL_MEMORY:
Status = STATUS_UNSUCCESSFUL;
break;
case MEMORY_AREA_SECTION_VIEW:
Status = MmAccessFaultSectionView(AddressSpace,
MemoryArea,
(PVOID)Address,
Locked);
break;
case MEMORY_AREA_SHARED_DATA:
Status = STATUS_UNSUCCESSFUL;
break;
case MEMORY_AREA_VIRTUAL_MEMORY:
Status = STATUS_UNSUCCESSFUL;
break;
default:
Status = STATUS_UNSUCCESSFUL;
break;
}
}
case MEMORY_AREA_SHARED_DATA:
Status = STATUS_UNSUCCESSFUL;
break;
default:
Status = STATUS_UNSUCCESSFUL;
break;
}
}
while (Status == STATUS_MM_RESTART_OPERATION);
DPRINT("Completed page fault handling\n");
if (!FromMdl)
{
MmUnlockAddressSpace(AddressSpace);
}
{
MmUnlockAddressSpace(AddressSpace);
}
return(Status);
}
NTSTATUS MmCommitPagedPoolAddress(PVOID Address, BOOLEAN Locked)
{
NTSTATUS Status;
PHYSICAL_ADDRESS AllocatedPage;
Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage);
if (!NT_SUCCESS(Status))
{
NTSTATUS Status;
PHYSICAL_ADDRESS AllocatedPage;
Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage);
if (!NT_SUCCESS(Status))
{
MmUnlockAddressSpace(MmGetKernelAddressSpace());
Status = MmRequestPageMemoryConsumer(MC_PPOOL, TRUE, &AllocatedPage);
MmLockAddressSpace(MmGetKernelAddressSpace());
}
Status =
MmCreateVirtualMapping(NULL,
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READWRITE,
AllocatedPage,
FALSE);
if (!NT_SUCCESS(Status))
{
}
Status =
MmCreateVirtualMapping(NULL,
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READWRITE,
AllocatedPage,
FALSE);
if (!NT_SUCCESS(Status))
{
MmUnlockAddressSpace(MmGetKernelAddressSpace());
Status =
MmCreateVirtualMapping(NULL,
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READWRITE,
AllocatedPage,
FALSE);
Status =
MmCreateVirtualMapping(NULL,
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READWRITE,
AllocatedPage,
FALSE);
MmLockAddressSpace(MmGetKernelAddressSpace());
}
if (Locked)
{
}
if (Locked)
{
MmLockPage(AllocatedPage);
}
return(Status);
}
return(Status);
}
NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
ULONG Address,
BOOLEAN FromMdl)
ULONG Address,
BOOLEAN FromMdl)
{
PMADDRESS_SPACE AddressSpace;
MEMORY_AREA* MemoryArea;
NTSTATUS Status;
BOOLEAN Locked = FromMdl;
DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address);
if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
{
DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
return(STATUS_UNSUCCESSFUL);
}
{
DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
return(STATUS_UNSUCCESSFUL);
}
if (PsGetCurrentProcess() == NULL)
{
DbgPrint("No current process\n");
return(STATUS_UNSUCCESSFUL);
}
{
DbgPrint("No current process\n");
return(STATUS_UNSUCCESSFUL);
}
/*
* Find the memory area for the faulting address
*/
if (Address >= KERNEL_BASE)
{
/*
* Check permissions
*/
if (Mode != KernelMode)
{
DbgPrint("%s:%d\n",__FILE__,__LINE__);
return(STATUS_UNSUCCESSFUL);
}
AddressSpace = MmGetKernelAddressSpace();
}
{
/*
* Check permissions
*/
if (Mode != KernelMode)
{
DbgPrint("%s:%d\n",__FILE__,__LINE__);
return(STATUS_UNSUCCESSFUL);
}
AddressSpace = MmGetKernelAddressSpace();
}
else
{
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
}
{
AddressSpace = &PsGetCurrentProcess()->AddressSpace;
}
if (!FromMdl)
{
MmLockAddressSpace(AddressSpace);
}
{
MmLockAddressSpace(AddressSpace);
}
/*
* Call the memory area specific fault handler
*/
do
{
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address);
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
if (!FromMdl)
{
MmUnlockAddressSpace(AddressSpace);
}
return (STATUS_UNSUCCESSFUL);
}
{
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address);
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
if (!FromMdl)
{
MmUnlockAddressSpace(AddressSpace);
}
return (STATUS_UNSUCCESSFUL);
}
switch (MemoryArea->Type)
{
case MEMORY_AREA_PAGED_POOL:
{
Status = MmCommitPagedPoolAddress((PVOID)Address, Locked);
break;
}
switch (MemoryArea->Type)
{
case MEMORY_AREA_PAGED_POOL:
{
Status = MmCommitPagedPoolAddress((PVOID)Address, Locked);
break;
}
case MEMORY_AREA_SYSTEM:
Status = STATUS_UNSUCCESSFUL;
break;
case MEMORY_AREA_SECTION_VIEW:
Status = MmNotPresentFaultSectionView(AddressSpace,
MemoryArea,
(PVOID)Address,
Locked);
break;
case MEMORY_AREA_VIRTUAL_MEMORY:
Status = MmNotPresentFaultVirtualMemory(AddressSpace,
MemoryArea,
(PVOID)Address,
Locked);
break;
case MEMORY_AREA_SHARED_DATA:
Status =
MmCreateVirtualMapping(PsGetCurrentProcess(),
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READONLY,
MmSharedDataPagePhysicalAddress,
FALSE);
if (!NT_SUCCESS(Status))
{
MmUnlockAddressSpace(&PsGetCurrentProcess()->AddressSpace);
Status =
MmCreateVirtualMapping(PsGetCurrentProcess(),
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READONLY,
MmSharedDataPagePhysicalAddress,
TRUE);
MmLockAddressSpace(&PsGetCurrentProcess()->AddressSpace);
}
break;
default:
Status = STATUS_UNSUCCESSFUL;
break;
}
}
case MEMORY_AREA_SYSTEM:
Status = STATUS_UNSUCCESSFUL;
break;
case MEMORY_AREA_SECTION_VIEW:
Status = MmNotPresentFaultSectionView(AddressSpace,
MemoryArea,
(PVOID)Address,
Locked);
break;
case MEMORY_AREA_VIRTUAL_MEMORY:
Status = MmNotPresentFaultVirtualMemory(AddressSpace,
MemoryArea,
(PVOID)Address,
Locked);
break;
case MEMORY_AREA_SHARED_DATA:
Status =
MmCreateVirtualMapping(PsGetCurrentProcess(),
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READONLY,
MmSharedDataPagePhysicalAddress,
FALSE);
if (!NT_SUCCESS(Status))
{
MmUnlockAddressSpace(&PsGetCurrentProcess()->AddressSpace);
Status =
MmCreateVirtualMapping(PsGetCurrentProcess(),
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READONLY,
MmSharedDataPagePhysicalAddress,
TRUE);
MmLockAddressSpace(&PsGetCurrentProcess()->AddressSpace);
}
break;
default:
Status = STATUS_UNSUCCESSFUL;
break;
}
}
while (Status == STATUS_MM_RESTART_OPERATION);
DPRINT("Completed page fault handling\n");
if (!FromMdl)
{
MmUnlockAddressSpace(AddressSpace);
}
{
MmUnlockAddressSpace(AddressSpace);
}
return(Status);
}
@@ -427,24 +427,24 @@ NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
* @unimplemented
*/
DWORD STDCALL
MmAdjustWorkingSetSize (DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2)
MmAdjustWorkingSetSize (DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2)
{
UNIMPLEMENTED;
return (0);
UNIMPLEMENTED;
return (0);
}
DWORD
STDCALL
MmDbgTranslatePhysicalAddress (
DWORD Unknown0,
DWORD Unknown1
)
DWORD Unknown0,
DWORD Unknown1
)
{
UNIMPLEMENTED;
return (0);
UNIMPLEMENTED;
return (0);
}
@@ -454,11 +454,11 @@ MmDbgTranslatePhysicalAddress (
NTSTATUS
STDCALL
MmGrowKernelStack (
DWORD Unknown0
)
DWORD Unknown0
)
{
UNIMPLEMENTED;
return (STATUS_NOT_IMPLEMENTED);
UNIMPLEMENTED;
return (STATUS_NOT_IMPLEMENTED);
}
@@ -468,12 +468,12 @@ MmGrowKernelStack (
BOOLEAN
STDCALL
MmSetAddressRangeModified (
DWORD Unknown0,
DWORD Unknown1
)
DWORD Unknown0,
DWORD Unknown1
)
{
UNIMPLEMENTED;
return (FALSE);
UNIMPLEMENTED;
return (FALSE);
}
/* EOF */
+199 -197
View File
@@ -1,4 +1,4 @@
/* $Id: mminit.c,v 1.62 2004/03/16 22:45:56 dwelch Exp $
/* $Id: mminit.c,v 1.63 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel
@@ -48,7 +48,7 @@ static MEMORY_AREA* kernel_data_desc = NULL;
static MEMORY_AREA* kernel_param_desc = NULL;
static MEMORY_AREA* kernel_pool_desc = NULL;
static MEMORY_AREA* kernel_shared_data_desc = NULL;
static MEMORY_AREA* kernel_mapped_vga_framebuffer_desc = NULL;
static MEMORY_AREA* kernel_mapped_vga_framebuffer_desc = NULL;
static MEMORY_AREA* MiKernelMapDescriptor = NULL;
static MEMORY_AREA* MiPagedPoolDescriptor = NULL;
@@ -78,12 +78,11 @@ MM_SYSTEM_SIZE STDCALL MmQuerySystemSize(VOID)
}
VOID MiShutdownMemoryManager(VOID)
{
}
{}
VOID INIT_FUNCTION
MmInitVirtualMemory(ULONG LastKernelAddress,
ULONG KernelLength)
ULONG KernelLength)
/*
* FUNCTION: Intialize the memory areas list
* ARGUMENTS:
@@ -97,9 +96,9 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
NTSTATUS Status;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
//ULONG i;
DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress, KernelLength);
BoundaryAddressMultiple.QuadPart = 0;
LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress);
@@ -124,58 +123,58 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
*/
BaseAddress = (PVOID)0xf0000000;
MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
0x400000,
0,
&kernel_map_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
0x400000,
0,
&kernel_map_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
BaseAddress = (PVOID)KPCR_BASE;
MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
PAGE_SIZE * MAXIMUM_PROCESSORS,
0,
&kernel_kpcr_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
PAGE_SIZE * MAXIMUM_PROCESSORS,
0,
&kernel_kpcr_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
BaseAddress = (PVOID)0xFF3A0000;
MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
0x20000,
0,
&kernel_mapped_vga_framebuffer_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
0x20000,
0,
&kernel_mapped_vga_framebuffer_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
BaseAddress = (PVOID)KERNEL_BASE;
Length = PAGE_ROUND_UP(((ULONG)&_text_end__)) - KERNEL_BASE;
ParamLength = ParamLength - Length;
/*
* No need to lock the address space at this point since no
* other threads are running.
*/
MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Length,
0,
&kernel_text_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Length,
0,
&kernel_text_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_text_end__));
assert (BaseAddress == (PVOID)&_init_start__);
@@ -184,17 +183,17 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
ParamLength = ParamLength - Length;
MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Length,
0,
&kernel_init_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Length,
0,
&kernel_init_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
Length = PAGE_ROUND_UP(((ULONG)&_bss_end__)) -
Length = PAGE_ROUND_UP(((ULONG)&_bss_end__)) -
PAGE_ROUND_UP(((ULONG)&_init_end__));
ParamLength = ParamLength - Length;
DPRINT("Length %x\n",Length);
@@ -206,64 +205,64 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
* the only thread running.
*/
MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Length,
0,
&kernel_data_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Length,
0,
&kernel_data_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_bss_end__));
Length = LastKernelAddress - (ULONG)BaseAddress;
MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Length,
0,
&kernel_param_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Length,
0,
&kernel_param_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
BaseAddress = MiNonPagedPoolStart;
MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
MiNonPagedPoolLength,
0,
&kernel_pool_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
MiNonPagedPoolLength,
0,
&kernel_pool_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
BaseAddress = MiKernelMapStart;
Status = MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
MiKernelMapLength,
0,
&MiKernelMapDescriptor,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
MiKernelMapLength,
0,
&MiKernelMapDescriptor,
FALSE,
FALSE,
BoundaryAddressMultiple);
BaseAddress = MmPagedPoolBase;
Status = MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_PAGED_POOL,
&BaseAddress,
MmPagedPoolSize,
0,
&MiPagedPoolDescriptor,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_PAGED_POOL,
&BaseAddress,
MmPagedPoolSize,
0,
&MiPagedPoolDescriptor,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmInitializePagedPool();
@@ -273,27 +272,27 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
BaseAddress = (PVOID)KI_USER_SHARED_DATA;
Length = PAGE_SIZE;
MmCreateMemoryArea(NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Length,
0,
&kernel_shared_data_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE,
&MmSharedDataPagePhysicalAddress);
MmGetKernelAddressSpace(),
MEMORY_AREA_SYSTEM,
&BaseAddress,
Length,
0,
&kernel_shared_data_desc,
FALSE,
FALSE,
BoundaryAddressMultiple);
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE,
&MmSharedDataPagePhysicalAddress);
Status = MmCreateVirtualMapping(NULL,
(PVOID)KI_USER_SHARED_DATA,
PAGE_READWRITE,
MmSharedDataPagePhysicalAddress,
TRUE);
(PVOID)KI_USER_SHARED_DATA,
PAGE_READWRITE,
MmSharedDataPagePhysicalAddress,
TRUE);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KEBUGCHECK(0);
}
{
DbgPrint("Unable to create virtual mapping\n");
KEBUGCHECK(0);
}
RtlZeroMemory(BaseAddress, Length);
/*
@@ -304,11 +303,11 @@ MmInitVirtualMemory(ULONG LastKernelAddress,
VOID INIT_FUNCTION
MmInit1(ULONG FirstKrnlPhysAddr,
ULONG LastKrnlPhysAddr,
ULONG LastKernelAddress,
PADDRESS_RANGE BIOSMemoryMap,
ULONG AddressRangeCount,
ULONG MaxMem)
ULONG LastKrnlPhysAddr,
ULONG LastKernelAddress,
PADDRESS_RANGE BIOSMemoryMap,
ULONG AddressRangeCount,
ULONG MaxMem)
/*
* FUNCTION: Initalize memory managment
*/
@@ -316,37 +315,38 @@ MmInit1(ULONG FirstKrnlPhysAddr,
ULONG i;
ULONG kernel_len;
#ifndef MP
extern unsigned int unmap_me, unmap_me2, unmap_me3;
#endif
DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n",
FirstKrnlPhysAddr,
LastKrnlPhysAddr,
LastKernelAddress);
FirstKrnlPhysAddr,
LastKrnlPhysAddr,
LastKernelAddress);
if ((BIOSMemoryMap != NULL) && (AddressRangeCount > 0))
{
// If we have a bios memory map, recalulate the memory size
ULONG last = 0;
for (i = 0; i < AddressRangeCount; i++)
{
if (BIOSMemoryMap[i].Type == 1
&& (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE > last)
{
last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE;
}
}
if ((last - 256) * 4 > KeLoaderBlock.MemHigher)
{
KeLoaderBlock.MemHigher = (last - 256) * 4;
}
}
{
// If we have a bios memory map, recalulate the memory size
ULONG last = 0;
for (i = 0; i < AddressRangeCount; i++)
{
if (BIOSMemoryMap[i].Type == 1
&& (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE > last)
{
last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE;
}
}
if ((last - 256) * 4 > KeLoaderBlock.MemHigher)
{
KeLoaderBlock.MemHigher = (last - 256) * 4;
}
}
if (KeLoaderBlock.MemHigher >= (MaxMem - 1) * 1024)
{
KeLoaderBlock.MemHigher = (MaxMem - 1) * 1024;
}
{
KeLoaderBlock.MemHigher = (MaxMem - 1) * 1024;
}
/*
* FIXME: Set this based on the system command line
@@ -354,7 +354,7 @@ MmInit1(ULONG FirstKrnlPhysAddr,
MmSystemRangeStart = (PVOID)KERNEL_BASE; // 0xC0000000
MmUserProbeAddress = (PVOID)0x7fff0000;
MmHighestUserAddress = (PVOID)0x7ffeffff;
MmInitGlobalKernelPageDirectory();
/*
@@ -370,7 +370,7 @@ MmInit1(ULONG FirstKrnlPhysAddr,
MmStats.PagingRequestsInLastMinute = 0;
MmStats.PagingRequestsInLastFiveMinutes = 0;
MmStats.PagingRequestsInLastFifteenMinutes = 0;
/*
* Initialize the kernel address space
*/
@@ -380,7 +380,7 @@ MmInit1(ULONG FirstKrnlPhysAddr,
* Unmap low memory
*/
#ifndef MP
/* In SMP mode we unmap the low memory in MmInit3.
/* In SMP mode we unmap the low memory in MmInit3.
The APIC needs the mapping of the first pages
while the processors are starting up. */
MmDeletePageTable(NULL, 0);
@@ -391,35 +391,36 @@ MmInit1(ULONG FirstKrnlPhysAddr,
* memory)
*/
DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr,
LastKrnlPhysAddr);
LastKrnlPhysAddr);
/*
* Free physical memory not used by the kernel
*/
MmStats.NrTotalPages = KeLoaderBlock.MemHigher/4;
if (!MmStats.NrTotalPages)
{
DbgPrint("Memory not detected, default to 8 MB\n");
MmStats.NrTotalPages = 2048;
}
{
DbgPrint("Memory not detected, default to 8 MB\n");
MmStats.NrTotalPages = 2048;
}
else
{
/* add 1MB for standard memory (not extended) */
MmStats.NrTotalPages += 256;
}
{
/* add 1MB for standard memory (not extended) */
MmStats.NrTotalPages += 256;
}
#ifdef BIOS_MEM_FIX
MmStats.NrTotalPages += 16;
#endif
DbgPrint("Used memory %dKb\n", (MmStats.NrTotalPages * PAGE_SIZE) / 1024);
LastKernelAddress = (ULONG)MmInitializePageList((PVOID)FirstKrnlPhysAddr,
(PVOID)LastKrnlPhysAddr,
MmStats.NrTotalPages,
PAGE_ROUND_UP(LastKernelAddress),
BIOSMemoryMap,
AddressRangeCount);
(PVOID)LastKrnlPhysAddr,
MmStats.NrTotalPages,
PAGE_ROUND_UP(LastKernelAddress),
BIOSMemoryMap,
AddressRangeCount);
kernel_len = LastKrnlPhysAddr - FirstKrnlPhysAddr;
/*
* Create a trap for null pointer references and protect text
* segment
@@ -427,27 +428,27 @@ MmInit1(ULONG FirstKrnlPhysAddr,
CHECKPOINT;
DPRINT("_text_start__ %x _init_end__ %x\n",(int)&_text_start__,(int)&_init_end__);
for (i=PAGE_ROUND_DOWN(((int)&_text_start__));
i<PAGE_ROUND_UP(((int)&_init_end__));i=i+PAGE_SIZE)
{
MmSetPageProtect(NULL,
(PVOID)i,
PAGE_EXECUTE_READ);
}
i<PAGE_ROUND_UP(((int)&_init_end__));i=i+PAGE_SIZE)
{
MmSetPageProtect(NULL,
(PVOID)i,
PAGE_EXECUTE_READ);
}
DPRINT("Invalidating between %x and %x\n",
LastKernelAddress, 0xc0600000);
LastKernelAddress, 0xc0600000);
for (i=(LastKernelAddress); i<0xc0600000; i+=PAGE_SIZE)
{
MmRawDeleteVirtualMapping((PVOID)(i));
}
{
MmRawDeleteVirtualMapping((PVOID)(i));
}
DPRINT("Invalidating between %x and %x\n",
0xd0100000, 0xd0400000);
0xd0100000, 0xd0400000);
for (i=0xd0100000; i<0xd0400000; i+=PAGE_SIZE)
{
MmRawDeleteVirtualMapping((PVOID)(i));
}
{
MmRawDeleteVirtualMapping((PVOID)(i));
}
DPRINT("Almost done MmInit()\n");
#ifndef MP
/* FIXME: This is broken in SMP mode */
@@ -479,10 +480,11 @@ MmInit3(VOID)
* Unmap low memory
*/
#ifdef MP
/* In SMP mode we can unmap the low memory
/* In SMP mode we can unmap the low memory
if all processors are started. */
MmDeletePageTable(NULL, 0);
#endif
MmInitZeroPageThread();
MmCreatePhysicalMemorySection();
MiInitBalancerThread();
@@ -496,25 +498,25 @@ MmInit3(VOID)
}
VOID STATIC
MiFreeInitMemoryPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
BOOLEAN Dirty)
MiFreeInitMemoryPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
BOOLEAN Dirty)
{
assert(SwapEntry == 0);
if (PhysAddr.QuadPart != 0)
{
assert(SwapEntry == 0);
if (PhysAddr.QuadPart != 0)
{
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr);
}
}
}
VOID
VOID
MiFreeInitMemory(VOID)
{
MmLockAddressSpace(MmGetKernelAddressSpace());
MmFreeMemoryArea(MmGetKernelAddressSpace(),
(PVOID)&_init_start__,
PAGE_ROUND_UP((ULONG)&_init_end__) - (ULONG)_init_start__,
MiFreeInitMemoryPage,
NULL);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
MmLockAddressSpace(MmGetKernelAddressSpace());
MmFreeMemoryArea(MmGetKernelAddressSpace(),
(PVOID)&_init_start__,
PAGE_ROUND_UP((ULONG)&_init_end__) - (ULONG)_init_start__,
MiFreeInitMemoryPage,
NULL);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
}
+70 -66
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: mpw.c,v 1.17 2003/12/30 18:52:05 fireball Exp $
/* $Id: mpw.c,v 1.18 2004/04/10 22:35:25 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/mpw.c
@@ -49,100 +49,104 @@ static volatile BOOLEAN MpwThreadShouldTerminate;
NTSTATUS STDCALL
MmWriteDirtyPages(ULONG Target, PULONG Actual)
{
PHYSICAL_ADDRESS Page;
PHYSICAL_ADDRESS NextPage;
NTSTATUS Status;
PHYSICAL_ADDRESS Page;
PHYSICAL_ADDRESS NextPage;
NTSTATUS Status;
Page = MmGetLRUFirstUserPage();
Page = MmGetLRUFirstUserPage();
#if defined(__GNUC__)
while (Page.QuadPart != 0LL && Target > 0)
while (Page.QuadPart != 0LL && Target > 0)
#else
while (Page.QuadPart && Target > 0)
while (Page.QuadPart && Target > 0)
#endif
{
{
/*
* FIXME: While the current page is write back it is possible
* that the next page is freed and not longer a user page.
*/
NextPage = MmGetLRUNextUserPage(Page);
if (MmIsDirtyPageRmap(Page))
{
Status = MmWritePagePhysicalAddress(Page);
if (NT_SUCCESS(Status))
{
Target--;
}
}
{
Status = MmWritePagePhysicalAddress(Page);
if (NT_SUCCESS(Status))
{
Target--;
}
}
Page = NextPage;
}
*Actual = Target;
return(STATUS_SUCCESS);
}
*Actual = Target;
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
MmMpwThreadMain(PVOID Ignored)
{
NTSTATUS Status;
ULONG PagesWritten;
LARGE_INTEGER Timeout;
Timeout.QuadPart = -50000000;
for(;;)
{
NTSTATUS Status;
ULONG PagesWritten;
LARGE_INTEGER Timeout;
Timeout.QuadPart = -50000000;
for(;;)
{
Status = KeWaitForSingleObject(&MpwThreadEvent,
0,
KernelMode,
FALSE,
&Timeout);
0,
KernelMode,
FALSE,
&Timeout);
if (!NT_SUCCESS(Status))
{
DbgPrint("MpwThread: Wait failed\n");
KEBUGCHECK(0);
return(STATUS_UNSUCCESSFUL);
}
{
DbgPrint("MpwThread: Wait failed\n");
KEBUGCHECK(0);
return(STATUS_UNSUCCESSFUL);
}
if (MpwThreadShouldTerminate)
{
DbgPrint("MpwThread: Terminating\n");
return(STATUS_SUCCESS);
}
{
DbgPrint("MpwThread: Terminating\n");
return(STATUS_SUCCESS);
}
PagesWritten = 0;
#if 0
/*
/*
* FIXME: MmWriteDirtyPages doesn't work correctly.
*/
MmWriteDirtyPages(128, &PagesWritten);
#endif
CcRosFlushDirtyPages(128, &PagesWritten);
}
}
}
NTSTATUS MmInitMpwThread(VOID)
{
KPRIORITY Priority;
NTSTATUS Status;
MpwThreadShouldTerminate = FALSE;
KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
Status = PsCreateSystemThread(&MpwThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&MpwThreadId,
(PKSTART_ROUTINE) MmMpwThreadMain,
NULL);
if (!NT_SUCCESS(Status))
{
KPRIORITY Priority;
NTSTATUS Status;
MpwThreadShouldTerminate = FALSE;
KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
Status = PsCreateSystemThread(&MpwThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&MpwThreadId,
(PKSTART_ROUTINE) MmMpwThreadMain,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Priority = 1;
NtSetInformationThread(MpwThreadHandle,
ThreadPriority,
&Priority,
sizeof(Priority));
return(STATUS_SUCCESS);
}
Priority = 1;
NtSetInformationThread(MpwThreadHandle,
ThreadPriority,
&Priority,
sizeof(Priority));
return(STATUS_SUCCESS);
}
+66 -66
View File
@@ -1,4 +1,4 @@
/* $Id: ncache.c,v 1.27 2003/12/31 05:33:04 jfilby Exp $
/* $Id: ncache.c,v 1.28 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -22,30 +22,30 @@
/**********************************************************************
* NAME EXPORTED
* MmAllocateNonCachedMemory@4
* NAME EXPORTED
* MmAllocateNonCachedMemory@4
*
* DESCRIPTION
* Allocates a virtual address range of noncached and cache
* aligned memory.
*
* Allocates a virtual address range of noncached and cache
* aligned memory.
*
* ARGUMENTS
* NumberOfBytes
* Size of region to allocate.
*
* NumberOfBytes
* Size of region to allocate.
*
* RETURN VALUE
* The base address of the range on success;
* NULL on failure.
* The base address of the range on success;
* NULL on failure.
*
* NOTE
* Description taken from include/ddk/mmfuncs.h.
* Code taken from ntoskrnl/mm/special.c.
* Description taken from include/ddk/mmfuncs.h.
* Code taken from ntoskrnl/mm/special.c.
*
* REVISIONS
*
* @implemented
*/
PVOID STDCALL
PVOID STDCALL
MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
{
PVOID Result;
@@ -59,85 +59,85 @@ MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
MmLockAddressSpace(MmGetKernelAddressSpace());
Result = NULL;
Status = MmCreateMemoryArea (NULL,
MmGetKernelAddressSpace(),
MEMORY_AREA_NO_CACHE,
&Result,
NumberOfBytes,
0,
&marea,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmGetKernelAddressSpace(),
MEMORY_AREA_NO_CACHE,
&Result,
NumberOfBytes,
0,
&marea,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
if (!NT_SUCCESS(Status))
{
return (NULL);
}
Attributes = PAGE_READWRITE | PAGE_SYSTEM | PAGE_NOCACHE |
PAGE_WRITETHROUGH;
{
return (NULL);
}
Attributes = PAGE_READWRITE | PAGE_SYSTEM | PAGE_NOCACHE |
PAGE_WRITETHROUGH;
for (i = 0; i < (PAGE_ROUND_UP(NumberOfBytes) / PAGE_SIZE); i++)
{
PHYSICAL_ADDRESS NPage;
{
PHYSICAL_ADDRESS NPage;
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &NPage);
MmCreateVirtualMapping (NULL,
(char*)Result + (i * PAGE_SIZE),
Attributes,
NPage,
TRUE);
}
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &NPage);
MmCreateVirtualMapping (NULL,
(char*)Result + (i * PAGE_SIZE),
Attributes,
NPage,
TRUE);
}
return ((PVOID)Result);
}
VOID STATIC
MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
BOOLEAN Dirty)
MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry,
BOOLEAN Dirty)
{
assert(SwapEntry == 0);
if (PhysAddr.QuadPart != 0)
{
assert(SwapEntry == 0);
if (PhysAddr.QuadPart != 0)
{
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr);
}
}
}
/**********************************************************************
* NAME EXPORTED
* MmFreeNonCachedMemory@8
* NAME EXPORTED
* MmFreeNonCachedMemory@8
*
* DESCRIPTION
* Releases a range of noncached memory allocated with
* MmAllocateNonCachedMemory.
*
* Releases a range of noncached memory allocated with
* MmAllocateNonCachedMemory.
*
* ARGUMENTS
* BaseAddress
* Virtual address to be freed;
*
* NumberOfBytes
* Size of the region to be freed.
*
* BaseAddress
* Virtual address to be freed;
*
* NumberOfBytes
* Size of the region to be freed.
*
* RETURN VALUE
* None.
* None.
*
* NOTE
* Description taken from include/ddk/mmfuncs.h.
* Code taken from ntoskrnl/mm/special.c.
* Description taken from include/ddk/mmfuncs.h.
* Code taken from ntoskrnl/mm/special.c.
*
* REVISIONS
*
* @implemented
*/
VOID STDCALL MmFreeNonCachedMemory (IN PVOID BaseAddress,
IN ULONG NumberOfBytes)
IN ULONG NumberOfBytes)
{
MmLockAddressSpace(MmGetKernelAddressSpace());
MmFreeMemoryArea (MmGetKernelAddressSpace(),
BaseAddress,
NumberOfBytes,
MmFreeNonCachedPage,
NULL);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
MmLockAddressSpace(MmGetKernelAddressSpace());
MmFreeMemoryArea (MmGetKernelAddressSpace(),
BaseAddress,
NumberOfBytes,
MmFreeNonCachedPage,
NULL);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
}
/* EOF */
+1107 -1087
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+165 -165
View File
@@ -1,4 +1,4 @@
/* $Id: pageop.c,v 1.19 2004/03/05 11:31:59 hbirr Exp $
/* $Id: pageop.c,v 1.20 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -32,227 +32,227 @@ static NPAGED_LOOKASIDE_LIST MmPageOpLookasideList;
VOID
MmReleasePageOp(PMM_PAGEOP PageOp)
/*
* FUNCTION: Release a reference to a page operation descriptor
*/
/*
* FUNCTION: Release a reference to a page operation descriptor
*/
{
KIRQL oldIrql;
PMM_PAGEOP PrevPageOp;
KIRQL oldIrql;
PMM_PAGEOP PrevPageOp;
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
PageOp->ReferenceCount--;
if (PageOp->ReferenceCount > 0)
{
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
PageOp->ReferenceCount--;
if (PageOp->ReferenceCount > 0)
{
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
return;
}
InterlockedDecrement((LONG *)&PageOp->MArea->PageOpCount);
PrevPageOp = MmPageOpHashTable[PageOp->Hash];
if (PrevPageOp == PageOp)
{
}
InterlockedDecrement((LONG *)&PageOp->MArea->PageOpCount);
PrevPageOp = MmPageOpHashTable[PageOp->Hash];
if (PrevPageOp == PageOp)
{
MmPageOpHashTable[PageOp->Hash] = PageOp->Next;
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
ExFreeToNPagedLookasideList(&MmPageOpLookasideList, PageOp);
return;
}
while (PrevPageOp->Next != NULL)
{
}
while (PrevPageOp->Next != NULL)
{
if (PrevPageOp->Next == PageOp)
{
PrevPageOp->Next = PageOp->Next;
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
ExFreeToNPagedLookasideList(&MmPageOpLookasideList, PageOp);
return;
}
{
PrevPageOp->Next = PageOp->Next;
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
ExFreeToNPagedLookasideList(&MmPageOpLookasideList, PageOp);
return;
}
PrevPageOp = PrevPageOp->Next;
}
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
KEBUGCHECK(0);
}
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
KEBUGCHECK(0);
}
PMM_PAGEOP
MmCheckForPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
PMM_SECTION_SEGMENT Segment, ULONG Offset)
PMM_SECTION_SEGMENT Segment, ULONG Offset)
{
ULONG Hash;
KIRQL oldIrql;
PMM_PAGEOP PageOp;
/*
* Calcuate the hash value for pageop structure
*/
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
{
ULONG Hash;
KIRQL oldIrql;
PMM_PAGEOP PageOp;
/*
* Calcuate the hash value for pageop structure
*/
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
{
Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE));
}
else
{
}
else
{
Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE));
}
Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
}
Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
/*
* Check for an existing pageop structure
*/
PageOp = MmPageOpHashTable[Hash];
while (PageOp != NULL)
{
/*
* Check for an existing pageop structure
*/
PageOp = MmPageOpHashTable[Hash];
while (PageOp != NULL)
{
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
{
if (PageOp->Segment == Segment &&
PageOp->Offset == Offset)
{
break;
}
}
{
if (PageOp->Segment == Segment &&
PageOp->Offset == Offset)
{
break;
}
}
else
{
if (PageOp->Pid == Pid &&
PageOp->Address == Address)
{
break;
}
}
{
if (PageOp->Pid == Pid &&
PageOp->Address == Address)
{
break;
}
}
PageOp = PageOp->Next;
}
/*
* If we found an existing pageop then increment the reference count
* and return it.
*/
if (PageOp != NULL)
{
}
/*
* If we found an existing pageop then increment the reference count
* and return it.
*/
if (PageOp != NULL)
{
PageOp->ReferenceCount++;
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
return(PageOp);
}
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
return(NULL);
}
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
return(NULL);
}
PMM_PAGEOP
MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType, BOOL First)
/*
* FUNCTION: Get a page operation descriptor corresponding to
* the memory area and either the segment, offset pair or the
* pid, address pair.
*/
PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType, BOOL First)
/*
* FUNCTION: Get a page operation descriptor corresponding to
* the memory area and either the segment, offset pair or the
* pid, address pair.
*/
{
ULONG Hash;
KIRQL oldIrql;
PMM_PAGEOP PageOp;
ULONG Hash;
KIRQL oldIrql;
PMM_PAGEOP PageOp;
/*
* Calcuate the hash value for pageop structure
*/
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
{
/*
* Calcuate the hash value for pageop structure
*/
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
{
Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE));
}
else
{
}
else
{
Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE));
}
Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
}
Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
/*
* Check for an existing pageop structure
*/
PageOp = MmPageOpHashTable[Hash];
while (PageOp != NULL)
{
/*
* Check for an existing pageop structure
*/
PageOp = MmPageOpHashTable[Hash];
while (PageOp != NULL)
{
if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
{
if (PageOp->Segment == Segment &&
PageOp->Offset == Offset)
{
break;
}
}
{
if (PageOp->Segment == Segment &&
PageOp->Offset == Offset)
{
break;
}
}
else
{
if (PageOp->Pid == Pid &&
PageOp->Address == Address)
{
break;
}
}
{
if (PageOp->Pid == Pid &&
PageOp->Address == Address)
{
break;
}
}
PageOp = PageOp->Next;
}
/*
* If we found an existing pageop then increment the reference count
* and return it.
*/
if (PageOp != NULL)
{
}
/*
* If we found an existing pageop then increment the reference count
* and return it.
*/
if (PageOp != NULL)
{
if (First)
{
PageOp = NULL;
}
{
PageOp = NULL;
}
else
{
PageOp->ReferenceCount++;
}
{
PageOp->ReferenceCount++;
}
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
return(PageOp);
}
}
/*
* Otherwise add a new pageop.
*/
PageOp = ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList);
if (PageOp == NULL)
{
/*
* Otherwise add a new pageop.
*/
PageOp = ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList);
if (PageOp == NULL)
{
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
KEBUGCHECK(0);
return(NULL);
}
if (MArea->Type != MEMORY_AREA_SECTION_VIEW)
{
}
if (MArea->Type != MEMORY_AREA_SECTION_VIEW)
{
PageOp->Pid = Pid;
PageOp->Address = Address;
}
else
{
}
else
{
PageOp->Segment = Segment;
PageOp->Offset = Offset;
}
PageOp->ReferenceCount = 1;
PageOp->Next = MmPageOpHashTable[Hash];
PageOp->Hash = Hash;
PageOp->Thread = PsGetCurrentThread();
PageOp->Abandoned = FALSE;
PageOp->Status = STATUS_PENDING;
PageOp->OpType = OpType;
PageOp->MArea = MArea;
KeInitializeEvent(&PageOp->CompletionEvent, NotificationEvent, FALSE);
MmPageOpHashTable[Hash] = PageOp;
InterlockedIncrement((LONG *)&MArea->PageOpCount);
}
PageOp->ReferenceCount = 1;
PageOp->Next = MmPageOpHashTable[Hash];
PageOp->Hash = Hash;
PageOp->Thread = PsGetCurrentThread();
PageOp->Abandoned = FALSE;
PageOp->Status = STATUS_PENDING;
PageOp->OpType = OpType;
PageOp->MArea = MArea;
KeInitializeEvent(&PageOp->CompletionEvent, NotificationEvent, FALSE);
MmPageOpHashTable[Hash] = PageOp;
InterlockedIncrement((LONG *)&MArea->PageOpCount);
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
return(PageOp);
KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
return(PageOp);
}
VOID INIT_FUNCTION
MmInitializePageOp(VOID)
{
memset(MmPageOpHashTable, 0, sizeof(MmPageOpHashTable));
KeInitializeSpinLock(&MmPageOpHashTableLock);
memset(MmPageOpHashTable, 0, sizeof(MmPageOpHashTable));
KeInitializeSpinLock(&MmPageOpHashTableLock);
ExInitializeNPagedLookasideList (&MmPageOpLookasideList,
NULL,
NULL,
0,
sizeof(MM_PAGEOP),
TAG_MM_PAGEOP,
50);
ExInitializeNPagedLookasideList (&MmPageOpLookasideList,
NULL,
NULL,
0,
sizeof(MM_PAGEOP),
TAG_MM_PAGEOP,
50);
}
+46 -45
View File
@@ -1,4 +1,4 @@
/* $Id: pager.c,v 1.16 2003/11/16 15:20:39 hbirr Exp $
/* $Id: pager.c,v 1.17 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -35,25 +35,25 @@ static ULONG PagerThreadWorkCount;
BOOLEAN
MiIsPagerThread(VOID)
{
return(PsGetCurrentThreadId() == PagerThreadId.UniqueThread);
return(PsGetCurrentThreadId() == PagerThreadId.UniqueThread);
}
VOID
MiStartPagerThread(VOID)
{
ULONG WasWorking;
ULONG WasWorking;
WasWorking = InterlockedIncrement(&PagerThreadWorkCount);
if (WasWorking == 1)
{
WasWorking = InterlockedIncrement(&PagerThreadWorkCount);
if (WasWorking == 1)
{
KeSetEvent(&PagerThreadEvent, IO_NO_INCREMENT, FALSE);
}
}
}
VOID
MiStopPagerThread(VOID)
{
(VOID)InterlockedDecrement(&PagerThreadWorkCount);
(VOID)InterlockedDecrement(&PagerThreadWorkCount);
}
static NTSTATUS STDCALL
@@ -62,53 +62,54 @@ MmPagerThreadMain(PVOID Ignored)
NTSTATUS Status;
for(;;)
{
/* Wake for a low memory situation or a terminate request. */
Status = KeWaitForSingleObject(&PagerThreadEvent,
0,
KernelMode,
FALSE,
NULL);
if (!NT_SUCCESS(Status))
{
DbgPrint("PagerThread: Wait failed\n");
KEBUGCHECK(0);
}
if (PagerThreadShouldTerminate)
{
DbgPrint("PagerThread: Terminating\n");
return(STATUS_SUCCESS);
}
do
{
/* Try and make some memory available to the system. */
MmRebalanceMemoryConsumers();
} while(PagerThreadWorkCount > 0);
}
{
/* Wake for a low memory situation or a terminate request. */
Status = KeWaitForSingleObject(&PagerThreadEvent,
0,
KernelMode,
FALSE,
NULL);
if (!NT_SUCCESS(Status))
{
DbgPrint("PagerThread: Wait failed\n");
KEBUGCHECK(0);
}
if (PagerThreadShouldTerminate)
{
DbgPrint("PagerThread: Terminating\n");
return(STATUS_SUCCESS);
}
do
{
/* Try and make some memory available to the system. */
MmRebalanceMemoryConsumers();
}
while(PagerThreadWorkCount > 0);
}
}
NTSTATUS MmInitPagerThread(VOID)
{
NTSTATUS Status;
PagerThreadShouldTerminate = FALSE;
PagerThreadWorkCount = 0;
KeInitializeEvent(&PagerThreadEvent,
SynchronizationEvent,
FALSE);
SynchronizationEvent,
FALSE);
Status = PsCreateSystemThread(&PagerThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&PagerThreadId,
(PKSTART_ROUTINE) MmPagerThreadMain,
NULL);
THREAD_ALL_ACCESS,
NULL,
NULL,
&PagerThreadId,
(PKSTART_ROUTINE) MmPagerThreadMain,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
{
return(Status);
}
return(STATUS_SUCCESS);
}
#endif
+7 -7
View File
@@ -1,4 +1,4 @@
/* $Id: pagfault.c,v 1.5 2003/07/10 21:05:03 royce Exp $ */
/* $Id: pagfault.c,v 1.6 2004/04/10 22:35:25 gdalsnes Exp $ */
#include <ddk/ntddk.h>
#include <internal/ps.h>
@@ -8,14 +8,14 @@
BOOLEAN
STDCALL
MmIsRecursiveIoFault (
VOID
)
VOID
)
{
PETHREAD Thread = PsGetCurrentThread ();
PETHREAD Thread = PsGetCurrentThread ();
return ( Thread->DisablePageFaultClustering
| Thread->ForwardClusterOnly
);
return ( Thread->DisablePageFaultClustering
| Thread->ForwardClusterOnly
);
}
+64 -57
View File
@@ -1,4 +1,4 @@
/* $Id: pool.c,v 1.27 2004/02/26 18:54:52 navaraf Exp $
/* $Id: pool.c,v 1.28 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -25,40 +25,40 @@
STATIC PVOID STDCALL
EiAllocatePool(POOL_TYPE PoolType,
ULONG NumberOfBytes,
ULONG Tag,
PVOID Caller)
ULONG NumberOfBytes,
ULONG Tag,
PVOID Caller)
{
PVOID Block;
switch(PoolType)
{
{
case NonPagedPool:
case NonPagedPoolMustSucceed:
case NonPagedPoolCacheAligned:
case NonPagedPoolCacheAlignedMustS:
Block =
ExAllocateNonPagedPoolWithTag(PoolType,
NumberOfBytes,
Tag,
Caller);
break;
Block =
ExAllocateNonPagedPoolWithTag(PoolType,
NumberOfBytes,
Tag,
Caller);
break;
case PagedPool:
case PagedPoolCacheAligned:
Block = ExAllocatePagedPoolWithTag(PoolType,NumberOfBytes,Tag);
break;
Block = ExAllocatePagedPoolWithTag(PoolType,NumberOfBytes,Tag);
break;
default:
return(NULL);
};
if ((PoolType==NonPagedPoolMustSucceed ||
PoolType==NonPagedPoolCacheAlignedMustS) && Block==NULL)
{
KEBUGCHECK(MUST_SUCCEED_POOL_EMPTY);
}
return(NULL);
};
if ((PoolType==NonPagedPoolMustSucceed ||
PoolType==NonPagedPoolCacheAlignedMustS) && Block==NULL)
{
KEBUGCHECK(MUST_SUCCEED_POOL_EMPTY);
}
return(Block);
}
@@ -91,18 +91,21 @@ ExAllocatePool (POOL_TYPE PoolType, ULONG NumberOfBytes)
{
PVOID Block;
#if defined(__GNUC__)
Block = EiAllocatePool(PoolType,
NumberOfBytes,
TAG_NONE,
(PVOID)__builtin_return_address(0));
NumberOfBytes,
TAG_NONE,
(PVOID)__builtin_return_address(0));
#elif defined(_MSC_VER)
Block = EiAllocatePool(PoolType,
NumberOfBytes,
TAG_NONE,
&ExAllocatePool);
NumberOfBytes,
TAG_NONE,
&ExAllocatePool);
#else
#error Unknown compiler
#endif
return(Block);
}
@@ -115,18 +118,21 @@ ExAllocatePoolWithTag (ULONG PoolType, ULONG NumberOfBytes, ULONG Tag)
{
PVOID Block;
#if defined(__GNUC__)
Block = EiAllocatePool(PoolType,
NumberOfBytes,
Tag,
(PVOID)__builtin_return_address(0));
NumberOfBytes,
Tag,
(PVOID)__builtin_return_address(0));
#elif defined(_MSC_VER)
Block = EiAllocatePool(PoolType,
NumberOfBytes,
Tag,
&ExAllocatePoolWithTag);
NumberOfBytes,
Tag,
&ExAllocatePoolWithTag);
#else
#error Unknown compiler
#endif
return(Block);
}
@@ -137,7 +143,7 @@ ExAllocatePoolWithTag (ULONG PoolType, ULONG NumberOfBytes, ULONG Tag)
PVOID STDCALL
ExAllocatePoolWithQuota (POOL_TYPE PoolType, ULONG NumberOfBytes)
{
return(ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, TAG_NONE));
return(ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, TAG_NONE));
}
@@ -145,20 +151,21 @@ ExAllocatePoolWithQuota (POOL_TYPE PoolType, ULONG NumberOfBytes)
* @unimplemented
*/
PVOID STDCALL
ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes,
IN ULONG Tag)
ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes,
IN ULONG Tag)
{
#if 0
PVOID Block;
Block = EiAllocatePool(PoolType,
NumberOfBytes,
Tag,
(PVOID)__builtin_return_address(0));
return(Block);
PVOID Block;
Block = EiAllocatePool(PoolType,
NumberOfBytes,
Tag,
(PVOID)__builtin_return_address(0));
return(Block);
#else
UNIMPLEMENTED;
return(NULL);
UNIMPLEMENTED;
return(NULL);
#endif
}
@@ -168,14 +175,14 @@ ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType,
VOID STDCALL
ExFreePool(IN PVOID Block)
{
if (Block >= MmPagedPoolBase && (char*)Block < ((char*)MmPagedPoolBase + MmPagedPoolSize))
{
if (Block >= MmPagedPoolBase && (char*)Block < ((char*)MmPagedPoolBase + MmPagedPoolSize))
{
ExFreePagedPool(Block);
}
else
{
}
else
{
ExFreeNonPagedPool(Block);
}
}
}
/*
@@ -184,8 +191,8 @@ ExFreePool(IN PVOID Block)
VOID STDCALL
ExFreePoolWithTag(IN PVOID Block, IN ULONG Tag)
{
/* FIXME: Validate the tag */
ExFreePool(Block);
/* FIXME: Validate the tag */
ExFreePool(Block);
}
/* EOF */
+331 -325
View File
@@ -1,4 +1,4 @@
/* $Id: ppool.c,v 1.27 2004/03/30 09:28:44 gvg Exp $
/* $Id: ppool.c,v 1.28 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -34,18 +34,21 @@
typedef struct _MM_PPOOL_FREE_BLOCK_HEADER
{
ULONG Size;
struct _MM_PPOOL_FREE_BLOCK_HEADER* NextFree;
} MM_PPOOL_FREE_BLOCK_HEADER, *PMM_PPOOL_FREE_BLOCK_HEADER;
ULONG Size;
struct _MM_PPOOL_FREE_BLOCK_HEADER* NextFree;
}
MM_PPOOL_FREE_BLOCK_HEADER, *PMM_PPOOL_FREE_BLOCK_HEADER;
typedef struct _MM_PPOOL_USED_BLOCK_HEADER
{
ULONG Size;
ULONG Size;
#if MM_PPOOL_REDZONE_BYTES
ULONG UserSize; // how many bytes the user actually asked for...
struct _MM_PPOOL_USED_BLOCK_HEADER* NextUsed;
ULONG UserSize; // how many bytes the user actually asked for...
struct _MM_PPOOL_USED_BLOCK_HEADER* NextUsed;
#endif//MM_PPOOL_REDZONE_BYTES
} MM_PPOOL_USED_BLOCK_HEADER, *PMM_PPOOL_USED_BLOCK_HEADER;
}
MM_PPOOL_USED_BLOCK_HEADER, *PMM_PPOOL_USED_BLOCK_HEADER;
PVOID MmPagedPoolBase;
ULONG MmPagedPoolSize;
@@ -63,49 +66,50 @@ inline static void* block_to_address ( PVOID blk )
* address (internal)
*/
{
return ( (void *) ((char*)blk + sizeof(MM_PPOOL_USED_BLOCK_HEADER) + MM_PPOOL_REDZONE_BYTES) );
return ( (void *) ((char*)blk + sizeof(MM_PPOOL_USED_BLOCK_HEADER) + MM_PPOOL_REDZONE_BYTES) );
}
inline static PMM_PPOOL_USED_BLOCK_HEADER address_to_block(PVOID addr)
{
return (PMM_PPOOL_USED_BLOCK_HEADER)
( ((char*)addr) - sizeof(MM_PPOOL_USED_BLOCK_HEADER) - MM_PPOOL_REDZONE_BYTES );
return (PMM_PPOOL_USED_BLOCK_HEADER)
( ((char*)addr) - sizeof(MM_PPOOL_USED_BLOCK_HEADER) - MM_PPOOL_REDZONE_BYTES );
}
VOID INIT_FUNCTION
MmInitializePagedPool(VOID)
{
MmPagedPoolFirstFreeBlock = (PMM_PPOOL_FREE_BLOCK_HEADER)MmPagedPoolBase;
/*
* We are still at a high IRQL level at this point so explicitly commit
* the first page of the paged pool before writing the first block header.
*/
MmCommitPagedPoolAddress((PVOID)MmPagedPoolFirstFreeBlock, FALSE);
MmPagedPoolFirstFreeBlock->Size = MmPagedPoolSize;
MmPagedPoolFirstFreeBlock->NextFree = NULL;
MmPagedPoolFirstFreeBlock = (PMM_PPOOL_FREE_BLOCK_HEADER)MmPagedPoolBase;
/*
* We are still at a high IRQL level at this point so explicitly commit
* the first page of the paged pool before writing the first block header.
*/
MmCommitPagedPoolAddress((PVOID)MmPagedPoolFirstFreeBlock, FALSE);
MmPagedPoolFirstFreeBlock->Size = MmPagedPoolSize;
MmPagedPoolFirstFreeBlock->NextFree = NULL;
#if MM_PPOOL_REDZONE_BYTES
MmPagedPoolFirstUsedBlock = NULL;
MmPagedPoolFirstUsedBlock = NULL;
#endif//MM_PPOOL_REDZONE_BYTES
ExInitializeFastMutex(&MmPagedPoolLock);
ExInitializeFastMutex(&MmPagedPoolLock);
}
#ifdef ENABLE_VALIDATE_POOL
static void VerifyPagedPool ( int line )
{
PMM_PPOOL_FREE_BLOCK_HEADER p = MmPagedPoolFirstFreeBlock;
int count = 0;
DPRINT ( "VerifyPagedPool(%i):\n", line );
while ( p )
{
DPRINT ( " 0x%x: %lu bytes (next 0x%x)\n", p, p->Size, p->NextFree );
ASSERT_PTR(p);
ASSERT_SIZE(p->Size);
count++;
p = p->NextFree;
}
DPRINT ( "VerifyPagedPool(%i): (%lu blocks)\n", line, count );
PMM_PPOOL_FREE_BLOCK_HEADER p = MmPagedPoolFirstFreeBlock;
int count = 0;
DPRINT ( "VerifyPagedPool(%i):\n", line );
while ( p )
{
DPRINT ( " 0x%x: %lu bytes (next 0x%x)\n", p, p->Size, p->NextFree );
ASSERT_PTR(p);
ASSERT_SIZE(p->Size);
count++;
p = p->NextFree;
}
DPRINT ( "VerifyPagedPool(%i): (%lu blocks)\n", line, count );
}
#define VerifyPagedPool() VerifyPagedPool(__LINE__)
#else
@@ -116,38 +120,38 @@ VOID STDCALL
MmDbgPagedPoolRedZoneCheck ( const char* file, int line )
{
#if MM_PPOOL_REDZONE_BYTES
PMM_PPOOL_USED_BLOCK_HEADER pUsed = MmPagedPoolFirstUsedBlock;
int i;
BOOL bLow = TRUE;
BOOL bHigh = TRUE;
PMM_PPOOL_USED_BLOCK_HEADER pUsed = MmPagedPoolFirstUsedBlock;
int i;
BOOL bLow = TRUE;
BOOL bHigh = TRUE;
while ( pUsed )
{
PUCHAR Addr = (PUCHAR)block_to_address(pUsed);
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
{
bLow = bLow && ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
bHigh = bHigh && ( *(Addr+pUsed->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
}
if ( !bLow || !bHigh )
{
const char* violation = "High and Low-side";
if ( bHigh ) // high is okay, so it was just low failed
violation = "Low-side";
else if ( bLow ) // low side is okay, so it was just high failed
violation = "High-side";
DbgPrint("%s(%i): %s redzone violation detected for paged pool address 0x%x\n",
file, line, violation, Addr );
KEBUGCHECK(0);
}
pUsed = pUsed->NextUsed;
}
while ( pUsed )
{
PUCHAR Addr = (PUCHAR)block_to_address(pUsed);
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
{
bLow = bLow && ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
bHigh = bHigh && ( *(Addr+pUsed->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
}
if ( !bLow || !bHigh )
{
const char* violation = "High and Low-side";
if ( bHigh ) // high is okay, so it was just low failed
violation = "Low-side";
else if ( bLow ) // low side is okay, so it was just high failed
violation = "High-side";
DbgPrint("%s(%i): %s redzone violation detected for paged pool address 0x%x\n",
file, line, violation, Addr );
KEBUGCHECK(0);
}
pUsed = pUsed->NextUsed;
}
#endif//MM_PPOOL_REDZONE_BYTES
}
/**********************************************************************
* NAME INTERNAL
* ExAllocatePagedPoolWithTag@12
* NAME INTERNAL
* ExAllocatePagedPoolWithTag@12
*
* DESCRIPTION
*
@@ -156,181 +160,182 @@ MmDbgPagedPoolRedZoneCheck ( const char* file, int line )
* RETURN VALUE
*/
PVOID STDCALL
ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes,
IN ULONG Tag)
ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes,
IN ULONG Tag)
{
PMM_PPOOL_FREE_BLOCK_HEADER BestBlock;
PMM_PPOOL_FREE_BLOCK_HEADER CurrentBlock;
ULONG BlockSize;
PMM_PPOOL_USED_BLOCK_HEADER NewBlock;
PMM_PPOOL_FREE_BLOCK_HEADER NextBlock;
PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock;
PMM_PPOOL_FREE_BLOCK_HEADER BestPreviousBlock;
PVOID BlockAddress;
ULONG Alignment;
PMM_PPOOL_FREE_BLOCK_HEADER BestBlock;
PMM_PPOOL_FREE_BLOCK_HEADER CurrentBlock;
ULONG BlockSize;
PMM_PPOOL_USED_BLOCK_HEADER NewBlock;
PMM_PPOOL_FREE_BLOCK_HEADER NextBlock;
PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock;
PMM_PPOOL_FREE_BLOCK_HEADER BestPreviousBlock;
PVOID BlockAddress;
ULONG Alignment;
ExAcquireFastMutex(&MmPagedPoolLock);
ExAcquireFastMutex(&MmPagedPoolLock);
/*
* Don't bother allocating anything for a zero-byte block.
*/
if (NumberOfBytes == 0)
{
/*
* Don't bother allocating anything for a zero-byte block.
*/
if (NumberOfBytes == 0)
{
MmDbgPagedPoolRedZoneCheck(__FILE__,__LINE__);
ExReleaseFastMutex(&MmPagedPoolLock);
return(NULL);
}
}
DPRINT ( "ExAllocatePagedPoolWithTag(%i,%lu,%lu)\n", PoolType, NumberOfBytes, Tag );
VerifyPagedPool();
DPRINT ( "ExAllocatePagedPoolWithTag(%i,%lu,%lu)\n", PoolType, NumberOfBytes, Tag );
VerifyPagedPool();
if (NumberOfBytes >= PAGE_SIZE)
{
if (NumberOfBytes >= PAGE_SIZE)
{
Alignment = PAGE_SIZE;
}
else if (PoolType == PagedPoolCacheAligned)
{
}
else if (PoolType == PagedPoolCacheAligned)
{
Alignment = MM_CACHE_LINE_SIZE;
}
else
{
}
else
{
Alignment = MM_POOL_ALIGNMENT;
}
}
/*
* Calculate the total number of bytes we will need.
*/
BlockSize = NumberOfBytes + sizeof(MM_PPOOL_USED_BLOCK_HEADER) + 2*MM_PPOOL_REDZONE_BYTES;
if (BlockSize < sizeof(MM_PPOOL_FREE_BLOCK_HEADER))
{
/* At least we need the size of the free block header. */
BlockSize = sizeof(MM_PPOOL_FREE_BLOCK_HEADER);
}
/*
* Calculate the total number of bytes we will need.
*/
BlockSize = NumberOfBytes + sizeof(MM_PPOOL_USED_BLOCK_HEADER) + 2*MM_PPOOL_REDZONE_BYTES;
if (BlockSize < sizeof(MM_PPOOL_FREE_BLOCK_HEADER))
{
/* At least we need the size of the free block header. */
BlockSize = sizeof(MM_PPOOL_FREE_BLOCK_HEADER);
}
/*
* Find the best-fitting block.
*/
PreviousBlock = NULL;
BestPreviousBlock = BestBlock = NULL;
CurrentBlock = MmPagedPoolFirstFreeBlock;
if ( Alignment > 0 )
{
/*
* Find the best-fitting block.
*/
PreviousBlock = NULL;
BestPreviousBlock = BestBlock = NULL;
CurrentBlock = MmPagedPoolFirstFreeBlock;
if ( Alignment > 0 )
{
PVOID BestAlignedAddr = NULL;
while ( CurrentBlock != NULL )
{
PVOID Addr = block_to_address(CurrentBlock);
PVOID CurrentBlockEnd = (char*)CurrentBlock + CurrentBlock->Size;
/* calculate last size-aligned address available within this block */
PVOID AlignedAddr = MM_ROUND_DOWN((char*)CurrentBlockEnd-NumberOfBytes-MM_PPOOL_REDZONE_BYTES, Alignment);
assert ( (char*)AlignedAddr+NumberOfBytes+MM_PPOOL_REDZONE_BYTES <= (char*)CurrentBlockEnd );
{
PVOID Addr = block_to_address(CurrentBlock);
PVOID CurrentBlockEnd = (char*)CurrentBlock + CurrentBlock->Size;
/* calculate last size-aligned address available within this block */
PVOID AlignedAddr = MM_ROUND_DOWN((char*)CurrentBlockEnd-NumberOfBytes-MM_PPOOL_REDZONE_BYTES, Alignment);
assert ( (char*)AlignedAddr+NumberOfBytes+MM_PPOOL_REDZONE_BYTES <= (char*)CurrentBlockEnd );
/* special case, this address is already size-aligned, and the right size */
if ( Addr == AlignedAddr )
{
BestAlignedAddr = AlignedAddr;
BestPreviousBlock = PreviousBlock;
BestBlock = CurrentBlock;
break;
}
else if ( Addr < (PVOID)address_to_block(AlignedAddr) )
{
/*
* there's enough room to allocate our size-aligned memory out
* of this block, see if it's a better choice than any previous
* finds
*/
if ( BestBlock == NULL || BestBlock->Size > CurrentBlock->Size )
{
BestAlignedAddr = AlignedAddr;
BestPreviousBlock = PreviousBlock;
BestBlock = CurrentBlock;
}
}
/* special case, this address is already size-aligned, and the right size */
if ( Addr == AlignedAddr )
{
BestAlignedAddr = AlignedAddr;
BestPreviousBlock = PreviousBlock;
BestBlock = CurrentBlock;
break;
}
else if ( Addr < (PVOID)address_to_block(AlignedAddr) )
{
/*
* there's enough room to allocate our size-aligned memory out
* of this block, see if it's a better choice than any previous
* finds
*/
if ( BestBlock == NULL || BestBlock->Size > CurrentBlock->Size )
{
BestAlignedAddr = AlignedAddr;
BestPreviousBlock = PreviousBlock;
BestBlock = CurrentBlock;
}
}
PreviousBlock = CurrentBlock;
CurrentBlock = CurrentBlock->NextFree;
}
PreviousBlock = CurrentBlock;
CurrentBlock = CurrentBlock->NextFree;
}
/*
* we found a best block can/should we chop a few bytes off the beginning
* into a separate memory block?
*/
if ( BestBlock != NULL )
{
PVOID Addr = block_to_address(BestBlock);
if ( BestAlignedAddr != Addr )
{
PMM_PPOOL_FREE_BLOCK_HEADER NewFreeBlock =
(PMM_PPOOL_FREE_BLOCK_HEADER)address_to_block(BestAlignedAddr);
assert ( BestAlignedAddr > Addr );
NewFreeBlock->Size = (char*)Addr + BestBlock->Size - (char*)BestAlignedAddr;
ASSERT_SIZE(NewFreeBlock->Size);
BestBlock->Size = (size_t)NewFreeBlock - (size_t)Addr;
ASSERT_SIZE(BestBlock->Size);
{
PVOID Addr = block_to_address(BestBlock);
if ( BestAlignedAddr != Addr )
{
PMM_PPOOL_FREE_BLOCK_HEADER NewFreeBlock =
(PMM_PPOOL_FREE_BLOCK_HEADER)address_to_block(BestAlignedAddr);
assert ( BestAlignedAddr > Addr );
NewFreeBlock->Size = (char*)Addr + BestBlock->Size - (char*)BestAlignedAddr;
ASSERT_SIZE(NewFreeBlock->Size);
BestBlock->Size = (size_t)NewFreeBlock - (size_t)Addr;
ASSERT_SIZE(BestBlock->Size);
DPRINT ( "breaking off preceding bytes into their own block...\n" );
DPRINT ( "NewFreeBlock 0x%x Size %lu (Old Block's new size %lu) NextFree 0x%x\n",
NewFreeBlock, NewFreeBlock->Size, BestBlock->Size, BestBlock->NextFree );
DPRINT ( "breaking off preceding bytes into their own block...\n" );
DPRINT ( "NewFreeBlock 0x%x Size %lu (Old Block's new size %lu) NextFree 0x%x\n",
NewFreeBlock, NewFreeBlock->Size, BestBlock->Size, BestBlock->NextFree );
/* insert the new block into the chain */
NewFreeBlock->NextFree = BestBlock->NextFree;
BestBlock->NextFree = NewFreeBlock;
/* insert the new block into the chain */
NewFreeBlock->NextFree = BestBlock->NextFree;
BestBlock->NextFree = NewFreeBlock;
/* we want the following code to use our size-aligned block */
BestPreviousBlock = BestBlock;
BestBlock = NewFreeBlock;
/* we want the following code to use our size-aligned block */
BestPreviousBlock = BestBlock;
BestBlock = NewFreeBlock;
//VerifyPagedPool();
}
}
}
/*
* non-size-aligned block search
*/
else while ( CurrentBlock != NULL )
{
if ( CurrentBlock->Size >= BlockSize
&& ( BestBlock == NULL || BestBlock->Size > CurrentBlock->Size )
)
{
BestPreviousBlock = PreviousBlock;
BestBlock = CurrentBlock;
}
//VerifyPagedPool();
}
}
}
/*
* non-size-aligned block search
*/
else
while ( CurrentBlock != NULL )
{
if ( CurrentBlock->Size >= BlockSize
&& ( BestBlock == NULL || BestBlock->Size > CurrentBlock->Size )
)
{
BestPreviousBlock = PreviousBlock;
BestBlock = CurrentBlock;
}
PreviousBlock = CurrentBlock;
CurrentBlock = CurrentBlock->NextFree;
}
PreviousBlock = CurrentBlock;
CurrentBlock = CurrentBlock->NextFree;
}
/*
* We didn't find anything suitable at all.
*/
if (BestBlock == NULL)
{
/*
* We didn't find anything suitable at all.
*/
if (BestBlock == NULL)
{
DPRINT1("Trying to allocate %lu bytes from paged pool - nothing suitable found, returning NULL\n",
NumberOfBytes );
ExReleaseFastMutex(&MmPagedPoolLock);
return(NULL);
}
}
DPRINT("BestBlock 0x%x NextFree 0x%x\n", BestBlock, BestBlock->NextFree );
DPRINT("BestBlock 0x%x NextFree 0x%x\n", BestBlock, BestBlock->NextFree );
//VerifyPagedPool();
//VerifyPagedPool();
/*
* Is there enough space to create a second block from the unused portion.
*/
if ( BestBlock->Size > BlockSize
&& (BestBlock->Size - BlockSize) > sizeof(MM_PPOOL_FREE_BLOCK_HEADER)
)
{
/*
* Is there enough space to create a second block from the unused portion.
*/
if ( BestBlock->Size > BlockSize
&& (BestBlock->Size - BlockSize) > sizeof(MM_PPOOL_FREE_BLOCK_HEADER)
)
{
ULONG NewSize = BestBlock->Size - BlockSize;
ASSERT_SIZE ( NewSize );
//DPRINT("creating 2nd block from unused portion\n");
DPRINT("BestBlock 0x%x Size 0x%x BlockSize 0x%x NewSize 0x%x\n",
BestBlock, BestBlock->Size, BlockSize, NewSize );
BestBlock, BestBlock->Size, BlockSize, NewSize );
/*
* Create the new free block.
@@ -349,15 +354,15 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
*/
//DPRINT("replacing old free block with it");
if (BestPreviousBlock == NULL)
{
//DPRINT("(from beginning)");
MmPagedPoolFirstFreeBlock = NextBlock;
}
{
//DPRINT("(from beginning)");
MmPagedPoolFirstFreeBlock = NextBlock;
}
else
{
//DPRINT("(from previous)");
BestPreviousBlock->NextFree = NextBlock;
}
{
//DPRINT("(from previous)");
BestPreviousBlock->NextFree = NextBlock;
}
//DPRINT(".\n");
/*
@@ -369,9 +374,9 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
NewBlock->Size = BlockSize;
ASSERT_SIZE ( NewBlock->Size );
//DPRINT(".\n");
}
else
{
}
else
{
ULONG NewSize = BestBlock->Size;
/*
@@ -379,13 +384,13 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
*/
//DPRINT ( "Removing selected block from free block list\n" );
if (BestPreviousBlock == NULL)
{
MmPagedPoolFirstFreeBlock = BestBlock->NextFree;
}
{
MmPagedPoolFirstFreeBlock = BestBlock->NextFree;
}
else
{
BestPreviousBlock->NextFree = BestBlock->NextFree;
}
{
BestPreviousBlock->NextFree = BestBlock->NextFree;
}
/*
* Set up the header of the new block
@@ -393,167 +398,168 @@ ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
NewBlock = (PMM_PPOOL_USED_BLOCK_HEADER)BestBlock;
NewBlock->Size = NewSize;
ASSERT_SIZE ( NewBlock->Size );
}
}
#if MM_PPOOL_REDZONE_BYTES
// now add the block to the used block list
NewBlock->NextUsed = MmPagedPoolFirstUsedBlock;
MmPagedPoolFirstUsedBlock = NewBlock;
// now add the block to the used block list
NewBlock->NextUsed = MmPagedPoolFirstUsedBlock;
MmPagedPoolFirstUsedBlock = NewBlock;
#endif//MM_PPOOL_REDZONE_BYTES
VerifyPagedPool();
VerifyPagedPool();
ExReleaseFastMutex(&MmPagedPoolLock);
ExReleaseFastMutex(&MmPagedPoolLock);
BlockAddress = block_to_address ( NewBlock );
/* RtlZeroMemory(BlockAddress, NumberOfBytes);*/
BlockAddress = block_to_address ( NewBlock );
/* RtlZeroMemory(BlockAddress, NumberOfBytes);*/
#if MM_PPOOL_REDZONE_BYTES
NewBlock->UserSize = NumberOfBytes;
// write out buffer-overrun detection bytes
{
PUCHAR Addr = (PUCHAR)BlockAddress;
//DbgPrint ( "writing buffer-overrun detection bytes" );
memset ( Addr - MM_PPOOL_REDZONE_BYTES,
MM_PPOOL_REDZONE_VALUE, MM_PPOOL_REDZONE_BYTES );
memset ( Addr + NewBlock->UserSize, MM_PPOOL_REDZONE_VALUE,
MM_PPOOL_REDZONE_BYTES );
/*for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
{
//DbgPrint(".");
*(Addr-i-1) = 0xCD;
//DbgPrint("o");
*(Addr+NewBlock->UserSize+i) = 0xCD;
}*/
//DbgPrint ( "done!\n" );
}
NewBlock->UserSize = NumberOfBytes;
// write out buffer-overrun detection bytes
{
PUCHAR Addr = (PUCHAR)BlockAddress;
//DbgPrint ( "writing buffer-overrun detection bytes" );
memset ( Addr - MM_PPOOL_REDZONE_BYTES,
MM_PPOOL_REDZONE_VALUE, MM_PPOOL_REDZONE_BYTES );
memset ( Addr + NewBlock->UserSize, MM_PPOOL_REDZONE_VALUE,
MM_PPOOL_REDZONE_BYTES );
/*for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
{
//DbgPrint(".");
*(Addr-i-1) = 0xCD;
//DbgPrint("o");
*(Addr+NewBlock->UserSize+i) = 0xCD;
}*/
//DbgPrint ( "done!\n" );
}
#endif//MM_PPOOL_REDZONE_BYTES
return(BlockAddress);
return(BlockAddress);
}
VOID STDCALL
ExFreePagedPool(IN PVOID Block)
{
PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock;
PMM_PPOOL_USED_BLOCK_HEADER UsedBlock = address_to_block(Block);
ULONG UsedSize = UsedBlock->Size;
PMM_PPOOL_FREE_BLOCK_HEADER FreeBlock =
(PMM_PPOOL_FREE_BLOCK_HEADER)UsedBlock;
PMM_PPOOL_FREE_BLOCK_HEADER NextBlock;
PMM_PPOOL_FREE_BLOCK_HEADER NextNextBlock;
PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock;
PMM_PPOOL_USED_BLOCK_HEADER UsedBlock = address_to_block(Block);
ULONG UsedSize = UsedBlock->Size;
PMM_PPOOL_FREE_BLOCK_HEADER FreeBlock =
(PMM_PPOOL_FREE_BLOCK_HEADER)UsedBlock;
PMM_PPOOL_FREE_BLOCK_HEADER NextBlock;
PMM_PPOOL_FREE_BLOCK_HEADER NextNextBlock;
#if MM_PPOOL_REDZONE_BYTES
// write out buffer-overrun detection bytes
{
int i;
PUCHAR Addr = (PUCHAR)Block;
//DbgPrint ( "checking buffer-overrun detection bytes..." );
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
{
if (*(Addr-i-1) != MM_PPOOL_REDZONE_VALUE)
// write out buffer-overrun detection bytes
{
int i;
PUCHAR Addr = (PUCHAR)Block;
//DbgPrint ( "checking buffer-overrun detection bytes..." );
for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
{
DPRINT1("Attempt to free memory %#08x. Redzone underrun!\n", Block);
}
if (*(Addr+UsedBlock->UserSize+i) != MM_PPOOL_REDZONE_VALUE)
{
DPRINT1("Attempt to free memory %#08x. Redzone overrun!\n", Block);
}
if (*(Addr-i-1) != MM_PPOOL_REDZONE_VALUE)
{
DPRINT1("Attempt to free memory %#08x. Redzone underrun!\n", Block);
}
if (*(Addr+UsedBlock->UserSize+i) != MM_PPOOL_REDZONE_VALUE)
{
DPRINT1("Attempt to free memory %#08x. Redzone overrun!\n", Block);
}
assert ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
assert ( *(Addr+UsedBlock->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
}
//DbgPrint ( "done!\n" );
}
assert ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
assert ( *(Addr+UsedBlock->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
}
//DbgPrint ( "done!\n" );
}
#endif//MM_PPOOL_REDZONE_BYTES
ExAcquireFastMutex(&MmPagedPoolLock);
ExAcquireFastMutex(&MmPagedPoolLock);
#if MM_PPOOL_REDZONE_BYTES
// remove from used list...
{
PMM_PPOOL_USED_BLOCK_HEADER pPrev = MmPagedPoolFirstUsedBlock;
if ( pPrev == UsedBlock )
{
// special-case, our freeing block is first in list...
MmPagedPoolFirstUsedBlock = pPrev->NextUsed;
}
else
{
while ( pPrev && pPrev->NextUsed != UsedBlock )
pPrev = pPrev->NextUsed;
// if this assert fails - memory has been corrupted
// ( or I have a logic error...! )
assert ( pPrev->NextUsed == UsedBlock );
pPrev->NextUsed = UsedBlock->NextUsed;
}
}
// remove from used list...
{
PMM_PPOOL_USED_BLOCK_HEADER pPrev = MmPagedPoolFirstUsedBlock;
if ( pPrev == UsedBlock )
{
// special-case, our freeing block is first in list...
MmPagedPoolFirstUsedBlock = pPrev->NextUsed;
}
else
{
while ( pPrev && pPrev->NextUsed != UsedBlock )
pPrev = pPrev->NextUsed;
// if this assert fails - memory has been corrupted
// ( or I have a logic error...! )
assert ( pPrev->NextUsed == UsedBlock );
pPrev->NextUsed = UsedBlock->NextUsed;
}
}
#endif//MM_PPOOL_REDZONE_BYTES
/*
* Begin setting up the newly freed block's header.
*/
FreeBlock->Size = UsedSize;
ASSERT_SIZE ( FreeBlock->Size );
/*
* Begin setting up the newly freed block's header.
*/
FreeBlock->Size = UsedSize;
ASSERT_SIZE ( FreeBlock->Size );
/*
* Find the blocks immediately before and after the newly freed block on the free list.
*/
PreviousBlock = NULL;
NextBlock = MmPagedPoolFirstFreeBlock;
while (NextBlock != NULL && NextBlock < FreeBlock)
{
/*
* Find the blocks immediately before and after the newly freed block on the free list.
*/
PreviousBlock = NULL;
NextBlock = MmPagedPoolFirstFreeBlock;
while (NextBlock != NULL && NextBlock < FreeBlock)
{
PreviousBlock = NextBlock;
NextBlock = NextBlock->NextFree;
}
}
/*
* Insert the freed block on the free list.
*/
if (PreviousBlock == NULL)
{
/*
* Insert the freed block on the free list.
*/
if (PreviousBlock == NULL)
{
FreeBlock->NextFree = MmPagedPoolFirstFreeBlock;
MmPagedPoolFirstFreeBlock = FreeBlock;
}
else
{
}
else
{
PreviousBlock->NextFree = FreeBlock;
FreeBlock->NextFree = NextBlock;
}
}
/*
* If the next block is immediately adjacent to the newly freed one then
* merge them.
*/
if (NextBlock != NULL &&
((char*)FreeBlock + FreeBlock->Size) == (char*)NextBlock)
{
/*
* If the next block is immediately adjacent to the newly freed one then
* merge them.
*/
if (NextBlock != NULL &&
((char*)FreeBlock + FreeBlock->Size) == (char*)NextBlock)
{
FreeBlock->Size = FreeBlock->Size + NextBlock->Size;
ASSERT_SIZE ( FreeBlock->Size );
FreeBlock->NextFree = NextBlock->NextFree;
NextNextBlock = NextBlock->NextFree;
}
else
{
}
else
{
NextNextBlock = NextBlock;
}
}
/*
* If the previous block is adjacent to the newly freed one then
* merge them.
*/
if (PreviousBlock != NULL &&
((char*)PreviousBlock + PreviousBlock->Size) == (char*)FreeBlock)
{
/*
* If the previous block is adjacent to the newly freed one then
* merge them.
*/
if (PreviousBlock != NULL &&
((char*)PreviousBlock + PreviousBlock->Size) == (char*)FreeBlock)
{
PreviousBlock->Size = PreviousBlock->Size + FreeBlock->Size;
ASSERT_SIZE ( PreviousBlock->Size );
PreviousBlock->NextFree = NextNextBlock;
}
}
VerifyPagedPool();
VerifyPagedPool();
ExReleaseFastMutex(&MmPagedPoolLock);
ExReleaseFastMutex(&MmPagedPoolLock);
}
/* EOF */
+204 -200
View File
@@ -16,14 +16,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: region.c,v 1.6 2003/12/30 18:52:05 fireball Exp $
/* $Id: region.c,v 1.7 2004/04/10 22:35:25 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/region.c
* PROGRAMMER: David Welch
* PURPOSE:
*/
/* INCLUDE *****************************************************************/
#include <ddk/ntddk.h>
@@ -43,279 +43,283 @@
/* FUNCTIONS *****************************************************************/
VOID STATIC
VOID STATIC
InsertAfterEntry(PLIST_ENTRY Previous,
PLIST_ENTRY Entry)
PLIST_ENTRY Entry)
/*
* FUNCTION: Insert a list entry after another entry in the list
*/
{
Previous->Flink->Blink = Entry;
Entry->Flink = Previous->Flink;
Entry->Blink = Previous;
Previous->Flink = Entry;
}
PMM_REGION STATIC
MmSplitRegion(PMM_REGION InitialRegion, PVOID InitialBaseAddress,
PVOID StartAddress, ULONG Length, ULONG NewType,
ULONG NewProtect, PMADDRESS_SPACE AddressSpace,
PMM_ALTER_REGION_FUNC AlterFunc)
PVOID StartAddress, ULONG Length, ULONG NewType,
ULONG NewProtect, PMADDRESS_SPACE AddressSpace,
PMM_ALTER_REGION_FUNC AlterFunc)
{
PMM_REGION NewRegion1;
PMM_REGION NewRegion2;
ULONG InternalLength;
/* Allocate this in front otherwise the failure case is too difficult. */
NewRegion2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
TAG_MM_REGION);
if (NewRegion2 == NULL)
{
return(NULL);
}
PMM_REGION NewRegion1;
PMM_REGION NewRegion2;
ULONG InternalLength;
/* Create the new region. */
NewRegion1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
TAG_MM_REGION);
if (NewRegion1 == NULL)
{
/* Allocate this in front otherwise the failure case is too difficult. */
NewRegion2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
TAG_MM_REGION);
if (NewRegion2 == NULL)
{
return(NULL);
}
/* Create the new region. */
NewRegion1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
TAG_MM_REGION);
if (NewRegion1 == NULL)
{
ExFreePool(NewRegion2);
return(NULL);
}
NewRegion1->Type = NewType;
NewRegion1->Protect = NewProtect;
InternalLength = ((char*)InitialBaseAddress + InitialRegion->Length) - (char*)StartAddress;
InternalLength = min(InternalLength, Length);
NewRegion1->Length = InternalLength;
InsertAfterEntry(&InitialRegion->RegionListEntry,
&NewRegion1->RegionListEntry);
}
NewRegion1->Type = NewType;
NewRegion1->Protect = NewProtect;
InternalLength = ((char*)InitialBaseAddress + InitialRegion->Length) - (char*)StartAddress;
InternalLength = min(InternalLength, Length);
NewRegion1->Length = InternalLength;
InsertAfterEntry(&InitialRegion->RegionListEntry,
&NewRegion1->RegionListEntry);
/*
* Call our helper function to do the changes on the addresses contained
* in the initial region.
*/
AlterFunc(AddressSpace, StartAddress, InternalLength, InitialRegion->Type,
InitialRegion->Protect, NewType, NewProtect);
/*
* Call our helper function to do the changes on the addresses contained
* in the initial region.
*/
AlterFunc(AddressSpace, StartAddress, InternalLength, InitialRegion->Type,
InitialRegion->Protect, NewType, NewProtect);
/*
* If necessary create a new region for the portion of the initial region
* beyond the range of addresses to alter.
*/
if (((char*)InitialBaseAddress + InitialRegion->Length) > ((char*)StartAddress + Length))
{
/*
* If necessary create a new region for the portion of the initial region
* beyond the range of addresses to alter.
*/
if (((char*)InitialBaseAddress + InitialRegion->Length) > ((char*)StartAddress + Length))
{
NewRegion2->Type = InitialRegion->Type;
NewRegion2->Protect = InitialRegion->Protect;
NewRegion2->Length = ((char*)InitialBaseAddress + InitialRegion->Length) -
((char*)StartAddress + Length);
InsertAfterEntry(&NewRegion1->RegionListEntry,
&NewRegion2->RegionListEntry);
}
else
{
NewRegion2->Length = ((char*)InitialBaseAddress + InitialRegion->Length) -
((char*)StartAddress + Length);
InsertAfterEntry(&NewRegion1->RegionListEntry,
&NewRegion2->RegionListEntry);
}
else
{
ExFreePool(NewRegion2);
}
}
/* Either remove or shrink the initial region. */
if (InitialBaseAddress == StartAddress)
{
/* Either remove or shrink the initial region. */
if (InitialBaseAddress == StartAddress)
{
RemoveEntryList(&InitialRegion->RegionListEntry);
ExFreePool(InitialRegion);
}
else
{
}
else
{
InitialRegion->Length = (char*)StartAddress - (char*)InitialBaseAddress;
}
return(NewRegion1);
}
return(NewRegion1);
}
NTSTATUS
MmAlterRegion(PMADDRESS_SPACE AddressSpace, PVOID BaseAddress,
PLIST_ENTRY RegionListHead, PVOID StartAddress, ULONG Length,
ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc)
MmAlterRegion(PMADDRESS_SPACE AddressSpace, PVOID BaseAddress,
PLIST_ENTRY RegionListHead, PVOID StartAddress, ULONG Length,
ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc)
{
PMM_REGION InitialRegion;
PVOID InitialBaseAddress;
PMM_REGION NewRegion;
PLIST_ENTRY CurrentEntry;
PMM_REGION CurrentRegion = NULL;
PVOID CurrentBaseAddress;
ULONG RemainingLength;
PMM_REGION InitialRegion;
PVOID InitialBaseAddress;
PMM_REGION NewRegion;
PLIST_ENTRY CurrentEntry;
PMM_REGION CurrentRegion = NULL;
PVOID CurrentBaseAddress;
ULONG RemainingLength;
/*
* Find the first region containing part of the range of addresses to
* be altered.
*/
InitialRegion = MmFindRegion(BaseAddress, RegionListHead, StartAddress,
&InitialBaseAddress);
if (((char*)StartAddress + Length) >
((char*)InitialBaseAddress + InitialRegion->Length))
{
RemainingLength = ((char*)StartAddress + Length) -
((char*)InitialBaseAddress + InitialRegion->Length);
}
else
{
/*
* Find the first region containing part of the range of addresses to
* be altered.
*/
InitialRegion = MmFindRegion(BaseAddress, RegionListHead, StartAddress,
&InitialBaseAddress);
if (((char*)StartAddress + Length) >
((char*)InitialBaseAddress + InitialRegion->Length))
{
RemainingLength = ((char*)StartAddress + Length) -
((char*)InitialBaseAddress + InitialRegion->Length);
}
else
{
RemainingLength = 0;
}
/*
* If necessary then split the region into the affected and unaffected parts.
*/
if (InitialRegion->Type != NewType || InitialRegion->Protect != NewProtect)
{
NewRegion = MmSplitRegion(InitialRegion, InitialBaseAddress,
StartAddress, Length, NewType, NewProtect,
AddressSpace, AlterFunc);
}
/*
* If necessary then split the region into the affected and unaffected parts.
*/
if (InitialRegion->Type != NewType || InitialRegion->Protect != NewProtect)
{
NewRegion = MmSplitRegion(InitialRegion, InitialBaseAddress,
StartAddress, Length, NewType, NewProtect,
AddressSpace, AlterFunc);
if (NewRegion == NULL)
{
return(STATUS_NO_MEMORY);
}
}
else
{
{
return(STATUS_NO_MEMORY);
}
}
else
{
NewRegion = InitialRegion;
}
/*
* Free any complete regions that are containing in the range of addresses
* and call the helper function to actually do the changes.
*/
CurrentEntry = NewRegion->RegionListEntry.Flink;
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
CurrentBaseAddress = (char*)StartAddress + NewRegion->Length;
while (RemainingLength > 0 && CurrentRegion->Length <= RemainingLength)
{
}
/*
* Free any complete regions that are containing in the range of addresses
* and call the helper function to actually do the changes.
*/
CurrentEntry = NewRegion->RegionListEntry.Flink;
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
CurrentBaseAddress = (char*)StartAddress + NewRegion->Length;
while (RemainingLength > 0 && CurrentRegion->Length <= RemainingLength)
{
if (CurrentRegion->Type != NewType &&
CurrentRegion->Protect != NewProtect)
{
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
CurrentRegion->Type, CurrentRegion->Protect,
NewType, NewProtect);
}
CurrentRegion->Protect != NewProtect)
{
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
CurrentRegion->Type, CurrentRegion->Protect,
NewType, NewProtect);
}
#if defined(__GNUC__)
CurrentBaseAddress += CurrentRegion->Length;
#else
{
char* pTemp = CurrentBaseAddress;
pTemp += CurrentRegion->Length;
CurrentBaseAddress = pTemp;
char* pTemp = CurrentBaseAddress;
pTemp += CurrentRegion->Length;
CurrentBaseAddress = pTemp;
}
#endif
NewRegion->Length += CurrentRegion->Length;
RemainingLength -= CurrentRegion->Length;
CurrentEntry = CurrentEntry->Flink;
CurrentEntry = CurrentEntry->Flink;
RemoveEntryList(&CurrentRegion->RegionListEntry);
ExFreePool(CurrentRegion);
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
}
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
}
/*
* Split any final region.
*/
if (RemainingLength > 0)
{
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
/*
* Split any final region.
*/
if (RemainingLength > 0)
{
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
if (CurrentRegion->Type != NewType &&
CurrentRegion->Protect != NewProtect)
{
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
CurrentRegion->Type, CurrentRegion->Protect,
NewType, NewProtect);
}
CurrentRegion->Protect != NewProtect)
{
AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length,
CurrentRegion->Type, CurrentRegion->Protect,
NewType, NewProtect);
}
NewRegion->Length += RemainingLength;
CurrentRegion->Length -= RemainingLength;
}
}
/*
* If the region after the new region has the same type then merge them.
*/
if (NewRegion->RegionListEntry.Flink != RegionListHead)
{
/*
* If the region after the new region has the same type then merge them.
*/
if (NewRegion->RegionListEntry.Flink != RegionListHead)
{
CurrentEntry = NewRegion->RegionListEntry.Flink;
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
if (CurrentRegion->Type == NewRegion->Type &&
CurrentRegion->Protect == NewRegion->Protect)
{
NewRegion->Length += CurrentRegion->Length;
RemoveEntryList(&CurrentRegion->RegionListEntry);
ExFreePool(CurrentRegion);
}
}
CurrentRegion->Protect == NewRegion->Protect)
{
NewRegion->Length += CurrentRegion->Length;
RemoveEntryList(&CurrentRegion->RegionListEntry);
ExFreePool(CurrentRegion);
}
}
/*
* If the region before the new region has the same type then merge them.
*/
if (NewRegion->RegionListEntry.Blink != RegionListHead)
{
/*
* If the region before the new region has the same type then merge them.
*/
if (NewRegion->RegionListEntry.Blink != RegionListHead)
{
CurrentEntry = NewRegion->RegionListEntry.Blink;
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION,
RegionListEntry);
if (CurrentRegion->Type == NewRegion->Type &&
CurrentRegion->Protect == NewRegion->Protect)
{
NewRegion->Length += CurrentRegion->Length;
RemoveEntryList(&CurrentRegion->RegionListEntry);
ExFreePool(CurrentRegion);
}
}
CurrentRegion->Protect == NewRegion->Protect)
{
NewRegion->Length += CurrentRegion->Length;
RemoveEntryList(&CurrentRegion->RegionListEntry);
ExFreePool(CurrentRegion);
}
}
return(STATUS_SUCCESS);
return(STATUS_SUCCESS);
}
VOID
MmInitialiseRegion(PLIST_ENTRY RegionListHead, ULONG Length, ULONG Type,
ULONG Protect)
ULONG Protect)
{
PMM_REGION Region;
PMM_REGION Region;
Region = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
TAG_MM_REGION);
Region->Type = Type;
Region->Protect = Protect;
Region->Length = Length;
InitializeListHead(RegionListHead);
InsertHeadList(RegionListHead, &Region->RegionListEntry);
Region = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION),
TAG_MM_REGION);
Region->Type = Type;
Region->Protect = Protect;
Region->Length = Length;
InitializeListHead(RegionListHead);
InsertHeadList(RegionListHead, &Region->RegionListEntry);
}
PMM_REGION
MmFindRegion(PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address,
PVOID* RegionBaseAddress)
PVOID* RegionBaseAddress)
{
PLIST_ENTRY current_entry;
PMM_REGION current;
PVOID StartAddress = BaseAddress;
current_entry = RegionListHead->Flink;
while (current_entry != RegionListHead)
{
PLIST_ENTRY current_entry;
PMM_REGION current;
PVOID StartAddress = BaseAddress;
current_entry = RegionListHead->Flink;
while (current_entry != RegionListHead)
{
current = CONTAINING_RECORD(current_entry, MM_REGION, RegionListEntry);
if (StartAddress <= Address &&
((char*)StartAddress + current->Length) > (char*)Address)
{
if (RegionBaseAddress != NULL)
{
*RegionBaseAddress = StartAddress;
}
return(current);
}
if (StartAddress <= Address &&
((char*)StartAddress + current->Length) > (char*)Address)
{
if (RegionBaseAddress != NULL)
{
*RegionBaseAddress = StartAddress;
}
return(current);
}
current_entry = current_entry->Flink;
#if defined(__GNUC__)
StartAddress += current->Length;
#else
{
char* pTemp = StartAddress;
pTemp += current->Length;
StartAddress = pTemp;
char* pTemp = StartAddress;
pTemp += current->Length;
StartAddress = pTemp;
}
#endif
}
return(NULL);
}
return(NULL);
}
+286 -285
View File
@@ -16,7 +16,7 @@
* 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.27 2004/03/05 11:31:59 hbirr Exp $
/* $Id: rmap.c,v 1.28 2004/04/10 22:35:25 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel
@@ -40,10 +40,11 @@
typedef struct _MM_RMAP_ENTRY
{
struct _MM_RMAP_ENTRY* Next;
PEPROCESS Process;
PVOID Address;
} MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
struct _MM_RMAP_ENTRY* Next;
PEPROCESS Process;
PVOID Address;
}
MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
#define TAG_RMAP TAG('R', 'M', 'A', 'P')
@@ -57,126 +58,100 @@ static NPAGED_LOOKASIDE_LIST RmapLookasideList;
VOID INIT_FUNCTION
MmInitializeRmapList(VOID)
{
ExInitializeFastMutex(&RmapListLock);
ExInitializeNPagedLookasideList (&RmapLookasideList,
NULL,
NULL,
0,
sizeof(MM_RMAP_ENTRY),
TAG_RMAP,
50);
ExInitializeFastMutex(&RmapListLock);
ExInitializeNPagedLookasideList (&RmapLookasideList,
NULL,
NULL,
0,
sizeof(MM_RMAP_ENTRY),
TAG_RMAP,
50);
}
NTSTATUS
MmWritePagePhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress)
{
PMM_RMAP_ENTRY entry;
PMEMORY_AREA MemoryArea;
PMADDRESS_SPACE AddressSpace;
ULONG Type;
PVOID Address;
PEPROCESS Process;
PMM_PAGEOP PageOp;
ULONG Offset;
NTSTATUS Status = STATUS_SUCCESS;
PMM_RMAP_ENTRY entry;
PMEMORY_AREA MemoryArea;
PMADDRESS_SPACE AddressSpace;
ULONG Type;
PVOID Address;
PEPROCESS Process;
PMM_PAGEOP PageOp;
ULONG Offset;
NTSTATUS Status = STATUS_SUCCESS;
/*
* Check that the address still has a valid rmap; then reference the
* process so it isn't freed while we are working.
*/
ExAcquireFastMutex(&RmapListLock);
entry = MmGetRmapListHeadPage(PhysicalAddress);
if (entry == NULL)
{
/*
* Check that the address still has a valid rmap; then reference the
* process so it isn't freed while we are working.
*/
ExAcquireFastMutex(&RmapListLock);
entry = MmGetRmapListHeadPage(PhysicalAddress);
if (entry == NULL)
{
ExReleaseFastMutex(&RmapListLock);
return(STATUS_UNSUCCESSFUL);
}
Process = entry->Process;
Address = entry->Address;
if ((((ULONG)Address) & 0xFFF) != 0)
{
}
Process = entry->Process;
Address = entry->Address;
if ((((ULONG)Address) & 0xFFF) != 0)
{
KEBUGCHECK(0);
}
if (Address < (PVOID)KERNEL_BASE)
{
}
if (Address < (PVOID)KERNEL_BASE)
{
Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
ExReleaseFastMutex(&RmapListLock);
if (!NT_SUCCESS(Status))
{
return Status;
}
{
return Status;
}
AddressSpace = &Process->AddressSpace;
}
else
{
}
else
{
ExReleaseFastMutex(&RmapListLock);
AddressSpace = MmGetKernelAddressSpace();
}
}
/*
* Lock the address space; then check that the address we are using
* still corresponds to a valid memory area (the page might have been
* freed or paged out after we read the rmap entry.)
*/
MmLockAddressSpace(AddressSpace);
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
/*
* Lock the address space; then check that the address we are using
* still corresponds to a valid memory area (the page might have been
* freed or paged out after we read the rmap entry.)
*/
MmLockAddressSpace(AddressSpace);
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
MmUnlockAddressSpace(AddressSpace);
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
{
ObDereferenceObject(Process);
}
return(STATUS_UNSUCCESSFUL);
}
}
Type = MemoryArea->Type;
if (Type == MEMORY_AREA_SECTION_VIEW)
{
Type = MemoryArea->Type;
if (Type == MEMORY_AREA_SECTION_VIEW)
{
Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress);
/*
* Get or create a pageop
*/
PageOp = MmGetPageOp(MemoryArea, 0, 0,
MemoryArea->Data.SectionData.Segment,
Offset, MM_PAGEOP_PAGEOUT, TRUE);
PageOp = MmGetPageOp(MemoryArea, 0, 0,
MemoryArea->Data.SectionData.Segment,
Offset, MM_PAGEOP_PAGEOUT, TRUE);
if (PageOp == NULL)
{
MmUnlockAddressSpace(AddressSpace);
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
return(STATUS_UNSUCCESSFUL);
}
/*
* Release locks now we have a page op.
*/
MmUnlockAddressSpace(AddressSpace);
/*
* Do the actual page out work.
*/
Status = MmWritePageSectionView(AddressSpace, MemoryArea,
Address, PageOp);
}
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
{
PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : 0,
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
if (PageOp == NULL)
{
MmUnlockAddressSpace(AddressSpace);
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
return(STATUS_UNSUCCESSFUL);
}
{
MmUnlockAddressSpace(AddressSpace);
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
return(STATUS_UNSUCCESSFUL);
}
/*
* Release locks now we have a page op.
@@ -186,95 +161,121 @@ MmWritePagePhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress)
/*
* Do the actual page out work.
*/
Status = MmWritePageVirtualMemory(AddressSpace, MemoryArea,
Address, PageOp);
}
else
{
Status = MmWritePageSectionView(AddressSpace, MemoryArea,
Address, PageOp);
}
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
{
PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : 0,
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
if (PageOp == NULL)
{
MmUnlockAddressSpace(AddressSpace);
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
return(STATUS_UNSUCCESSFUL);
}
/*
* Release locks now we have a page op.
*/
MmUnlockAddressSpace(AddressSpace);
/*
* Do the actual page out work.
*/
Status = MmWritePageVirtualMemory(AddressSpace, MemoryArea,
Address, PageOp);
}
else
{
KEBUGCHECK(0);
}
if (Address < (PVOID)KERNEL_BASE)
{
}
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
return(Status);
}
return(Status);
}
NTSTATUS
MmPageOutPhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress)
{
PMM_RMAP_ENTRY entry;
PMEMORY_AREA MemoryArea;
PMADDRESS_SPACE AddressSpace;
ULONG Type;
PVOID Address;
PEPROCESS Process;
PMM_PAGEOP PageOp;
ULONG Offset;
NTSTATUS Status = STATUS_SUCCESS;
PMM_RMAP_ENTRY entry;
PMEMORY_AREA MemoryArea;
PMADDRESS_SPACE AddressSpace;
ULONG Type;
PVOID Address;
PEPROCESS Process;
PMM_PAGEOP PageOp;
ULONG Offset;
NTSTATUS Status = STATUS_SUCCESS;
ExAcquireFastMutex(&RmapListLock);
entry = MmGetRmapListHeadPage(PhysicalAddress);
if (entry == NULL || MmGetLockCountPage(PhysicalAddress) != 0)
{
ExAcquireFastMutex(&RmapListLock);
entry = MmGetRmapListHeadPage(PhysicalAddress);
if (entry == NULL || MmGetLockCountPage(PhysicalAddress) != 0)
{
ExReleaseFastMutex(&RmapListLock);
return(STATUS_UNSUCCESSFUL);
}
Process = entry->Process;
Address = entry->Address;
if ((((ULONG)Address) & 0xFFF) != 0)
{
}
Process = entry->Process;
Address = entry->Address;
if ((((ULONG)Address) & 0xFFF) != 0)
{
KEBUGCHECK(0);
}
}
if (Address < (PVOID)KERNEL_BASE)
{
if (Address < (PVOID)KERNEL_BASE)
{
Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
ExReleaseFastMutex(&RmapListLock);
if (!NT_SUCCESS(Status))
{
return Status;
}
{
return Status;
}
AddressSpace = &Process->AddressSpace;
}
else
{
}
else
{
ExReleaseFastMutex(&RmapListLock);
AddressSpace = MmGetKernelAddressSpace();
}
}
MmLockAddressSpace(AddressSpace);
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
MmLockAddressSpace(AddressSpace);
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
{
MmUnlockAddressSpace(AddressSpace);
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
{
ObDereferenceObject(Process);
}
return(STATUS_UNSUCCESSFUL);
}
Type = MemoryArea->Type;
if (Type == MEMORY_AREA_SECTION_VIEW)
{
}
Type = MemoryArea->Type;
if (Type == MEMORY_AREA_SECTION_VIEW)
{
Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress);
/*
* Get or create a pageop
*/
PageOp = MmGetPageOp(MemoryArea, 0, 0,
MemoryArea->Data.SectionData.Segment,
Offset, MM_PAGEOP_PAGEOUT, TRUE);
PageOp = MmGetPageOp(MemoryArea, 0, 0,
MemoryArea->Data.SectionData.Segment,
Offset, MM_PAGEOP_PAGEOUT, TRUE);
if (PageOp == NULL)
{
MmUnlockAddressSpace(AddressSpace);
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
return(STATUS_UNSUCCESSFUL);
}
{
MmUnlockAddressSpace(AddressSpace);
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
return(STATUS_UNSUCCESSFUL);
}
/*
* Release locks now we have a page op.
*/
@@ -283,22 +284,22 @@ MmPageOutPhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress)
/*
* Do the actual page out work.
*/
Status = MmPageOutSectionView(AddressSpace, MemoryArea,
Address, PageOp);
}
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
{
Status = MmPageOutSectionView(AddressSpace, MemoryArea,
Address, PageOp);
}
else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
{
PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : 0,
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
if (PageOp == NULL)
{
MmUnlockAddressSpace(AddressSpace);
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
return(STATUS_UNSUCCESSFUL);
}
{
MmUnlockAddressSpace(AddressSpace);
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
return(STATUS_UNSUCCESSFUL);
}
/*
* Release locks now we have a page op.
@@ -308,177 +309,177 @@ MmPageOutPhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress)
/*
* Do the actual page out work.
*/
Status = MmPageOutVirtualMemory(AddressSpace, MemoryArea,
Address, PageOp);
}
else
{
Status = MmPageOutVirtualMemory(AddressSpace, MemoryArea,
Address, PageOp);
}
else
{
KEBUGCHECK(0);
}
if (Address < (PVOID)KERNEL_BASE)
{
}
if (Address < (PVOID)KERNEL_BASE)
{
ObDereferenceObject(Process);
}
return(Status);
}
return(Status);
}
VOID
MmSetCleanAllRmaps(PHYSICAL_ADDRESS PhysicalAddress)
{
PMM_RMAP_ENTRY current_entry;
PMM_RMAP_ENTRY current_entry;
ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
if (current_entry == NULL)
{
ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
if (current_entry == NULL)
{
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
KEBUGCHECK(0);
}
while (current_entry != NULL)
{
}
while (current_entry != NULL)
{
MmSetCleanPage(current_entry->Process, current_entry->Address);
current_entry = current_entry->Next;
}
ExReleaseFastMutex(&RmapListLock);
}
ExReleaseFastMutex(&RmapListLock);
}
VOID
MmSetDirtyAllRmaps(PHYSICAL_ADDRESS PhysicalAddress)
{
PMM_RMAP_ENTRY current_entry;
PMM_RMAP_ENTRY current_entry;
ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
if (current_entry == NULL)
{
ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
if (current_entry == NULL)
{
DPRINT1("MmIsDirtyRmap: No rmaps.\n");
KEBUGCHECK(0);
}
while (current_entry != NULL)
{
}
while (current_entry != NULL)
{
MmSetDirtyPage(current_entry->Process, current_entry->Address);
current_entry = current_entry->Next;
}
ExReleaseFastMutex(&RmapListLock);
}
ExReleaseFastMutex(&RmapListLock);
}
BOOL
MmIsDirtyPageRmap(PHYSICAL_ADDRESS PhysicalAddress)
{
PMM_RMAP_ENTRY current_entry;
PMM_RMAP_ENTRY current_entry;
ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
if (current_entry == NULL)
{
ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
if (current_entry == NULL)
{
ExReleaseFastMutex(&RmapListLock);
return(FALSE);
}
while (current_entry != NULL)
{
}
while (current_entry != NULL)
{
if (MmIsDirtyPage(current_entry->Process, current_entry->Address))
{
ExReleaseFastMutex(&RmapListLock);
return(TRUE);
}
{
ExReleaseFastMutex(&RmapListLock);
return(TRUE);
}
current_entry = current_entry->Next;
}
ExReleaseFastMutex(&RmapListLock);
return(FALSE);
}
ExReleaseFastMutex(&RmapListLock);
return(FALSE);
}
VOID
MmInsertRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process,
PVOID Address)
MmInsertRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process,
PVOID Address)
{
PMM_RMAP_ENTRY current_entry;
PMM_RMAP_ENTRY new_entry;
PMM_RMAP_ENTRY current_entry;
PMM_RMAP_ENTRY new_entry;
Address = (PVOID)PAGE_ROUND_DOWN(Address);
Address = (PVOID)PAGE_ROUND_DOWN(Address);
new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
if (new_entry == NULL)
{
new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
if (new_entry == NULL)
{
KEBUGCHECK(0);
}
new_entry->Address = Address;
new_entry->Process = Process;
}
new_entry->Address = Address;
new_entry->Process = Process;
if (MmGetPhysicalAddressForProcess(Process, Address).QuadPart !=
PhysicalAddress.QuadPart)
{
if (MmGetPhysicalAddressForProcess(Process, Address).QuadPart !=
PhysicalAddress.QuadPart)
{
DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical "
"address 0x%.8X\n", Process->UniqueProcessId, Address,
MmGetPhysicalAddressForProcess(Process, Address).u.LowPart,
PhysicalAddress.u.LowPart);
"address 0x%.8X\n", Process->UniqueProcessId, Address,
MmGetPhysicalAddressForProcess(Process, Address).u.LowPart,
PhysicalAddress.u.LowPart);
KEBUGCHECK(0);
}
}
ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
new_entry->Next = current_entry;
MmSetRmapListHeadPage(PhysicalAddress, new_entry);
ExReleaseFastMutex(&RmapListLock);
ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
new_entry->Next = current_entry;
MmSetRmapListHeadPage(PhysicalAddress, new_entry);
ExReleaseFastMutex(&RmapListLock);
}
VOID
MmDeleteAllRmaps(PHYSICAL_ADDRESS PhysicalAddress, PVOID Context,
VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
PVOID Address))
MmDeleteAllRmaps(PHYSICAL_ADDRESS PhysicalAddress, PVOID Context,
VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
PVOID Address))
{
PMM_RMAP_ENTRY current_entry;
PMM_RMAP_ENTRY previous_entry;
PMM_RMAP_ENTRY current_entry;
PMM_RMAP_ENTRY previous_entry;
ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
if (current_entry == NULL)
{
ExAcquireFastMutex(&RmapListLock);
current_entry = MmGetRmapListHeadPage(PhysicalAddress);
if (current_entry == NULL)
{
DPRINT1("MmDeleteAllRmaps: No rmaps.\n");
KEBUGCHECK(0);
}
MmSetRmapListHeadPage(PhysicalAddress, NULL);
while (current_entry != NULL)
{
}
MmSetRmapListHeadPage(PhysicalAddress, NULL);
while (current_entry != NULL)
{
previous_entry = current_entry;
current_entry = current_entry->Next;
if (DeleteMapping)
{
DeleteMapping(Context, previous_entry->Process,
previous_entry->Address);
}
{
DeleteMapping(Context, previous_entry->Process,
previous_entry->Address);
}
ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
}
ExReleaseFastMutex(&RmapListLock);
}
ExReleaseFastMutex(&RmapListLock);
}
VOID
MmDeleteRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process,
PVOID Address)
MmDeleteRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process,
PVOID Address)
{
PMM_RMAP_ENTRY current_entry, previous_entry;
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);
}
else
{
previous_entry->Next = current_entry->Next;
}
ExReleaseFastMutex(&RmapListLock);
ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
return;
}
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);
}
else
{
previous_entry->Next = current_entry->Next;
}
ExReleaseFastMutex(&RmapListLock);
ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
return;
}
previous_entry = current_entry;
current_entry = current_entry->Next;
}
KEBUGCHECK(0);
}
KEBUGCHECK(0);
}
+2824 -2820
View File
File diff suppressed because it is too large Load Diff
+195 -192
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: slab.c,v 1.11 2004/03/04 00:07:02 navaraf Exp $
/* $Id: slab.c,v 1.12 2004/04/10 22:35:26 gdalsnes Exp $
*
* COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel
@@ -44,27 +44,30 @@ struct _SLAB_CACHE_PAGE;
typedef struct _SLAB_CACHE
{
SLAB_CACHE_CONSTRUCTOR Constructor;
SLAB_CACHE_DESTRUCTOR Destructor;
ULONG BaseSize;
ULONG ObjectSize;
ULONG ObjectsPerPage;
LIST_ENTRY PageListHead;
struct _SLAB_CACHE_PAGE* FirstFreePage;
KSPIN_LOCK SlabLock;
} SLAB_CACHE, *PSLAB_CACHE;
SLAB_CACHE_CONSTRUCTOR Constructor;
SLAB_CACHE_DESTRUCTOR Destructor;
ULONG BaseSize;
ULONG ObjectSize;
ULONG ObjectsPerPage;
LIST_ENTRY PageListHead;
struct _SLAB_CACHE_PAGE* FirstFreePage;
KSPIN_LOCK SlabLock;
}
SLAB_CACHE, *PSLAB_CACHE;
typedef struct _SLAB_CACHE_BUFCTL
{
struct _SLAB_CACHE_BUFCTL* NextFree;
} SLAB_CACHE_BUFCTL, *PSLAB_CACHE_BUFCTL;
struct _SLAB_CACHE_BUFCTL* NextFree;
}
SLAB_CACHE_BUFCTL, *PSLAB_CACHE_BUFCTL;
typedef struct _SLAB_CACHE_PAGE
{
LIST_ENTRY PageListEntry;
PSLAB_CACHE_BUFCTL FirstFreeBuffer;
ULONG ReferenceCount;
} SLAB_CACHE_PAGE, *PSLAB_CACHE_PAGE;
LIST_ENTRY PageListEntry;
PSLAB_CACHE_BUFCTL FirstFreeBuffer;
ULONG ReferenceCount;
}
SLAB_CACHE_PAGE, *PSLAB_CACHE_PAGE;
/* GLOBALS ******************************************************************/
@@ -72,252 +75,252 @@ typedef struct _SLAB_CACHE_PAGE
PSLAB_CACHE
ExCreateSlabCache(PUNICODE_STRING Name, ULONG Size, ULONG Align,
SLAB_CACHE_CONSTRUCTOR Constructor,
SLAB_CACHE_DESTRUCTOR Destructor)
SLAB_CACHE_CONSTRUCTOR Constructor,
SLAB_CACHE_DESTRUCTOR Destructor)
{
PSLAB_CACHE Slab;
ULONG ObjectSize;
ULONG AlignSize;
PSLAB_CACHE Slab;
ULONG ObjectSize;
ULONG AlignSize;
Slab = ExAllocatePool(NonPagedPool, sizeof(SLAB_CACHE));
if (Slab == NULL)
{
Slab = ExAllocatePool(NonPagedPool, sizeof(SLAB_CACHE));
if (Slab == NULL)
{
return(NULL);
}
}
Slab->Constructor = Constructor;
Slab->Destructor = Destructor;
Slab->BaseSize = Size;
ObjectSize = Size + sizeof(SLAB_CACHE_BUFCTL);
AlignSize = Align - (ObjectSize % Align);
Slab->ObjectSize = ObjectSize + AlignSize;
Slab->ObjectsPerPage =
(PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) / Slab->ObjectSize;
Slab->FirstFreePage = NULL;
InitializeListHead(&Slab->PageListHead);
KeInitializeSpinLock(&Slab->SlabLock);
return(Slab);
Slab->Constructor = Constructor;
Slab->Destructor = Destructor;
Slab->BaseSize = Size;
ObjectSize = Size + sizeof(SLAB_CACHE_BUFCTL);
AlignSize = Align - (ObjectSize % Align);
Slab->ObjectSize = ObjectSize + AlignSize;
Slab->ObjectsPerPage =
(PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) / Slab->ObjectSize;
Slab->FirstFreePage = NULL;
InitializeListHead(&Slab->PageListHead);
KeInitializeSpinLock(&Slab->SlabLock);
return(Slab);
}
PSLAB_CACHE_PAGE
ExGrowSlabCache(PSLAB_CACHE Slab)
{
PSLAB_CACHE_PAGE SlabPage;
PHYSICAL_ADDRESS PhysicalPage;
PVOID Page;
NTSTATUS Status;
ULONG i;
PSLAB_CACHE_BUFCTL BufCtl;
PVOID Object;
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &PhysicalPage);
if (!NT_SUCCESS(Status))
{
return(NULL);
}
PSLAB_CACHE_PAGE SlabPage;
PHYSICAL_ADDRESS PhysicalPage;
PVOID Page;
NTSTATUS Status;
ULONG i;
PSLAB_CACHE_BUFCTL BufCtl;
PVOID Object;
Page = ExAllocatePageWithPhysPage(PhysicalPage);
if (Page == NULL)
{
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &PhysicalPage);
if (!NT_SUCCESS(Status))
{
return(NULL);
}
Page = ExAllocatePageWithPhysPage(PhysicalPage);
if (Page == NULL)
{
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysicalPage);
return(NULL);
}
}
SlabPage = (PSLAB_CACHE_PAGE)((char*)Page + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE));
SlabPage->ReferenceCount = 0;
SlabPage->FirstFreeBuffer = (PSLAB_CACHE_BUFCTL)Page;
for (i = 0; i < Slab->ObjectsPerPage; i++)
{
SlabPage = (PSLAB_CACHE_PAGE)((char*)Page + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE));
SlabPage->ReferenceCount = 0;
SlabPage->FirstFreeBuffer = (PSLAB_CACHE_BUFCTL)Page;
for (i = 0; i < Slab->ObjectsPerPage; i++)
{
BufCtl = (PSLAB_CACHE_BUFCTL)((char*)Page + (i * Slab->ObjectSize));
Object = (PVOID)(BufCtl + 1);
if (Slab->Constructor != NULL)
{
Slab->Constructor(Object, Slab->BaseSize);
}
{
Slab->Constructor(Object, Slab->BaseSize);
}
if (i == (Slab->ObjectsPerPage - 1))
{
BufCtl->NextFree =
(PSLAB_CACHE_BUFCTL)((char*)Page + ((i + 1) * Slab->ObjectSize));
}
{
BufCtl->NextFree =
(PSLAB_CACHE_BUFCTL)((char*)Page + ((i + 1) * Slab->ObjectSize));
}
else
{
BufCtl->NextFree = NULL;
}
}
{
BufCtl->NextFree = NULL;
}
}
return(SlabPage);
return(SlabPage);
}
PVOID
ExAllocateSlabCache(PSLAB_CACHE Slab, BOOLEAN MayWait)
{
KIRQL oldIrql;
PSLAB_CACHE_PAGE Page;
PVOID Object;
BOOLEAN NewPage;
KIRQL oldIrql;
PSLAB_CACHE_PAGE Page;
PVOID Object;
BOOLEAN NewPage;
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
/*
* Check if there is a page with free objects
* present, if so allocate from it, if
* not grow the slab.
*/
if (Slab->FirstFreePage == NULL)
{
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
/*
* Check if there is a page with free objects
* present, if so allocate from it, if
* not grow the slab.
*/
if (Slab->FirstFreePage == NULL)
{
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
Page = ExGrowSlabCache(Slab);
NewPage = TRUE;
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
}
else
{
}
else
{
Page = Slab->FirstFreePage;
NewPage = FALSE;
}
/*
* We shouldn't have got a page without free buffers.
*/
if (Page->FirstFreeBuffer == NULL)
{
}
/*
* We shouldn't have got a page without free buffers.
*/
if (Page->FirstFreeBuffer == NULL)
{
DPRINT1("First free page had no free buffers.\n");
KEBUGCHECK(0);
}
}
/*
* Allocate the first free object from the page.
*/
Object = (PVOID)((char*)Page->FirstFreeBuffer + sizeof(SLAB_CACHE_BUFCTL));
Page->FirstFreeBuffer = Page->FirstFreeBuffer->NextFree;
Page->ReferenceCount++;
/*
* Allocate the first free object from the page.
*/
Object = (PVOID)((char*)Page->FirstFreeBuffer + sizeof(SLAB_CACHE_BUFCTL));
Page->FirstFreeBuffer = Page->FirstFreeBuffer->NextFree;
Page->ReferenceCount++;
/*
* If we just allocated all the objects from this page
* and it was the first free page then adjust the
* first free page pointer and move the page to the head
* of the list.
*/
if (Page->ReferenceCount == Slab->ObjectsPerPage && !NewPage)
{
/*
* If we just allocated all the objects from this page
* and it was the first free page then adjust the
* first free page pointer and move the page to the head
* of the list.
*/
if (Page->ReferenceCount == Slab->ObjectsPerPage && !NewPage)
{
if (Page->PageListEntry.Flink == &Slab->PageListHead)
{
Slab->FirstFreePage = NULL;
}
{
Slab->FirstFreePage = NULL;
}
else
{
PSLAB_CACHE_PAGE NextPage;
NextPage = CONTAINING_RECORD(Page->PageListEntry.Flink,
SLAB_CACHE_PAGE,
PageListEntry);
Slab->FirstFreePage = NextPage;
}
{
PSLAB_CACHE_PAGE NextPage;
NextPage = CONTAINING_RECORD(Page->PageListEntry.Flink,
SLAB_CACHE_PAGE,
PageListEntry);
Slab->FirstFreePage = NextPage;
}
RemoveEntryList(&Page->PageListEntry);
InsertHeadList(&Slab->PageListHead, &Page->PageListEntry);
}
/*
* Otherwise if we created a new page then add it to the end of
* the page list.
*/
else if (NewPage)
{
}
/*
* Otherwise if we created a new page then add it to the end of
* the page list.
*/
else if (NewPage)
{
InsertTailList(&Slab->PageListHead, &Page->PageListEntry);
if (Slab->FirstFreePage == NULL)
{
Slab->FirstFreePage = Page;
}
}
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
return(Object);
{
Slab->FirstFreePage = Page;
}
}
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
return(Object);
}
VOID
ExFreeFromPageSlabCache(PSLAB_CACHE Slab,
PSLAB_CACHE_PAGE Page,
PVOID Object)
PSLAB_CACHE_PAGE Page,
PVOID Object)
{
PSLAB_CACHE_BUFCTL BufCtl;
PSLAB_CACHE_BUFCTL BufCtl;
BufCtl = (PSLAB_CACHE_BUFCTL)((char*)Object - sizeof(SLAB_CACHE_BUFCTL));
BufCtl->NextFree = Page->FirstFreeBuffer;
Page->FirstFreeBuffer = BufCtl;
Page->ReferenceCount--;
BufCtl = (PSLAB_CACHE_BUFCTL)((char*)Object - sizeof(SLAB_CACHE_BUFCTL));
BufCtl->NextFree = Page->FirstFreeBuffer;
Page->FirstFreeBuffer = BufCtl;
Page->ReferenceCount--;
}
VOID
ExFreeSlabCache(PSLAB_CACHE Slab, PVOID Object)
{
KIRQL oldIrql;
PLIST_ENTRY current_entry;
PSLAB_CACHE_PAGE current;
KIRQL oldIrql;
PLIST_ENTRY current_entry;
PSLAB_CACHE_PAGE current;
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
current_entry = Slab->PageListHead.Flink;
while (current_entry != &Slab->PageListHead)
{
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
current_entry = Slab->PageListHead.Flink;
while (current_entry != &Slab->PageListHead)
{
PVOID Base;
current = CONTAINING_RECORD(current_entry,
SLAB_CACHE_PAGE,
PageListEntry);
SLAB_CACHE_PAGE,
PageListEntry);
Base = (PVOID)((char*)current + sizeof(SLAB_CACHE_PAGE) - PAGE_SIZE);
if (Base >= Object &&
((char*)Base + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) >=
((char*)Object + Slab->ObjectSize))
{
ExFreeFromPageSlabCache(Slab, current, Object);
/*
* If the page just become free then rearrange things.
*/
if (current->ReferenceCount == 0)
{
RemoveEntryList(&current->PageListEntry);
InsertTailList(&Slab->PageListHead, &current->PageListEntry);
if (Slab->FirstFreePage == NULL)
{
Slab->FirstFreePage = current;
}
}
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
return;
}
}
DPRINT1("Tried to free object not in cache.\n");
KEBUGCHECK(0);
if (Base >= Object &&
((char*)Base + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) >=
((char*)Object + Slab->ObjectSize))
{
ExFreeFromPageSlabCache(Slab, current, Object);
/*
* If the page just become free then rearrange things.
*/
if (current->ReferenceCount == 0)
{
RemoveEntryList(&current->PageListEntry);
InsertTailList(&Slab->PageListHead, &current->PageListEntry);
if (Slab->FirstFreePage == NULL)
{
Slab->FirstFreePage = current;
}
}
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
return;
}
}
DPRINT1("Tried to free object not in cache.\n");
KEBUGCHECK(0);
}
VOID
ExDestroySlabCache(PSLAB_CACHE Slab)
{
PLIST_ENTRY current_entry;
PSLAB_CACHE_PAGE current;
ULONG i;
PVOID Object;
PLIST_ENTRY current_entry;
PSLAB_CACHE_PAGE current;
ULONG i;
PVOID Object;
current_entry = Slab->PageListHead.Flink;
while (current_entry != &Slab->PageListHead)
{
current_entry = Slab->PageListHead.Flink;
while (current_entry != &Slab->PageListHead)
{
PVOID Base;
PHYSICAL_ADDRESS PhysicalPage;
current = CONTAINING_RECORD(current_entry,
SLAB_CACHE_PAGE,
PageListEntry);
SLAB_CACHE_PAGE,
PageListEntry);
Base = (PVOID)((char*)current + sizeof(SLAB_CACHE_PAGE) - PAGE_SIZE);
if (Slab->Destructor != NULL)
{
for (i = 0; i < Slab->ObjectsPerPage; i++)
{
Object = (char*)Base + (i * Slab->ObjectSize) +
sizeof(SLAB_CACHE_BUFCTL);
Slab->Destructor(Object, Slab->BaseSize);
}
}
{
for (i = 0; i < Slab->ObjectsPerPage; i++)
{
Object = (char*)Base + (i * Slab->ObjectSize) +
sizeof(SLAB_CACHE_BUFCTL);
Slab->Destructor(Object, Slab->BaseSize);
}
}
PhysicalPage = MmGetPhysicalAddressForProcess(NULL, Base);
ExUnmapPage(Base);
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysicalPage);
}
ExFreePool(Slab);
}
ExFreePool(Slab);
}
+331 -331
View File
@@ -16,14 +16,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: virtual.c,v 1.71 2003/12/14 17:44:02 hbirr Exp $
/* $Id: virtual.c,v 1.72 2004/04/10 22:35:26 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/virtual.c
* PURPOSE: Implementing operations on virtual memory.
* PROGRAMMER: David Welch
*/
/* INCLUDE *****************************************************************/
#include <ddk/ntddk.h>
@@ -39,11 +39,11 @@
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
NtFlushVirtualMemory(IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN ULONG NumberOfBytesToFlush,
OUT PULONG NumberOfBytesFlushed OPTIONAL)
NTSTATUS STDCALL
NtFlushVirtualMemory(IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN ULONG NumberOfBytesToFlush,
OUT PULONG NumberOfBytesFlushed OPTIONAL)
/*
* FUNCTION: Flushes virtual memory to file
* ARGUMENTS:
@@ -55,152 +55,152 @@ NtFlushVirtualMemory(IN HANDLE ProcessHandle,
* RETURNS: Status
*/
{
UNIMPLEMENTED;
return(STATUS_NOT_IMPLEMENTED);
UNIMPLEMENTED;
return(STATUS_NOT_IMPLEMENTED);
}
NTSTATUS STDCALL
NtLockVirtualMemory(HANDLE ProcessHandle,
PVOID BaseAddress,
ULONG NumberOfBytesToLock,
PULONG NumberOfBytesLocked) // ULONG LockOption?
NTSTATUS STDCALL
NtLockVirtualMemory(HANDLE ProcessHandle,
PVOID BaseAddress,
ULONG NumberOfBytesToLock,
PULONG NumberOfBytesLocked) // ULONG LockOption?
{
// AG [08-20-03] : I have *no* idea if this is correct, I just used the
// other functions as a template and made a few intelligent guesses...
// AG [08-20-03] : I have *no* idea if this is correct, I just used the
// other functions as a template and made a few intelligent guesses...
NTSTATUS Status;
PMDL Mdl;
PEPROCESS Process;
DPRINT("NtLockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
"NumberOfBytesToLock %d), NumberOfBytesLocked %x\n",ProcessHandle,BaseAddress,
NumberOfBytesToLock, NumberOfBytesLocked);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
if (Status != STATUS_SUCCESS)
{
NTSTATUS Status;
PMDL Mdl;
PEPROCESS Process;
DPRINT("NtLockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
"NumberOfBytesToLock %d), NumberOfBytesLocked %x\n",ProcessHandle,BaseAddress,
NumberOfBytesToLock, NumberOfBytesLocked);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
if (Status != STATUS_SUCCESS)
{
return(Status);
}
Mdl = MmCreateMdl(NULL,
BaseAddress,
NumberOfBytesToLock);
MmProbeAndLockPages(Mdl,
UserMode,
IoWriteAccess);
ExFreePool(Mdl); // Are we supposed to do this here?
ObDereferenceObject(Process);
*NumberOfBytesLocked = NumberOfBytesToLock;
return(STATUS_SUCCESS);
}
Mdl = MmCreateMdl(NULL,
BaseAddress,
NumberOfBytesToLock);
MmProbeAndLockPages(Mdl,
UserMode,
IoWriteAccess);
ExFreePool(Mdl); // Are we supposed to do this here?
ObDereferenceObject(Process);
*NumberOfBytesLocked = NumberOfBytesToLock;
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
NTSTATUS STDCALL
NtQueryVirtualMemory (IN HANDLE ProcessHandle,
IN PVOID Address,
IN CINT VirtualMemoryInformationClass,
OUT PVOID VirtualMemoryInformation,
IN ULONG Length,
OUT PULONG UnsafeResultLength)
IN PVOID Address,
IN CINT VirtualMemoryInformationClass,
OUT PVOID VirtualMemoryInformation,
IN ULONG Length,
OUT PULONG UnsafeResultLength)
{
NTSTATUS Status;
PEPROCESS Process;
MEMORY_AREA* MemoryArea;
ULONG ResultLength = 0;
PMADDRESS_SPACE AddressSpace;
DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, "
"VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, "
"Length %lu ResultLength %x)\n",ProcessHandle,Address,
VirtualMemoryInformationClass,VirtualMemoryInformation,
Length,ResultLength);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
PROCESS_QUERY_INFORMATION,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("NtQueryVirtualMemory() = %x\n",Status);
return(Status);
}
{
DPRINT("NtQueryVirtualMemory() = %x\n",Status);
return(Status);
}
AddressSpace = &Process->AddressSpace;
MmLockAddressSpace(AddressSpace);
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
Address);
Address);
switch(VirtualMemoryInformationClass)
{
case MemoryBasicInformation:
{
PMEMORY_BASIC_INFORMATION Info =
(PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
if (Length != sizeof(MEMORY_BASIC_INFORMATION))
{
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
return(STATUS_INFO_LENGTH_MISMATCH);
}
if (MemoryArea == NULL)
{
Info->State = MEM_FREE;
Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
Status = STATUS_SUCCESS;
ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
}
else if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
{
Status = MmQueryAnonMem(MemoryArea, Address, Info,
&ResultLength);
}
else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
{
Status = MmQuerySectionView(MemoryArea, Address, Info,
&ResultLength);
}
else
{
Status = STATUS_UNSUCCESSFUL;
ResultLength = 0;
}
break;
}
default:
{
Status = STATUS_INVALID_INFO_CLASS;
ResultLength = 0;
break;
}
}
{
case MemoryBasicInformation:
{
PMEMORY_BASIC_INFORMATION Info =
(PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation;
if (Length != sizeof(MEMORY_BASIC_INFORMATION))
{
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
return(STATUS_INFO_LENGTH_MISMATCH);
}
if (MemoryArea == NULL)
{
Info->State = MEM_FREE;
Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
Status = STATUS_SUCCESS;
ResultLength = sizeof(MEMORY_BASIC_INFORMATION);
}
else if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
{
Status = MmQueryAnonMem(MemoryArea, Address, Info,
&ResultLength);
}
else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
{
Status = MmQuerySectionView(MemoryArea, Address, Info,
&ResultLength);
}
else
{
Status = STATUS_UNSUCCESSFUL;
ResultLength = 0;
}
break;
}
default:
{
Status = STATUS_INVALID_INFO_CLASS;
ResultLength = 0;
break;
}
}
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
if (UnsafeResultLength != NULL)
{
MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
}
{
MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG));
}
return(Status);
}
NTSTATUS STDCALL
NtProtectVirtualMemory(IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN ULONG NumberOfBytesToProtect,
IN ULONG NewAccessProtection,
OUT PULONG UnsafeOldAccessProtection)
NtProtectVirtualMemory(IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN ULONG NumberOfBytesToProtect,
IN ULONG NewAccessProtection,
OUT PULONG UnsafeOldAccessProtection)
{
PMEMORY_AREA MemoryArea;
PEPROCESS Process;
@@ -209,210 +209,210 @@ NtProtectVirtualMemory(IN HANDLE ProcessHandle,
ULONG OldAccessProtection;
NumberOfBytesToProtect =
PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) -
PAGE_ROUND_DOWN(BaseAddress);
PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) -
PAGE_ROUND_DOWN(BaseAddress);
BaseAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_OPERATION,
PsProcessType,
UserMode,
(PVOID*)(&Process),
NULL);
PROCESS_VM_OPERATION,
PsProcessType,
UserMode,
(PVOID*)(&Process),
NULL);
if (Status != STATUS_SUCCESS)
{
DPRINT("NtProtectVirtualMemory() = %x\n",Status);
return(Status);
}
{
DPRINT("NtProtectVirtualMemory() = %x\n",Status);
return(Status);
}
AddressSpace = &Process->AddressSpace;
MmLockAddressSpace(AddressSpace);
MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
BaseAddress);
BaseAddress);
if (MemoryArea == NULL)
{
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
return(STATUS_UNSUCCESSFUL);
}
{
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
return(STATUS_UNSUCCESSFUL);
}
if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY)
{
Status = MmProtectAnonMem(AddressSpace, MemoryArea, BaseAddress,
NumberOfBytesToProtect, NewAccessProtection,
&OldAccessProtection);
}
{
Status = MmProtectAnonMem(AddressSpace, MemoryArea, BaseAddress,
NumberOfBytesToProtect, NewAccessProtection,
&OldAccessProtection);
}
else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
{
Status = MmProtectSectionView(AddressSpace, MemoryArea, BaseAddress,
NumberOfBytesToProtect,
NewAccessProtection,
&OldAccessProtection);
}
{
Status = MmProtectSectionView(AddressSpace, MemoryArea, BaseAddress,
NumberOfBytesToProtect,
NewAccessProtection,
&OldAccessProtection);
}
MmUnlockAddressSpace(AddressSpace);
ObDereferenceObject(Process);
MmCopyToCaller(UnsafeOldAccessProtection, &OldAccessProtection,
sizeof(ULONG));
MmCopyToCaller(UnsafeOldAccessProtection, &OldAccessProtection,
sizeof(ULONG));
return(Status);
}
NTSTATUS STDCALL
NtReadVirtualMemory(IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
OUT PVOID Buffer,
IN ULONG NumberOfBytesToRead,
OUT PULONG NumberOfBytesRead)
{
NTSTATUS Status;
PMDL Mdl;
PVOID SystemAddress;
PEPROCESS Process;
DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
"Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
Buffer,NumberOfBytesToRead);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
if (Status != STATUS_SUCCESS)
{
return(Status);
}
Mdl = MmCreateMdl(NULL,
Buffer,
NumberOfBytesToRead);
MmProbeAndLockPages(Mdl,
UserMode,
IoWriteAccess);
KeAttachProcess(Process);
SystemAddress = MmGetSystemAddressForMdl(Mdl);
memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
KeDetachProcess();
if (Mdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
MmUnlockPages(Mdl);
ExFreePool(Mdl);
ObDereferenceObject(Process);
*NumberOfBytesRead = NumberOfBytesToRead;
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
NtUnlockVirtualMemory(HANDLE ProcessHandle,
PVOID BaseAddress,
ULONG NumberOfBytesToUnlock,
PULONG NumberOfBytesUnlocked OPTIONAL)
{
// AG [08-20-03] : I have *no* idea if this is correct, I just used the
// other functions as a template and made a few intelligent guesses...
NTSTATUS Status;
PMDL Mdl;
PEPROCESS Process;
DPRINT("NtUnlockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
"NumberOfBytesToUnlock %d), NumberOfBytesUnlocked %x\n",ProcessHandle,BaseAddress,
NumberOfBytesToUnlock, NumberOfBytesUnlocked);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
if (Status != STATUS_SUCCESS)
{
return(Status);
}
Mdl = MmCreateMdl(NULL,
BaseAddress,
NumberOfBytesToUnlock);
ObDereferenceObject(Process);
if (Mdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
MmUnlockPages(Mdl);
ExFreePool(Mdl);
*NumberOfBytesUnlocked = NumberOfBytesToUnlock;
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
NtWriteVirtualMemory(IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN PVOID Buffer,
IN ULONG NumberOfBytesToWrite,
OUT PULONG NumberOfBytesWritten)
NTSTATUS STDCALL
NtReadVirtualMemory(IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
OUT PVOID Buffer,
IN ULONG NumberOfBytesToRead,
OUT PULONG NumberOfBytesRead)
{
NTSTATUS Status;
PMDL Mdl;
PVOID SystemAddress;
PEPROCESS Process;
DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
"Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress,
Buffer,NumberOfBytesToWrite);
DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
"Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
Buffer,NumberOfBytesToRead);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
PROCESS_VM_WRITE,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
if (Status != STATUS_SUCCESS)
{
return(Status);
}
Mdl = MmCreateMdl(NULL,
Buffer,
NumberOfBytesToWrite);
{
return(Status);
}
Mdl = MmCreateMdl(NULL,
Buffer,
NumberOfBytesToRead);
MmProbeAndLockPages(Mdl,
UserMode,
IoReadAccess);
UserMode,
IoWriteAccess);
KeAttachProcess(Process);
SystemAddress = MmGetSystemAddressForMdl(Mdl);
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
KeDetachProcess();
if (Mdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
MmUnlockPages(Mdl);
ExFreePool(Mdl);
ObDereferenceObject(Process);
*NumberOfBytesRead = NumberOfBytesToRead;
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
NtUnlockVirtualMemory(HANDLE ProcessHandle,
PVOID BaseAddress,
ULONG NumberOfBytesToUnlock,
PULONG NumberOfBytesUnlocked OPTIONAL)
{
// AG [08-20-03] : I have *no* idea if this is correct, I just used the
// other functions as a template and made a few intelligent guesses...
NTSTATUS Status;
PMDL Mdl;
PEPROCESS Process;
DPRINT("NtUnlockVirtualMemory(ProcessHandle %x, BaseAddress %x, "
"NumberOfBytesToUnlock %d), NumberOfBytesUnlocked %x\n",ProcessHandle,BaseAddress,
NumberOfBytesToUnlock, NumberOfBytesUnlocked);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
if (Status != STATUS_SUCCESS)
{
return(Status);
}
Mdl = MmCreateMdl(NULL,
BaseAddress,
NumberOfBytesToUnlock);
ObDereferenceObject(Process);
if (Mdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
MmUnlockPages(Mdl);
ExFreePool(Mdl);
*NumberOfBytesUnlocked = NumberOfBytesToUnlock;
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
NtWriteVirtualMemory(IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN PVOID Buffer,
IN ULONG NumberOfBytesToWrite,
OUT PULONG NumberOfBytesWritten)
{
NTSTATUS Status;
PMDL Mdl;
PVOID SystemAddress;
PEPROCESS Process;
DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, "
"Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress,
Buffer,NumberOfBytesToWrite);
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_VM_WRITE,
NULL,
UserMode,
(PVOID*)(&Process),
NULL);
if (Status != STATUS_SUCCESS)
{
return(Status);
}
Mdl = MmCreateMdl(NULL,
Buffer,
NumberOfBytesToWrite);
MmProbeAndLockPages(Mdl,
UserMode,
IoReadAccess);
KeAttachProcess(Process);
SystemAddress = MmGetSystemAddressForMdl(Mdl);
memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite);
KeDetachProcess();
ObDereferenceObject(Process);
if (Mdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
MmUnlockPages(Mdl);
ExFreePool(Mdl);
*NumberOfBytesWritten = NumberOfBytesToWrite;
return(STATUS_SUCCESS);
}
@@ -424,15 +424,15 @@ MmSecureVirtualMemory (PVOID Address,
SIZE_T Length,
ULONG Mode)
{
/* Only works for user space */
if (MmHighestUserAddress < Address)
{
/* Only works for user space */
if (MmHighestUserAddress < Address)
{
return NULL;
}
}
UNIMPLEMENTED;
UNIMPLEMENTED;
return 0;
return 0;
}
@@ -442,12 +442,12 @@ MmSecureVirtualMemory (PVOID Address,
VOID STDCALL
MmUnsecureVirtualMemory(PVOID SecureMem)
{
if (NULL == SecureMem)
{
if (NULL == SecureMem)
{
return;
}
}
UNIMPLEMENTED;
UNIMPLEMENTED;
}
@@ -456,23 +456,23 @@ MmUnsecureVirtualMemory(PVOID SecureMem)
*/
VOID STDCALL
ProbeForRead (IN PVOID Address,
IN ULONG Length,
IN ULONG Alignment)
IN ULONG Length,
IN ULONG Alignment)
{
assert (Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
assert (Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
if (Length == 0)
return;
if (Length == 0)
return;
if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
{
if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
{
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
}
else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address ||
(ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress)
{
}
else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address ||
(ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress)
{
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
}
}
}
@@ -481,35 +481,35 @@ ProbeForRead (IN PVOID Address,
*/
VOID STDCALL
ProbeForWrite (IN PVOID Address,
IN ULONG Length,
IN ULONG Alignment)
IN ULONG Length,
IN ULONG Alignment)
{
PULONG Ptr;
ULONG x;
ULONG i;
PULONG Ptr;
ULONG x;
ULONG i;
assert (Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
assert (Alignment ==1 || Alignment == 2 || Alignment == 4 || Alignment == 8);
if (Length == 0)
return;
if (Length == 0)
return;
if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
{
if (((ULONG_PTR)Address & (Alignment - 1)) != 0)
{
ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
}
else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address ||
(ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress)
{
}
else if ((ULONG_PTR)Address + Length < (ULONG_PTR)Address ||
(ULONG_PTR)Address + Length > (ULONG_PTR)MmUserProbeAddress)
{
ExRaiseStatus (STATUS_ACCESS_VIOLATION);
}
}
/* Check for accessible pages */
for (i = 0; i < Length; i += PAGE_SIZE)
{
/* Check for accessible pages */
for (i = 0; i < Length; i += PAGE_SIZE)
{
Ptr = (PULONG)(((ULONG_PTR)Address & ~(PAGE_SIZE - 1)) + i);
x = *Ptr;
*Ptr = x;
}
}
}
/* EOF */
+18 -18
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: wset.c,v 1.17 2003/07/12 01:52:10 dwelch Exp $
/* $Id: wset.c,v 1.18 2004/04/10 22:35:26 gdalsnes Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/wset.c
@@ -41,30 +41,30 @@
NTSTATUS
MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
{
PHYSICAL_ADDRESS CurrentPhysicalAddress;
PHYSICAL_ADDRESS NextPhysicalAddress;
NTSTATUS Status;
PHYSICAL_ADDRESS CurrentPhysicalAddress;
PHYSICAL_ADDRESS NextPhysicalAddress;
NTSTATUS Status;
(*NrFreedPages) = 0;
(*NrFreedPages) = 0;
CurrentPhysicalAddress = MmGetLRUFirstUserPage();
while (CurrentPhysicalAddress.QuadPart != 0 && Target > 0)
{
CurrentPhysicalAddress = MmGetLRUFirstUserPage();
while (CurrentPhysicalAddress.QuadPart != 0 && Target > 0)
{
NextPhysicalAddress = MmGetLRUNextUserPage(CurrentPhysicalAddress);
Status = MmPageOutPhysicalAddress(CurrentPhysicalAddress);
if (NT_SUCCESS(Status))
{
DPRINT("Succeeded\n");
Target--;
(*NrFreedPages)++;
}
{
DPRINT("Succeeded\n");
Target--;
(*NrFreedPages)++;
}
else if (Status == STATUS_PAGEFILE_QUOTA)
{
MmSetLRULastPage(CurrentPhysicalAddress);
}
{
MmSetLRULastPage(CurrentPhysicalAddress);
}
CurrentPhysicalAddress = NextPhysicalAddress;
}
return(STATUS_SUCCESS);
}
return(STATUS_SUCCESS);
}