diff --git a/reactos/ntoskrnl/cc/view.c b/reactos/ntoskrnl/cc/view.c index 43279a7e999..86fb01b2532 100644 --- a/reactos/ntoskrnl/cc/view.c +++ b/reactos/ntoskrnl/cc/view.c @@ -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: view.c,v 1.79 2004/10/22 20:11:12 ekohl Exp $ +/* $Id$ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/cc/view.c @@ -813,8 +813,7 @@ CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg) #else MmLockAddressSpace(MmGetKernelAddressSpace()); MmFreeMemoryArea(MmGetKernelAddressSpace(), - CacheSeg->BaseAddress, - CacheSeg->Bcb->CacheSegmentSize, + CacheSeg->MemoryArea, CcFreeCachePage, NULL); MmUnlockAddressSpace(MmGetKernelAddressSpace()); diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index ab641913912..71335a6838c 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -184,15 +184,17 @@ typedef struct _PAGEFAULT_HISTORY #endif /* __USE_W32API */ -typedef struct +typedef struct _MEMORY_AREA { + PVOID StartingAddress; + PVOID EndingAddress; + struct _MEMORY_AREA *Parent; + struct _MEMORY_AREA *LeftChild; + struct _MEMORY_AREA *RightChild; ULONG Type; - PVOID BaseAddress; - ULONG Length; ULONG Attributes; - LIST_ENTRY Entry; ULONG LockCount; - struct _EPROCESS* Process; + struct _EPROCESS* Process; /* FIXME: We don't need this! */ BOOLEAN DeleteInProgress; ULONG PageOpCount; union @@ -215,7 +217,7 @@ typedef struct typedef struct _MADDRESS_SPACE { - LIST_ENTRY MAreaListHead; + PMEMORY_AREA MemoryAreaRoot; FAST_MUTEX Lock; PVOID LowestAddress; struct _EPROCESS* Process; @@ -333,6 +335,10 @@ typedef struct _MM_REGION LIST_ENTRY RegionListEntry; } MM_REGION, *PMM_REGION; +typedef VOID (*PMM_FREE_PAGE_FUNC)(PVOID Context, PMEMORY_AREA MemoryArea, + PVOID Address, PFN_TYPE Page, + SWAPENTRY SwapEntry, BOOLEAN Dirty); + /* FUNCTIONS */ /* aspace.c ******************************************************************/ @@ -354,48 +360,67 @@ NTSTATUS MmDestroyAddressSpace(PMADDRESS_SPACE AddressSpace); /* marea.c *******************************************************************/ -NTSTATUS MmCreateMemoryArea(struct _EPROCESS* Process, - PMADDRESS_SPACE AddressSpace, - ULONG Type, - PVOID* BaseAddress, - ULONG Length, - ULONG Attributes, - MEMORY_AREA** Result, - BOOL FixedAddress, - BOOL TopDown, - PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL); +NTSTATUS INIT_FUNCTION +MmInitMemoryAreas(VOID); -MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace, - PVOID Address); +NTSTATUS STDCALL +MmCreateMemoryArea( + struct _EPROCESS* Process, + PMADDRESS_SPACE AddressSpace, + ULONG Type, + PVOID *BaseAddress, + ULONG_PTR Length, + ULONG Attributes, + PMEMORY_AREA *Result, + BOOLEAN FixedAddress, + BOOLEAN TopDown, + PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL); -ULONG MmFindGapAtAddress(PMADDRESS_SPACE AddressSpace, - PVOID Address); +PMEMORY_AREA STDCALL +MmOpenMemoryAreaByAddress( + PMADDRESS_SPACE AddressSpace, + PVOID Address); -NTSTATUS MmInitMemoryAreas(VOID); +ULONG STDCALL +MmFindGapAtAddress( + PMADDRESS_SPACE AddressSpace, + PVOID Address); -NTSTATUS MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace, - PVOID BaseAddress, - ULONG Length, - VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, - PVOID Address, PFN_TYPE Page, SWAPENTRY SwapEntry, - BOOLEAN Dirty), - PVOID FreePageContext); +NTSTATUS STDCALL +MmFreeMemoryArea( + PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_FREE_PAGE_FUNC FreePage, + PVOID FreePageContext); -VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead); +NTSTATUS STDCALL +MmFreeMemoryAreaByPtr( + PMADDRESS_SPACE AddressSpace, + PVOID BaseAddress, + PMM_FREE_PAGE_FUNC FreePage, + PVOID FreePageContext); -NTSTATUS MmLockMemoryArea(MEMORY_AREA* MemoryArea); +VOID STDCALL +MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace); -NTSTATUS MmUnlockMemoryArea(MEMORY_AREA* MemoryArea); +PMEMORY_AREA STDCALL +MmOpenMemoryAreaByRegion( + PMADDRESS_SPACE AddressSpace, + PVOID Address, + ULONG_PTR Length); -MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace, - PVOID Address, - ULONG Length); +PVOID STDCALL +MmFindGap( + PMADDRESS_SPACE AddressSpace, + ULONG_PTR Length, + ULONG_PTR Granularity, + BOOLEAN TopDown); -PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity, BOOL TopDown); - -void MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process, - PMADDRESS_SPACE AddressSpace, - PVOID BaseAddress); +VOID STDCALL +MmReleaseMemoryAreaIfDecommitted( + PEPROCESS Process, + PMADDRESS_SPACE AddressSpace, + PVOID BaseAddress); /* npool.c *******************************************************************/ diff --git a/reactos/ntoskrnl/ke/bug.c b/reactos/ntoskrnl/ke/bug.c index 259e6dc6463..2e8df660bb8 100644 --- a/reactos/ntoskrnl/ke/bug.c +++ b/reactos/ntoskrnl/ke/bug.c @@ -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: bug.c,v 1.48 2004/12/12 17:42:00 hbirr Exp $ +/* $Id$ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/bug.c @@ -116,6 +116,11 @@ KeBugCheckWithTf(ULONG BugCheckCode, Ke386DisableInterrupts(); DebugLogDumpMessages(); + if (MmGetKernelAddressSpace()->Lock.Owner == KeGetCurrentThread()) + { + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + } + if (KeGetCurrentIrql() < DISPATCH_LEVEL) { KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index ac21c66d98b..e1105f5e3ea 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -320,7 +320,7 @@ KiDoubleFaultHandler(VOID) { KeRosPrintAddress((PVOID)Frame[1]); Frame = (PULONG)Frame[0]; - DbgPrint(" "); + DbgPrint("\n"); } #else DbgPrint("Frames: "); @@ -663,7 +663,7 @@ KeDumpStackFrames(PULONG Frame) break; StackBase = Frame; Frame = (PULONG)Frame[0]; - DbgPrint(" "); + DbgPrint("\n"); } } _SEH_HANDLE diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index b74fc265b51..8651c5e5aaf 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -90,11 +90,10 @@ KeReleaseThread(PKTHREAD Thread) if (Thread->StackLimit != (ULONG_PTR)&init_stack) { MmLockAddressSpace(MmGetKernelAddressSpace()); - MmFreeMemoryArea(MmGetKernelAddressSpace(), - (PVOID)Thread->StackLimit, - MM_STACK_SIZE, - KeFreeStackPage, - NULL); + MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(), + (PVOID)Thread->StackLimit, + KeFreeStackPage, + NULL); MmUnlockAddressSpace(MmGetKernelAddressSpace()); } Thread->StackLimit = 0; diff --git a/reactos/ntoskrnl/mm/anonmem.c b/reactos/ntoskrnl/mm/anonmem.c index 8809a4e569d..c0924094f07 100644 --- a/reactos/ntoskrnl/mm/anonmem.c +++ b/reactos/ntoskrnl/mm/anonmem.c @@ -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: anonmem.c,v 1.34 2004/12/19 16:16:57 navaraf Exp $ +/* $Id$ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/anonmem.c @@ -261,7 +261,7 @@ MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace, /* * Get the segment corresponding to the virtual address */ - Region = MmFindRegion(MemoryArea->BaseAddress, + Region = MmFindRegion(MemoryArea->StartingAddress, &MemoryArea->Data.VirtualMemoryData.RegionListHead, Address, NULL); if (Region->Type == MEM_RESERVE || Region->Protect == PAGE_NOACCESS) @@ -525,6 +525,7 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle, { PEPROCESS Process; MEMORY_AREA* MemoryArea; + ULONG_PTR MemoryAreaLength; ULONG Type; NTSTATUS Status; PMADDRESS_SPACE AddressSpace; @@ -582,39 +583,43 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle, MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress); - if (MemoryArea != NULL && - MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY && - MemoryArea->Length >= RegionSize) + if (MemoryArea != NULL) { - Status = - MmAlterRegion(AddressSpace, - MemoryArea->BaseAddress, - &MemoryArea->Data.VirtualMemoryData.RegionListHead, - BaseAddress, RegionSize, - Type, Protect, MmModifyAttributes); - MmUnlockAddressSpace(AddressSpace); - ObDereferenceObject(Process); - DPRINT("NtAllocateVirtualMemory() = %x\n",Status); - return(Status); - } - else if (MemoryArea != NULL && MemoryArea->Length >= RegionSize) - { - Status = - MmAlterRegion(AddressSpace, - MemoryArea->BaseAddress, - &MemoryArea->Data.SectionData.RegionListHead, - BaseAddress, RegionSize, - Type, Protect, MmModifyAttributes); - MmUnlockAddressSpace(AddressSpace); - ObDereferenceObject(Process); - DPRINT("NtAllocateVirtualMemory() = %x\n",Status); - return(Status); - } - else if (MemoryArea != NULL) - { - MmUnlockAddressSpace(AddressSpace); - ObDereferenceObject(Process); - return(STATUS_UNSUCCESSFUL); + MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress - + (ULONG_PTR)MemoryArea->StartingAddress; + if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY && + MemoryAreaLength >= RegionSize) + { + Status = + MmAlterRegion(AddressSpace, + MemoryArea->StartingAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + BaseAddress, RegionSize, + Type, Protect, MmModifyAttributes); + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + DPRINT("NtAllocateVirtualMemory() = %x\n",Status); + return(Status); + } + else if (MemoryAreaLength >= RegionSize) + { + Status = + MmAlterRegion(AddressSpace, + MemoryArea->StartingAddress, + &MemoryArea->Data.SectionData.RegionListHead, + BaseAddress, RegionSize, + Type, Protect, MmModifyAttributes); + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + DPRINT("NtAllocateVirtualMemory() = %x\n",Status); + return(Status); + } + else + { + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); + } } } @@ -626,7 +631,7 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle, Protect, &MemoryArea, PBaseAddress != 0, - (AllocationType & MEM_TOP_DOWN), + (AllocationType & MEM_TOP_DOWN) == MEM_TOP_DOWN, BoundaryAddressMultiple); if (!NT_SUCCESS(Status)) { @@ -635,18 +640,22 @@ NtAllocateVirtualMemory(IN HANDLE ProcessHandle, DPRINT("NtAllocateVirtualMemory() = %x\n",Status); return(Status); } + + MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress - + (ULONG_PTR)MemoryArea->StartingAddress; + MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead, - MemoryArea->Length, Type, Protect); + MemoryAreaLength, Type, Protect); if ((AllocationType & MEM_COMMIT) && ((Protect & PAGE_READWRITE) || (Protect & PAGE_EXECUTE_READWRITE))) { - MmReserveSwapPages(MemoryArea->Length); + MmReserveSwapPages(MemoryAreaLength); } *UBaseAddress = BaseAddress; - *URegionSize = MemoryArea->Length; + *URegionSize = MemoryAreaLength; DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress, RegionSize); MmUnlockAddressSpace(AddressSpace); @@ -702,7 +711,11 @@ MmFreeVirtualMemory(PEPROCESS Process, */ if (MemoryArea->PageOpCount > 0) { - for (i = 0; i < PAGE_ROUND_UP(MemoryArea->Length) / PAGE_SIZE; i++) + ULONG_PTR MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress - + (ULONG_PTR)MemoryArea->StartingAddress; + + /* FiN TODO: Optimize loop counter! */ + for (i = 0; i < PAGE_ROUND_UP(MemoryAreaLength) / PAGE_SIZE; i++) { PMM_PAGEOP PageOp; @@ -712,7 +725,7 @@ MmFreeVirtualMemory(PEPROCESS Process, } PageOp = MmCheckForPageOp(MemoryArea, Process->UniqueProcessId, - (char*)MemoryArea->BaseAddress + (i * PAGE_SIZE), + (PVOID)((ULONG_PTR)MemoryArea->StartingAddress + (i * PAGE_SIZE)), NULL, 0); if (PageOp != NULL) { @@ -745,8 +758,7 @@ MmFreeVirtualMemory(PEPROCESS Process, /* Actually free the memory area. */ MmFreeMemoryArea(&Process->AddressSpace, - MemoryArea->BaseAddress, - 0, + MemoryArea, MmFreeVirtualMemoryPage, (PVOID)Process); } @@ -814,7 +826,7 @@ NtFreeVirtualMemory(IN HANDLE ProcessHandle, { case MEM_RELEASE: /* We can only free a memory area in one step. */ - if (MemoryArea->BaseAddress != BaseAddress || + if (MemoryArea->StartingAddress != BaseAddress || MemoryArea->Type != MEMORY_AREA_VIRTUAL_MEMORY) { MmUnlockAddressSpace(AddressSpace); @@ -829,7 +841,7 @@ NtFreeVirtualMemory(IN HANDLE ProcessHandle, case MEM_DECOMMIT: Status = MmAlterRegion(AddressSpace, - MemoryArea->BaseAddress, + MemoryArea->StartingAddress, &MemoryArea->Data.VirtualMemoryData.RegionListHead, BaseAddress, RegionSize, @@ -856,11 +868,11 @@ MmProtectAnonMem(PMADDRESS_SPACE AddressSpace, PMM_REGION Region; NTSTATUS Status; - Region = MmFindRegion(MemoryArea->BaseAddress, + Region = MmFindRegion(MemoryArea->StartingAddress, &MemoryArea->Data.VirtualMemoryData.RegionListHead, BaseAddress, NULL); *OldProtect = Region->Protect; - Status = MmAlterRegion(AddressSpace, MemoryArea->BaseAddress, + Status = MmAlterRegion(AddressSpace, MemoryArea->StartingAddress, &MemoryArea->Data.VirtualMemoryData.RegionListHead, BaseAddress, Length, Region->Type, Protect, MmModifyAttributes); @@ -878,11 +890,11 @@ MmQueryAnonMem(PMEMORY_AREA MemoryArea, Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address); - Region = MmFindRegion(MemoryArea->BaseAddress, + Region = MmFindRegion(MemoryArea->StartingAddress, &MemoryArea->Data.VirtualMemoryData.RegionListHead, Address, &RegionBase); Info->BaseAddress = RegionBase; - Info->AllocationBase = MemoryArea->BaseAddress; + Info->AllocationBase = MemoryArea->StartingAddress; Info->AllocationProtect = MemoryArea->Attributes; Info->RegionSize = (char*)RegionBase + Region->Length - (char*)Info->BaseAddress; Info->State = Region->Type; diff --git a/reactos/ntoskrnl/mm/aspace.c b/reactos/ntoskrnl/mm/aspace.c index 8296857f5cb..f7ee69a4c42 100644 --- a/reactos/ntoskrnl/mm/aspace.c +++ b/reactos/ntoskrnl/mm/aspace.c @@ -68,7 +68,7 @@ NTSTATUS MmInitializeAddressSpace(PEPROCESS Process, PMADDRESS_SPACE AddressSpace) { - InitializeListHead(&AddressSpace->MAreaListHead); + AddressSpace->MemoryAreaRoot = NULL; ExInitializeFastMutex(&AddressSpace->Lock); if (Process != NULL) { diff --git a/reactos/ntoskrnl/mm/cont.c b/reactos/ntoskrnl/mm/cont.c index b1ec2fe57b9..324cca6d44b 100644 --- a/reactos/ntoskrnl/mm/cont.c +++ b/reactos/ntoskrnl/mm/cont.c @@ -1,4 +1,4 @@ -/* $Id: cont.c,v 1.35 2004/10/22 20:38:22 ekohl Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -42,7 +42,7 @@ MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes, { PMEMORY_AREA MArea; NTSTATUS Status; - PVOID BaseAddress = 0; + PVOID BaseAddress = NULL; PFN_TYPE PBase; ULONG Attributes; ULONG i; @@ -83,8 +83,7 @@ MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes, { MmLockAddressSpace(MmGetKernelAddressSpace()); MmFreeMemoryArea(MmGetKernelAddressSpace(), - BaseAddress, - 0, + MArea, NULL, NULL); MmUnlockAddressSpace(MmGetKernelAddressSpace()); @@ -174,11 +173,10 @@ VOID STDCALL MmFreeContiguousMemory(IN PVOID BaseAddress) { MmLockAddressSpace(MmGetKernelAddressSpace()); - MmFreeMemoryArea(MmGetKernelAddressSpace(), - BaseAddress, - 0, - MmFreeContinuousPage, - NULL); + MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(), + BaseAddress, + MmFreeContinuousPage, + NULL); MmUnlockAddressSpace(MmGetKernelAddressSpace()); } @@ -260,11 +258,10 @@ MmFreeContiguousMemorySpecifyCache(IN PVOID BaseAddress, IN MEMORY_CACHING_TYPE CacheType) { MmLockAddressSpace(MmGetKernelAddressSpace()); - MmFreeMemoryArea(MmGetKernelAddressSpace(), - BaseAddress, - NumberOfBytes, - MmFreeContinuousPage, - NULL); + MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(), + BaseAddress, + MmFreeContinuousPage, + NULL); MmUnlockAddressSpace(MmGetKernelAddressSpace()); } diff --git a/reactos/ntoskrnl/mm/drvlck.c b/reactos/ntoskrnl/mm/drvlck.c index b5aa396797f..c2a70708fc7 100644 --- a/reactos/ntoskrnl/mm/drvlck.c +++ b/reactos/ntoskrnl/mm/drvlck.c @@ -1,4 +1,4 @@ -/* $Id: drvlck.c,v 1.6 2004/08/15 16:39:06 chorns Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -64,7 +64,7 @@ PVOID STDCALL MmLockPagableDataSection(IN PVOID AddressWithinSection) { PVOID Handle; - Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection); + Handle = MmOpenMemoryAreaByAddress(NULL, AddressWithinSection); MmLockPagableSectionByHandle(Handle); return(Handle); } diff --git a/reactos/ntoskrnl/mm/iospace.c b/reactos/ntoskrnl/mm/iospace.c index e76f6a23db6..3cbd4333d15 100644 --- a/reactos/ntoskrnl/mm/iospace.c +++ b/reactos/ntoskrnl/mm/iospace.c @@ -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.30 2004/08/15 16:39:07 chorns Exp $ +/* $Id$ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/iospace.c @@ -127,7 +127,7 @@ MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress, KEBUGCHECK(0); } } - return ((PVOID)((char*)Result + Offset)); + return (PVOID)((ULONG_PTR)Result + Offset); } @@ -160,16 +160,17 @@ MmUnmapIoSpace (IN PVOID BaseAddress, IN ULONG NumberOfBytes) { ULONG Offset; - Offset = (ULONG_PTR)BaseAddress % PAGE_SIZE; - BaseAddress = (PVOID)((PUCHAR)BaseAddress - Offset); + PVOID Address = BaseAddress; + + Offset = (ULONG_PTR)Address % PAGE_SIZE; + Address -= Offset; NumberOfBytes += Offset; MmLockAddressSpace(MmGetKernelAddressSpace()); - MmFreeMemoryArea(MmGetKernelAddressSpace(), - BaseAddress, - NumberOfBytes, - NULL, - NULL); + MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(), + Address, + NULL, + NULL); MmUnlockAddressSpace(MmGetKernelAddressSpace()); } diff --git a/reactos/ntoskrnl/mm/marea.c b/reactos/ntoskrnl/mm/marea.c index 41ab4bc38cd..3e48cf3e8eb 100644 --- a/reactos/ntoskrnl/mm/marea.c +++ b/reactos/ntoskrnl/mm/marea.c @@ -35,331 +35,590 @@ #define TAG_MAREA TAG('M', 'A', 'R', 'E') +/* #define VALIDATE_MEMORY_AREAS */ + /* FUNCTIONS *****************************************************************/ -VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead) +/** + * @name MmIterateFirstNode + * + * @param Node + * Head node of the MEMORY_AREA tree. + * + * @return The leftmost MEMORY_AREA node (ie. the one with lowest + * address) + */ + +static PMEMORY_AREA MmIterateFirstNode(PMEMORY_AREA Node) { - PLIST_ENTRY current_entry; - MEMORY_AREA* current; + while (Node->LeftChild != NULL) + Node = Node->LeftChild; + + return Node; +} + +/** + * @name MmIterateNextNode + * + * @param Node + * Current node in the tree. + * + * @return Next node in the tree (sorted by address). + */ + +static PMEMORY_AREA MmIterateNextNode(PMEMORY_AREA Node) +{ + if (Node->RightChild != NULL) + { + Node = Node->RightChild; + while (Node->LeftChild != NULL) + Node = Node->LeftChild; + } + else + { + PMEMORY_AREA TempNode = NULL; + + do + { + /* Check if we're at the end of tree. */ + if (Node->Parent == NULL) + return NULL; + + TempNode = Node; + Node = Node->Parent; + } + while (TempNode == Node->RightChild); + } + return Node; +} + +/** + * @name MmIterateFirstNode + * + * @param Node + * Head node of the MEMORY_AREA tree. + * + * @return The rightmost MEMORY_AREA node (ie. the one with highest + * address) + */ + +static PMEMORY_AREA MmIterateLastNode(PMEMORY_AREA Node) +{ + while (Node->RightChild != NULL) + Node = Node->RightChild; + + return Node; +} + +/** + * @name MmIterateNextNode + * + * @param Node + * Current node in the tree. + * + * @return Previous node in the tree (sorted by address). + */ + +static PMEMORY_AREA MmIteratePrevNode(PMEMORY_AREA Node) +{ + if (Node->LeftChild != NULL) + { + Node = Node->LeftChild; + while (Node->RightChild != NULL) + Node = Node->RightChild; + } + else + { + PMEMORY_AREA TempNode = NULL; + + do + { + /* Check if we're at the end of tree. */ + if (Node->Parent == NULL) + return NULL; + + TempNode = Node; + Node = Node->Parent; + } + while (TempNode == Node->LeftChild); + } + return Node; +} + +#ifdef VALIDATE_MEMORY_AREAS +static VOID MmVerifyMemoryAreas(PMADDRESS_SPACE AddressSpace) +{ + PMEMORY_AREA Node; + + ASSERT(AddressSpace != NULL); + + /* Special case for empty tree. */ + if (AddressSpace->MemoryAreaRoot == NULL) + return; + + /* Traverse the tree from left to right. */ + for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot); + Node != NULL; + Node = MmIterateNextNode(Node)) + { + /* FiN: The starting address can be NULL if someone explicitely asks + * for NULL address. */ + ASSERT(Node->StartingAddress >= AddressSpace->LowestAddress || + Node->StartingAddress == NULL); + ASSERT(Node->EndingAddress >= Node->StartingAddress); + } +} +#else +#define MmVerifyMemoryAreas(x) +#endif + +VOID STDCALL +MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace) +{ + PMEMORY_AREA Node; DbgPrint("MmDumpMemoryAreas()\n"); + + /* Special case for empty tree. */ + if (AddressSpace->MemoryAreaRoot == NULL) + return; - current_entry = ListHead->Flink; - while (current_entry!=ListHead) + /* Traverse the tree from left to right. */ + for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot); + Node != NULL; + Node = MmIterateNextNode(Node)) { - 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("Start %x End %x Attributes %x\n", + Node->StartingAddress, Node->EndingAddress, + Node->Attributes); } + DbgPrint("Finished MmDumpMemoryAreas()\n"); } -MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace, - PVOID Address) +PMEMORY_AREA STDCALL +MmOpenMemoryAreaByAddress( + PMADDRESS_SPACE AddressSpace, + PVOID Address) { - PLIST_ENTRY current_entry; - MEMORY_AREA* current; - PLIST_ENTRY previous_entry; + PMEMORY_AREA Node = AddressSpace->MemoryAreaRoot; 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) + if (!(KdDebugState & KD_DEBUG_SCREEN)) + MmVerifyMemoryAreas(AddressSpace); + + while (Node != NULL) { - 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) + if (Address < Node->StartingAddress) + Node = Node->LeftChild; + else if (Address >= Node->EndingAddress) + Node = Node->RightChild; + else { - DPRINT("%s() = %x\n",__FUNCTION__,current); - return(current); + DPRINT("MmOpenMemoryAreaByAddress(%x): %x [%x - %x]\n", + Address, Node, Node->StartingAddress, Node->EndingAddress); + return Node; } - 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); + + DPRINT("MmOpenMemoryAreaByAddress(%x): 0\n", Address); + return NULL; } -MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace, - PVOID Address, - ULONG Length) +PMEMORY_AREA STDCALL +MmOpenMemoryAreaByRegion( + PMADDRESS_SPACE AddressSpace, + PVOID Address, + ULONG_PTR Length) { - PLIST_ENTRY current_entry; - MEMORY_AREA* current; - ULONG Extent; + PMEMORY_AREA Node; + PVOID Extent = (PVOID)((ULONG_PTR)Address + Length); - DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n", - AddressSpace, Address, Length); + MmVerifyMemoryAreas(AddressSpace); - current_entry = AddressSpace->MAreaListHead.Flink; - while (current_entry != &AddressSpace->MAreaListHead) + /* Special case for empty tree. */ + if (AddressSpace->MemoryAreaRoot == NULL) + return NULL; + + /* Traverse the tree from left to right. */ + for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot); + Node != NULL; + Node = MmIterateNextNode(Node)) { - 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)) + if (Node->StartingAddress >= Address && + Node->StartingAddress < Extent) { - DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n", - current); - return(current); + DPRINT("MmOpenMemoryAreaByRegion(%x - %x): %x - %x\n", + Address, Address + Length, Node->StartingAddress, + Node->EndingAddress); + return Node; } - Extent = (ULONG)current->BaseAddress + current->Length; - if (Extent > (ULONG)Address && - Extent < (ULONG)((char*)Address+Length)) + if (Node->EndingAddress > Address && + Node->EndingAddress < Extent) { - DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n", - current); - return(current); + DPRINT("MmOpenMemoryAreaByRegion(%x - %x): %x - %x\n", + Address, Address + Length, Node->StartingAddress, + Node->EndingAddress); + return Node; } - if (current->BaseAddress <= Address && - Extent >= (ULONG)((char*)Address+Length)) + if (Node->StartingAddress <= Address && + Node->EndingAddress >= Extent) { - DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n", - current); - return(current); + DPRINT("MmOpenMemoryAreaByRegion(%x - %x): %x - %x\n", + Address, Address + Length, Node->StartingAddress, + Node->EndingAddress); + return Node; } - if (current->BaseAddress >= (PVOID)((char*)Address+Length)) + if (Node->StartingAddress >= Extent) { - DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0); - return(NULL); + DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n"); + return NULL; } - current_entry = current_entry->Flink; } - DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0); - return(NULL); + + return NULL; } -static VOID MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace, - MEMORY_AREA* marea) +/* + * @name MmCompressHelper + * + * This is helper of MmRebalanceTree. Performs a compression transformation + * count times, starting at root. + */ + +static VOID +MmCompressHelper( + PMADDRESS_SPACE AddressSpace, + ULONG Count) { - PLIST_ENTRY ListHead; - PLIST_ENTRY current_entry; - PLIST_ENTRY inserted_entry = &marea->Entry; - MEMORY_AREA* current; - MEMORY_AREA* next; + PMEMORY_AREA Root = NULL; + PMEMORY_AREA Red = AddressSpace->MemoryAreaRoot; + PMEMORY_AREA Black = Red->LeftChild; - 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)) + while (Count--) { - InsertHeadList(ListHead,&marea->Entry); + if (Root) + Root->LeftChild = Black; + else + AddressSpace->MemoryAreaRoot = Black; + Black->Parent = Root; + Red->LeftChild = Black->RightChild; + if (Black->RightChild) + Black->RightChild->Parent = Red; + Black->RightChild = Red; + Red->Parent = Black; + Root = Black; + + if (Count) + { + Red = Root->LeftChild; + Black = Red->LeftChild; + } + } +} + +/* + * @name MmRebalanceTree + * + * Rebalance a memory area tree using the Tree->Vine->Balanced Tree + * method described in libavl documentation in chapter 4.12. + * (http://www.stanford.edu/~blp/avl/libavl.html/) + */ + +static VOID +MmRebalanceTree( + PMADDRESS_SPACE AddressSpace) +{ + PMEMORY_AREA PreviousNode; + PMEMORY_AREA CurrentNode; + PMEMORY_AREA TempNode; + ULONG NodeCount = 0; + ULONG Vine; /* Number of nodes in main vine. */ + ULONG Leaves; /* Nodes in incomplete bottom level, if any. */ + INT Height; /* Height of produced balanced tree. */ + + /* Transform the tree into Vine. */ + + PreviousNode = NULL; + CurrentNode = AddressSpace->MemoryAreaRoot; + while (CurrentNode != NULL) + { + if (CurrentNode->RightChild == NULL) + { + PreviousNode = CurrentNode; + CurrentNode = CurrentNode->LeftChild; + NodeCount++; + } + else + { + TempNode = CurrentNode->RightChild; + + CurrentNode->RightChild = TempNode->LeftChild; + if (TempNode->LeftChild) + TempNode->LeftChild->Parent = CurrentNode; + + TempNode->LeftChild = CurrentNode; + CurrentNode->Parent = TempNode; + + CurrentNode = TempNode; + + if (PreviousNode != NULL) + PreviousNode->LeftChild = TempNode; + else + AddressSpace->MemoryAreaRoot = TempNode; + TempNode->Parent = PreviousNode; + } + } + + /* Transform Vine back into a balanced tree. */ + + Leaves = NodeCount + 1; + for (;;) + { + ULONG Next = Leaves & (Leaves - 1); + if (Next == 0) + break; + Leaves = Next; + } + Leaves = NodeCount + 1 - Leaves; + + MmCompressHelper(AddressSpace, Leaves); + + Vine = NodeCount - Leaves; + Height = 1 + (Leaves > 0); + while (Vine > 1) + { + MmCompressHelper(AddressSpace, Vine / 2); + Vine /= 2; + Height++; + } +} + +static VOID +MmInsertMemoryArea( + PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA marea) +{ + PMEMORY_AREA Node; + PMEMORY_AREA PreviousNode; + ULONG Depth = 0; + + MmVerifyMemoryAreas(AddressSpace); + + if (AddressSpace->MemoryAreaRoot == NULL) + { + AddressSpace->MemoryAreaRoot = marea; + marea->LeftChild = marea->RightChild = marea->Parent = NULL; return; } - current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry); - if (current->BaseAddress > marea->BaseAddress) + + Node = AddressSpace->MemoryAreaRoot; + do { - 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) + DPRINT("marea->EndingAddress: %x Node->StartingAddress: %x\n", + marea->EndingAddress, Node->StartingAddress); + DPRINT("marea->StartingAddress: %x Node->EndingAddress: %x\n", + marea->StartingAddress, Node->EndingAddress); + ASSERT(marea->EndingAddress <= Node->StartingAddress || + marea->StartingAddress >= Node->EndingAddress); + ASSERT(marea->StartingAddress != Node->StartingAddress); + + PreviousNode = Node; + + if (marea->StartingAddress < Node->StartingAddress) + Node = Node->LeftChild; + else + Node = Node->RightChild; + + if (Node) { - 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); -} - -static PVOID MmFindGapBottomUp(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity) -{ - PLIST_ENTRY ListHead; - PLIST_ENTRY current_entry; - MEMORY_AREA* current; - MEMORY_AREA* next; - ULONG Gap; - PVOID Address; - - DPRINT("MmFindGapBottomUp(Length %x)\n",Length); - -#ifdef DBG - Length += PAGE_SIZE; /* For a guard page following the area */ -#endif - - 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); - Address = (PVOID) ((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length)); -#ifdef DBG - Address = (PVOID) ((char *) Address + PAGE_SIZE); /* For a guard page preceding the area */ -#endif - Address = (PVOID) MM_ROUND_UP(Address, Granularity); - if (Address < next->BaseAddress) - { - Gap = (char*)next->BaseAddress - ((char*)current->BaseAddress + PAGE_ROUND_UP(current->Length)); - if (Gap >= Length) + Depth++; + if (Depth == 22) { - return Address; + MmRebalanceTree(AddressSpace); + PreviousNode = Node->Parent; } } - current_entry = current_entry->Flink; } + while (Node != NULL); - if (current_entry == ListHead) - { - Address = (PVOID) MM_ROUND_UP(AddressSpace->LowestAddress, Granularity); - } + marea->LeftChild = marea->RightChild = NULL; + marea->Parent = PreviousNode; + if (marea->StartingAddress < PreviousNode->StartingAddress) + PreviousNode->LeftChild = marea; else - { - current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry); - Address = (char*)current->BaseAddress + PAGE_ROUND_UP(current->Length); -#ifdef DBG - Address = (PVOID) ((char *) Address + PAGE_SIZE); /* For a guard page preceding the area */ -#endif - Address = (PVOID) MM_ROUND_UP(Address, Granularity); - } - /* Check if enough space for the block */ - if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE) - { - if ((ULONG_PTR) Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG_PTR) Address) - { - DPRINT1("Failed to find gap\n"); - return NULL; - } - } - else - { - if (Length >= ~ ((ULONG_PTR) 0) - (ULONG_PTR) Address) - { - DPRINT1("Failed to find gap\n"); - return NULL; - } - } - return Address; + PreviousNode->RightChild = marea; } - -static PVOID MmFindGapTopDown(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity) +static PVOID +MmFindGapBottomUp( + PMADDRESS_SPACE AddressSpace, + ULONG_PTR Length, + ULONG_PTR Granularity) { - PLIST_ENTRY ListHead; - PLIST_ENTRY current_entry; - MEMORY_AREA* current; - ULONG Gap; - PVOID Address; - PVOID TopAddress; - PVOID BottomAddress; - PVOID HighestAddress; + PVOID HighestAddress = AddressSpace->LowestAddress < (PVOID)KERNEL_BASE ? + (PVOID)(KERNEL_BASE - 1) : (PVOID)MAXULONG_PTR; + PVOID AlignedAddress; + PMEMORY_AREA Node; + PMEMORY_AREA FirstNode; + PMEMORY_AREA PreviousNode; - DPRINT("MmFindGapTopDown(Length %lx)\n",Length); + MmVerifyMemoryAreas(AddressSpace); -#ifdef DBG - Length += PAGE_SIZE; /* For a guard page following the area */ -#endif + DPRINT("LowestAddress: %x HighestAddress: %x\n", + AddressSpace->LowestAddress, HighestAddress); - if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE) //(ULONG_PTR)MmSystemRangeStart) + AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity); + + /* Special case for empty tree. */ + if (AddressSpace->MemoryAreaRoot == NULL) { - HighestAddress = MmHighestUserAddress; - } - else - { - HighestAddress = (PVOID)0xFFFFFFFF; - } - - TopAddress = HighestAddress; - - 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); -#ifdef DBG - BottomAddress = (PVOID) ((char *) BottomAddress + PAGE_SIZE); /* For a guard page preceding the area */ -#endif - BottomAddress = (PVOID) MM_ROUND_UP(BottomAddress, Granularity); - DPRINT("Base %p Length %lx\n", current->BaseAddress, PAGE_ROUND_UP(current->Length)); - - if (BottomAddress < TopAddress && BottomAddress < HighestAddress) + if (HighestAddress - AlignedAddress >= Length) { - 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 (PVOID) MM_ROUND_DOWN((char*) TopAddress - Length + 1, Granularity); - } + DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress); + return AlignedAddress; } - TopAddress = (char*)current->BaseAddress - 1; - current_entry = current_entry->Blink; + DPRINT("MmFindGapBottomUp: 0\n"); + return 0; } - if (current_entry == ListHead) - { - Address = (PVOID) MM_ROUND_DOWN((char*) HighestAddress - Length + 1, Granularity); - } - else - { - Address = (PVOID) MM_ROUND_DOWN((char*)TopAddress - Length + 1, Granularity); - } + /* Go to the node with lowest address in the tree. */ + FirstNode = Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot); - /* Check if enough space for the block */ - if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE) + /* Traverse the tree from left to right. */ + PreviousNode = Node; + for (;;) { - if ((ULONG_PTR) Address >= KERNEL_BASE || Length > KERNEL_BASE - (ULONG_PTR) Address) + Node = MmIterateNextNode(Node); + if (Node == NULL) + break; + + AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity); + if (Node->StartingAddress > AlignedAddress && + Node->StartingAddress - AlignedAddress >= Length) { - DPRINT1("Failed to find gap\n"); - return NULL; - } - } - else - { - if (Length >= ~ ((ULONG_PTR) 0) - (ULONG_PTR) Address) - { - DPRINT1("Failed to find gap\n"); - return NULL; + DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress); + return AlignedAddress; } + + PreviousNode = Node; } - DPRINT("Found gap at %p\n", Address); - return Address; + /* Check if there is enough space after the last memory area. */ + AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity); + if (HighestAddress - AlignedAddress >= Length) + { + DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress); + return AlignedAddress; + } + + /* Check if there is enough space before the first memory area. */ + AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity); + if (FirstNode->StartingAddress > AlignedAddress && + FirstNode->StartingAddress - AlignedAddress >= Length) + { + DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress); + return AlignedAddress; + } + + DPRINT("MmFindGapBottomUp: 0\n"); + return 0; } -PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity, BOOL TopDown) +static PVOID +MmFindGapTopDown( + PMADDRESS_SPACE AddressSpace, + ULONG_PTR Length, + ULONG_PTR Granularity) +{ + PVOID HighestAddress = AddressSpace->LowestAddress < (PVOID)KERNEL_BASE ? + (PVOID)(KERNEL_BASE - 1) : (PVOID)MAXULONG_PTR; + PVOID AlignedAddress; + PMEMORY_AREA Node; + PMEMORY_AREA PreviousNode; + + MmVerifyMemoryAreas(AddressSpace); + + DPRINT("LowestAddress: %x HighestAddress: %x\n", + AddressSpace->LowestAddress, HighestAddress); + + AlignedAddress = MM_ROUND_DOWN(HighestAddress - Length + 1, Granularity); + + /* Check for overflow. */ + if (AlignedAddress > HighestAddress) + return NULL; + + /* Special case for empty tree. */ + if (AddressSpace->MemoryAreaRoot == NULL) + { + if (AlignedAddress >= (PVOID)AddressSpace->LowestAddress) + { + DPRINT("MmFindGapTopDown: %x\n", AlignedAddress); + return AlignedAddress; + } + DPRINT("MmFindGapTopDown: 0\n"); + return 0; + } + + /* Go to the node with highest address in the tree. */ + Node = MmIterateLastNode(AddressSpace->MemoryAreaRoot); + + /* Check if there is enough space after the last memory area. */ + if (Node->EndingAddress <= AlignedAddress) + { + DPRINT("MmFindGapTopDown: %x\n", AlignedAddress); + return AlignedAddress; + } + + /* Traverse the tree from left to right. */ + PreviousNode = Node; + for (;;) + { + Node = MmIteratePrevNode(Node); + if (Node == NULL) + break; + + AlignedAddress = MM_ROUND_DOWN(PreviousNode->StartingAddress - Length + 1, Granularity); + + /* Check for overflow. */ + if (AlignedAddress > PreviousNode->StartingAddress) + return NULL; + + if (Node->EndingAddress <= AlignedAddress) + { + DPRINT("MmFindGapTopDown: %x\n", AlignedAddress); + return AlignedAddress; + } + + PreviousNode = Node; + } + + AlignedAddress = MM_ROUND_DOWN(PreviousNode->StartingAddress - Length + 1, Granularity); + + /* Check for overflow. */ + if (AlignedAddress > PreviousNode->StartingAddress) + return NULL; + + if (AlignedAddress >= (PVOID)AddressSpace->LowestAddress) + { + DPRINT("MmFindGapTopDown: %x\n", AlignedAddress); + return AlignedAddress; + } + + DPRINT("MmFindGapTopDown: 0\n"); + return 0; +} + + +PVOID STDCALL +MmFindGap( + PMADDRESS_SPACE AddressSpace, + ULONG_PTR Length, + ULONG_PTR Granularity, + BOOLEAN TopDown) { if (TopDown) return MmFindGapTopDown(AddressSpace, Length, Granularity); @@ -367,12 +626,19 @@ PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity, B return MmFindGapBottomUp(AddressSpace, Length, Granularity); } -ULONG MmFindGapAtAddress(PMADDRESS_SPACE AddressSpace, PVOID Address) +ULONG_PTR STDCALL +MmFindGapAtAddress( + PMADDRESS_SPACE AddressSpace, + PVOID Address) { - PLIST_ENTRY current_entry, ListHead; - PMEMORY_AREA current; + PMEMORY_AREA Node = AddressSpace->MemoryAreaRoot; + PMEMORY_AREA RightNeighbour = NULL; + PVOID HighestAddress = AddressSpace->LowestAddress < (PVOID)KERNEL_BASE ? + (PVOID)(KERNEL_BASE - 1) : (PVOID)MAXULONG_PTR; - Address = (PVOID)PAGE_ROUND_DOWN(Address); + MmVerifyMemoryAreas(AddressSpace); + + Address = MM_ROUND_DOWN(Address, PAGE_SIZE); if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE) { @@ -383,66 +649,229 @@ ULONG MmFindGapAtAddress(PMADDRESS_SPACE AddressSpace, PVOID Address) } else { - if ((ULONG_PTR)Address < (ULONG_PTR)AddressSpace->LowestAddress) + if (Address < AddressSpace->LowestAddress) { return 0; } } - ListHead = &AddressSpace->MAreaListHead; - - current_entry = ListHead->Flink; - while (current_entry != ListHead) + while (Node != NULL) { - current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry); - if (current->BaseAddress <= Address && (char*)Address < (char*)current->BaseAddress + current->Length) + if (Address < Node->StartingAddress) { + RightNeighbour = Node; + Node = Node->LeftChild; + } + else if (Address >= Node->EndingAddress) + { + Node = Node->RightChild; + } + else + { + DPRINT("MmFindGapAtAddress: 0\n"); return 0; } - else if (current->BaseAddress > Address) - { - return (ULONG_PTR)current->BaseAddress - (ULONG_PTR)Address; - } - current_entry = current_entry->Flink; } - if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE) + + if (RightNeighbour) { - return KERNEL_BASE - (ULONG_PTR)Address; + DPRINT("MmFindGapAtAddress: %x [%x]\n", Address, RightNeighbour->StartingAddress - Address); + return RightNeighbour->StartingAddress - Address; } else { - return 0 - (ULONG_PTR)Address; + DPRINT("MmFindGapAtAddress: %x [%x]\n", Address, HighestAddress - Address); + return HighestAddress - Address; } } +/** + * @name MmInitMemoryAreas + * + * Initialize the memory area list implementation. + */ + NTSTATUS INIT_FUNCTION MmInitMemoryAreas(VOID) -/* - * FUNCTION: Initialize the memory area list - */ { DPRINT("MmInitMemoryAreas()\n",0); return(STATUS_SUCCESS); } -NTSTATUS -MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace, - PVOID BaseAddress, - ULONG Length, - VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, - PVOID Address, PFN_TYPE Page, - SWAPENTRY SwapEntry, BOOLEAN Dirty), - PVOID FreePageContext) + +/* + * @name MmFreeMemoryArea + * + * Free an existing memory area. + * + * @param AddressSpace + * Address space to free the area from. + * @param MemoryArea + * Memory area we're about to free. + * @param FreePage + * Callback function for each freed page. + * @param FreePageContext + * Context passed to the callback function. + * + * @return Status + * + * @remarks Lock the address space before calling this function. + */ + +NTSTATUS STDCALL +MmFreeMemoryArea( + PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PMM_FREE_PAGE_FUNC FreePage, + PVOID FreePageContext) { - MEMORY_AREA* MemoryArea; - char* Address; - char* EndAddress; + PMEMORY_AREA *ParentReplace; + PVOID Address; + PVOID EndAddress; PEPROCESS CurrentProcess = PsGetCurrentProcess(); + if (AddressSpace->Process != NULL && + AddressSpace->Process != CurrentProcess) + { + KeAttachProcess(&AddressSpace->Process->Pcb); + } + + EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE); + for (Address = MemoryArea->StartingAddress; Address < EndAddress; Address += PAGE_SIZE) + { + if (MemoryArea->Type == MEMORY_AREA_IO_MAPPING) + { + MmRawDeleteVirtualMapping((PVOID)Address); + } + else + { + BOOL Dirty = FALSE; + SWAPENTRY SwapEntry = 0; + PFN_TYPE Page = 0; + + if (MmIsPageSwapEntry(AddressSpace->Process, (PVOID)Address)) + { + MmDeletePageFileMapping(AddressSpace->Process, (PVOID)Address, &SwapEntry); + } + else + { + MmDeleteVirtualMapping(AddressSpace->Process, (PVOID)Address, FALSE, &Dirty, &Page); + } + if (FreePage != NULL) + { + FreePage(FreePageContext, MemoryArea, (PVOID)Address, + Page, SwapEntry, (BOOLEAN)Dirty); + } + } + } + + if (AddressSpace->Process != NULL && + AddressSpace->Process != CurrentProcess) + { + KeDetachProcess(); + } + + /* Remove the tree item. */ + { + if (MemoryArea->Parent != NULL) + { + if (MemoryArea->Parent->LeftChild == MemoryArea) + ParentReplace = &MemoryArea->Parent->LeftChild; + else + ParentReplace = &MemoryArea->Parent->RightChild; + } + else + ParentReplace = &AddressSpace->MemoryAreaRoot; + + if (MemoryArea->RightChild == NULL) + { + *ParentReplace = MemoryArea->LeftChild; + if (MemoryArea->LeftChild) + MemoryArea->LeftChild->Parent = MemoryArea->Parent; + } + else + { + if (MemoryArea->RightChild->LeftChild == NULL) + { + MemoryArea->RightChild->LeftChild = MemoryArea->LeftChild; + if (MemoryArea->LeftChild) + MemoryArea->LeftChild->Parent = MemoryArea->RightChild; + + *ParentReplace = MemoryArea->RightChild; + MemoryArea->RightChild->Parent = MemoryArea->Parent; + } + else + { + PMEMORY_AREA LowestNode; + + LowestNode = MemoryArea->RightChild->LeftChild; + while (LowestNode->LeftChild != NULL) + LowestNode = LowestNode->LeftChild; + + LowestNode->Parent->LeftChild = LowestNode->RightChild; + if (LowestNode->RightChild) + LowestNode->RightChild->Parent = LowestNode->Parent; + + LowestNode->LeftChild = MemoryArea->LeftChild; + if (MemoryArea->LeftChild) + MemoryArea->LeftChild->Parent = LowestNode; + + LowestNode->RightChild = MemoryArea->RightChild; + MemoryArea->RightChild->Parent = LowestNode; + + *ParentReplace = LowestNode; + LowestNode->Parent = MemoryArea->Parent; + } + } + } + + ExFreePool(MemoryArea); + + DPRINT("MmFreeMemoryAreaByNode() succeeded\n"); + + return STATUS_SUCCESS; +} + +/* + * @name MmFreeMemoryAreaByPtr + * + * Free an existing memory area given a pointer inside it. + * + * @param AddressSpace + * Address space to free the area from. + * @param BaseAddress + * Address in the memory area we're about to free. + * @param FreePage + * Callback function for each freed page. + * @param FreePageContext + * Context passed to the callback function. + * + * @return Status + * + * @see MmFreeMemoryArea + * + * @todo Should we require the BaseAddress to be really the starting + * address of the memory area or is the current relaxed check + * (BaseAddress can point anywhere in the memory area) acceptable? + * + * @remarks Lock the address space before calling this function. + */ + +NTSTATUS STDCALL +MmFreeMemoryAreaByPtr( + PMADDRESS_SPACE AddressSpace, + PVOID BaseAddress, + PMM_FREE_PAGE_FUNC FreePage, + PVOID FreePageContext) +{ + PMEMORY_AREA MemoryArea; + DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x," "FreePageContext %d)\n",AddressSpace,BaseAddress,Length, FreePageContext); + MmVerifyMemoryAreas(AddressSpace); + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress); if (MemoryArea == NULL) @@ -450,92 +879,69 @@ MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace, KEBUGCHECK(0); return(STATUS_UNSUCCESSFUL); } - if (AddressSpace->Process != NULL && - AddressSpace->Process != CurrentProcess) - { - KeAttachProcess(&AddressSpace->Process->Pcb); - } - EndAddress = (char*)MemoryArea->BaseAddress + PAGE_ROUND_UP(MemoryArea->Length); - for (Address = MemoryArea->BaseAddress; Address < EndAddress; Address += PAGE_SIZE) - { - if (MemoryArea->Type == MEMORY_AREA_IO_MAPPING) - { - MmRawDeleteVirtualMapping(Address); - } - else - { - BOOL Dirty = FALSE; - SWAPENTRY SwapEntry = 0; - PFN_TYPE Page = 0; - - - if (MmIsPageSwapEntry(AddressSpace->Process, Address)) - { - MmDeletePageFileMapping(AddressSpace->Process, Address, &SwapEntry); - } - else - { - MmDeleteVirtualMapping(AddressSpace->Process, Address, FALSE, &Dirty, &Page); - } - if (FreePage != NULL) - { - FreePage(FreePageContext, MemoryArea, Address, - Page, SwapEntry, (BOOLEAN)Dirty); - } - } - } - if (AddressSpace->Process != NULL && - AddressSpace->Process != CurrentProcess) - { - KeDetachProcess(); - } - RemoveEntryList(&MemoryArea->Entry); - ExFreePool(MemoryArea); - - DPRINT("MmFreeMemoryArea() succeeded\n"); - - return(STATUS_SUCCESS); + return MmFreeMemoryArea(AddressSpace, MemoryArea, FreePage, FreePageContext); } -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) /* - * FUNCTION: Create a memory area - * ARGUMENTS: - * AddressSpace = Address space to create the area in - * Type = Type of the address space - * BaseAddress = - * Length = Length to allocate - * Attributes = Protection attributes for the memory area - * Result = Receives a pointer to the memory area on exit - * RETURNS: Status - * NOTES: Lock the address space before calling this function + * @name MmCreateMemoryArea + * + * Create a memory area. + * + * @param AddressSpace + * Address space to create the area in. + * @param Type + * Type of the memory area. + * @param BaseAddress + * Base address for the memory area we're about the create. On + * input it contains either 0 (auto-assign address) or preferred + * address. On output it contains the starting address of the + * newly created area. + * @param Length + * Length of the area to allocate. + * @param Attributes + * Protection attributes for the memory area. + * @param Result + * Receives a pointer to the memory area on successful exit. + * + * @return Status + * + * @remarks Lock the address space before calling this function. */ + +NTSTATUS STDCALL +MmCreateMemoryArea(PEPROCESS Process, + PMADDRESS_SPACE AddressSpace, + ULONG Type, + PVOID *BaseAddress, + ULONG_PTR Length, + ULONG Attributes, + PMEMORY_AREA *Result, + BOOLEAN FixedAddress, + BOOLEAN TopDown, + PHYSICAL_ADDRESS BoundaryAddressMultiple) { PVOID EndAddress; ULONG Granularity; ULONG tmpLength; - DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x," - "*BaseAddress %x, Length %x, Attributes %x, Result %x)\n", - Type,BaseAddress,*BaseAddress,Length,Attributes,Result); + PMEMORY_AREA MemoryArea; + + DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x, " + "*BaseAddress %x, Length %x, Attributes %x, TopDown: %x, " + "FixedAddress %x, Result %x)\n", + Type, BaseAddress, *BaseAddress, Length, Attributes, TopDown, + FixedAddress, Result); + + MmVerifyMemoryAreas(AddressSpace); Granularity = (MEMORY_AREA_VIRTUAL_MEMORY == Type ? MM_VIRTMEM_GRANULARITY : PAGE_SIZE); if ((*BaseAddress) == 0 && !FixedAddress) { tmpLength = PAGE_ROUND_UP(Length); *BaseAddress = MmFindGap(AddressSpace, - PAGE_ROUND_UP(Length), + tmpLength, Granularity, - TopDown); + TopDown != 0); if ((*BaseAddress) == 0) { DPRINT("No suitable gap\n"); @@ -544,26 +950,28 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process, } else { - tmpLength = Length + ((ULONG_PTR) *BaseAddress - - (ULONG_PTR) MM_ROUND_DOWN(*BaseAddress, Granularity)); + tmpLength = Length + ((ULONG_PTR) *BaseAddress + - (ULONG_PTR) MM_ROUND_DOWN(*BaseAddress, Granularity)); *BaseAddress = MM_ROUND_DOWN(*BaseAddress, Granularity); if (AddressSpace->LowestAddress == (PVOID)KERNEL_BASE && - (*BaseAddress) < (PVOID)KERNEL_BASE) + *BaseAddress < (PVOID)KERNEL_BASE) { + CHECKPOINT; return STATUS_ACCESS_VIOLATION; } if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE && - (PVOID)((char*)(*BaseAddress) + tmpLength) > (PVOID)KERNEL_BASE) + (ULONG_PTR)(*BaseAddress) + tmpLength > KERNEL_BASE) { + CHECKPOINT; return STATUS_ACCESS_VIOLATION; } if (BoundaryAddressMultiple.QuadPart != 0) { EndAddress = ((char*)(*BaseAddress)) + tmpLength-1; - ASSERT(((DWORD_PTR)*BaseAddress/BoundaryAddressMultiple.QuadPart) == ((DWORD_PTR)EndAddress/BoundaryAddressMultiple.QuadPart)); + ASSERT(((ULONG_PTR)*BaseAddress/BoundaryAddressMultiple.QuadPart) == ((DWORD_PTR)EndAddress/BoundaryAddressMultiple.QuadPart)); } if (MmOpenMemoryAreaByRegion(AddressSpace, @@ -575,52 +983,56 @@ NTSTATUS MmCreateMemoryArea(PEPROCESS Process, } } - *Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA), - TAG_MAREA); - RtlZeroMemory(*Result,sizeof(MEMORY_AREA)); - (*Result)->Type = Type; - (*Result)->BaseAddress = *BaseAddress; - (*Result)->Length = tmpLength; - (*Result)->Attributes = Attributes; - (*Result)->LockCount = 0; - (*Result)->Process = Process; - (*Result)->PageOpCount = 0; - (*Result)->DeleteInProgress = FALSE; + MemoryArea = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA), + TAG_MAREA); + RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA)); + MemoryArea->Type = Type; + MemoryArea->StartingAddress = *BaseAddress; + MemoryArea->EndingAddress = *BaseAddress + tmpLength; + MemoryArea->Attributes = Attributes; + MemoryArea->LockCount = 0; + MemoryArea->Process = Process; + MemoryArea->PageOpCount = 0; + MemoryArea->DeleteInProgress = FALSE; - MmInsertMemoryArea(AddressSpace, *Result); + MmInsertMemoryArea(AddressSpace, MemoryArea); - DPRINT("MmCreateMemoryArea() succeeded\n"); + *Result = MemoryArea; + + DPRINT("MmCreateMemoryArea() succeeded (%x)\n", *BaseAddress); return STATUS_SUCCESS; } -void +VOID STDCALL MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process, PMADDRESS_SPACE AddressSpace, PVOID BaseAddress) { - PMEMORY_AREA MemoryArea; - PLIST_ENTRY Entry; - PMM_REGION Region; - BOOLEAN Reserved; + PMEMORY_AREA MemoryArea; + PLIST_ENTRY Entry; + PMM_REGION Region; + BOOLEAN Reserved; - MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress); - if (NULL != MemoryArea) - { + MmVerifyMemoryAreas(AddressSpace); + + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress); + if (MemoryArea != NULL) + { Entry = MemoryArea->Data.VirtualMemoryData.RegionListHead.Flink; Reserved = TRUE; while (Reserved && Entry != &MemoryArea->Data.VirtualMemoryData.RegionListHead) - { - Region = CONTAINING_RECORD(Entry, MM_REGION, RegionListEntry); - Reserved = (MEM_RESERVE == Region->Type); - Entry = Entry->Flink; - } + { + Region = CONTAINING_RECORD(Entry, MM_REGION, RegionListEntry); + Reserved = (MEM_RESERVE == Region->Type); + Entry = Entry->Flink; + } if (Reserved) - { - MmFreeVirtualMemory(Process, MemoryArea); - } - } + { + MmFreeVirtualMemory(Process, MemoryArea); + } + } } /* EOF */ diff --git a/reactos/ntoskrnl/mm/mdl.c b/reactos/ntoskrnl/mm/mdl.c index 31abfea567d..3811043f96f 100644 --- a/reactos/ntoskrnl/mm/mdl.c +++ b/reactos/ntoskrnl/mm/mdl.c @@ -269,7 +269,7 @@ MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode) KEBUGCHECK(0); } - Base = (char*)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE; + Base = (PVOID)((ULONG_PTR)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE); if (MiMdlMappingRegionHint == StartingOffset) { @@ -384,7 +384,7 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl) NULL); } - if ((DWORD)BaseAddress >= KERNEL_BASE) + if ((ULONG_PTR)BaseAddress >= KERNEL_BASE) { ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA); @@ -416,7 +416,7 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl) KEBUGCHECK(0); } - MmFreeMemoryArea( &Mdl->Process->AddressSpace, Marea->BaseAddress, 0, NULL, NULL ); + MmFreeMemoryArea( &Mdl->Process->AddressSpace, Marea, NULL, NULL ); Mdl->Process = NULL; } diff --git a/reactos/ntoskrnl/mm/mm.c b/reactos/ntoskrnl/mm/mm.c index 6e08490e8a9..6a132217b30 100644 --- a/reactos/ntoskrnl/mm/mm.c +++ b/reactos/ntoskrnl/mm/mm.c @@ -99,13 +99,13 @@ NTSTATUS MmReleaseMemoryArea(PEPROCESS Process, PMEMORY_AREA Marea) 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, Marea->StartingAddress, Marea->EndingAddress, Marea->Type); switch (Marea->Type) { case MEMORY_AREA_SECTION_VIEW: - Status = MmUnmapViewOfSection(Process, Marea->BaseAddress); + Status = MmUnmapViewOfSection(Process, (PVOID)Marea->StartingAddress); ASSERT(Status == STATUS_SUCCESS); return(STATUS_SUCCESS); @@ -116,8 +116,7 @@ NTSTATUS MmReleaseMemoryArea(PEPROCESS Process, PMEMORY_AREA Marea) case MEMORY_AREA_SHARED_DATA: case MEMORY_AREA_NO_ACCESS: Status = MmFreeMemoryArea(&Process->AddressSpace, - Marea->BaseAddress, - 0, + Marea, NULL, NULL); break; @@ -135,20 +134,13 @@ NTSTATUS MmReleaseMemoryArea(PEPROCESS Process, PMEMORY_AREA Marea) NTSTATUS MmReleaseMmInfo(PEPROCESS Process) { - PLIST_ENTRY CurrentEntry; - PMEMORY_AREA Current; - DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process, 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); - } + while (Process->AddressSpace.MemoryAreaRoot != NULL) + MmReleaseMemoryArea(Process, Process->AddressSpace.MemoryAreaRoot); Mmi386ReleaseMmInfo(Process); @@ -208,7 +200,7 @@ BOOLEAN STDCALL MmIsAddressValid(PVOID VirtualAddress) } NTSTATUS MmAccessFault(KPROCESSOR_MODE Mode, - ULONG Address, + ULONG Address, /* FiN TODO: Should be ULONG_PTR! */ BOOLEAN FromMdl) { PMADDRESS_SPACE AddressSpace; @@ -330,7 +322,7 @@ NTSTATUS MmCommitPagedPoolAddress(PVOID Address, BOOLEAN Locked) } NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode, - ULONG Address, + ULONG Address, /* FiN TODO: Should be ULONG_PTR! */ BOOLEAN FromMdl) { PMADDRESS_SPACE AddressSpace; diff --git a/reactos/ntoskrnl/mm/mminit.c b/reactos/ntoskrnl/mm/mminit.c index 6f03c1cf7cb..6daca270538 100644 --- a/reactos/ntoskrnl/mm/mminit.c +++ b/reactos/ntoskrnl/mm/mminit.c @@ -480,10 +480,9 @@ VOID MiFreeInitMemory(VOID) { MmLockAddressSpace(MmGetKernelAddressSpace()); - MmFreeMemoryArea(MmGetKernelAddressSpace(), - (PVOID)&_init_start__, - PAGE_ROUND_UP((ULONG)&_init_end__) - (ULONG)&_init_start__, - MiFreeInitMemoryPage, - NULL); + MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(), + (PVOID)&_init_start__, + MiFreeInitMemoryPage, + NULL); MmUnlockAddressSpace(MmGetKernelAddressSpace()); } diff --git a/reactos/ntoskrnl/mm/ncache.c b/reactos/ntoskrnl/mm/ncache.c index 57439281d5c..48e3ccfc50a 100644 --- a/reactos/ntoskrnl/mm/ncache.c +++ b/reactos/ntoskrnl/mm/ncache.c @@ -1,4 +1,4 @@ -/* $Id: ncache.c,v 1.31 2004/10/22 20:38:22 ekohl Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -129,11 +129,10 @@ VOID STDCALL MmFreeNonCachedMemory (IN PVOID BaseAddress, IN ULONG NumberOfBytes) { MmLockAddressSpace(MmGetKernelAddressSpace()); - MmFreeMemoryArea (MmGetKernelAddressSpace(), - BaseAddress, - NumberOfBytes, - MmFreeNonCachedPage, - NULL); + MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(), + BaseAddress, + MmFreeNonCachedPage, + NULL); MmUnlockAddressSpace(MmGetKernelAddressSpace()); } diff --git a/reactos/ntoskrnl/mm/pe.c b/reactos/ntoskrnl/mm/pe.c index aceca81a6d2..a7d71ae7551 100644 --- a/reactos/ntoskrnl/mm/pe.c +++ b/reactos/ntoskrnl/mm/pe.c @@ -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: pe.c,v 1.2 2004/12/30 05:59:11 hyperion Exp $ +/* $Id$ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/pe.c @@ -35,7 +35,7 @@ #include -#define NDEBUG +//#define NDEBUG #include #include @@ -666,8 +666,10 @@ l_ReadHeaderFromFile: DIE(("PointerToRawData[%u] is not aligned\n", i)); /* sections must be contiguous, ordered by base address and non-overlapping */ +#if 0 if(pishSectionHeaders[i].PointerToRawData != nPrevFileEndOfSegment) DIE(("File gap between section %u and the previous\n", i)); +#endif /* conversion */ pssSegments[i].FileOffset = pishSectionHeaders[i].PointerToRawData; diff --git a/reactos/ntoskrnl/mm/rmap.c b/reactos/ntoskrnl/mm/rmap.c index 2084ba50f3b..ee1198081b8 100644 --- a/reactos/ntoskrnl/mm/rmap.c +++ b/reactos/ntoskrnl/mm/rmap.c @@ -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.32 2004/12/24 17:06:59 navaraf Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top directory * PROJECT: ReactOS kernel @@ -91,7 +91,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page) } Process = entry->Process; Address = entry->Address; - if ((((ULONG)Address) & 0xFFF) != 0) + if ((((ULONG_PTR)Address) & 0xFFF) != 0) { KEBUGCHECK(0); } @@ -131,7 +131,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page) Type = MemoryArea->Type; if (Type == MEMORY_AREA_SECTION_VIEW) { - Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress); + Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress; /* * Get or create a pageop @@ -220,7 +220,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page) } Process = entry->Process; Address = entry->Address; - if ((((ULONG)Address) & 0xFFF) != 0) + if ((((ULONG_PTR)Address) & 0xFFF) != 0) { KEBUGCHECK(0); } @@ -255,7 +255,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page) Type = MemoryArea->Type; if (Type == MEMORY_AREA_SECTION_VIEW) { - Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress); + Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress; /* * Get or create a pageop diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index e8fe7f4c580..f40ea824952 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -611,7 +611,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, ULONG Offset; PFN_TYPE Page; NTSTATUS Status; - ULONG PAddress; + PVOID PAddress; PSECTION_OBJECT Section; PMM_SECTION_SEGMENT Segment; ULONG Entry; @@ -635,12 +635,12 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, return(STATUS_SUCCESS); } - PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address)); - Offset = PAddress - (ULONG)MemoryArea->BaseAddress; + PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); + Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress; Segment = MemoryArea->Data.SectionData.Segment; Section = MemoryArea->Data.SectionData.Section; - Region = MmFindRegion(MemoryArea->BaseAddress, + Region = MmFindRegion(MemoryArea->StartingAddress, &MemoryArea->Data.SectionData.RegionListHead, Address, NULL); /* @@ -1129,7 +1129,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, PFN_TYPE NewPage; PVOID NewAddress; NTSTATUS Status; - ULONG PAddress; + PVOID PAddress; ULONG Offset; PMM_PAGEOP PageOp; PMM_REGION Region; @@ -1148,12 +1148,12 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, /* * Find the offset of the page */ - PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address)); - Offset = PAddress - (ULONG)MemoryArea->BaseAddress; + PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE); + Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress; Segment = MemoryArea->Data.SectionData.Segment; Section = MemoryArea->Data.SectionData.Section; - Region = MmFindRegion(MemoryArea->BaseAddress, + Region = MmFindRegion(MemoryArea->StartingAddress, &MemoryArea->Data.SectionData.RegionListHead, Address, NULL); /* @@ -1181,7 +1181,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, PFN_FROM_SSE(Entry) != OldPage) { /* This is a private page. We must only change the page protection. */ - MmSetPageProtect(AddressSpace->Process, (PVOID)PAddress, Region->Protect); + MmSetPageProtect(AddressSpace->Process, PAddress, Region->Protect); return(STATUS_SUCCESS); } @@ -1244,7 +1244,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, */ NewAddress = ExAllocatePageWithPhysPage(NewPage); - memcpy(NewAddress, (PVOID)PAddress, PAGE_SIZE); + memcpy(NewAddress, PAddress, PAGE_SIZE); ExUnmapPage(NewAddress); /* @@ -1267,7 +1267,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, KEBUGCHECK(0); return(Status); } - MmInsertRmap(NewPage, AddressSpace->Process, (PVOID)PAddress); + MmInsertRmap(NewPage, AddressSpace->Process, PAddress); if (!NT_SUCCESS(Status)) { DbgPrint("Unable to create virtual mapping\n"); @@ -1282,7 +1282,7 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, /* * Unshare the old page. */ - MmDeleteRmap(OldPage, AddressSpace->Process, (PVOID)PAddress); + MmDeleteRmap(OldPage, AddressSpace->Process, PAddress); MmLockSectionSegment(Segment); MmUnsharePageEntrySectionSegment(Section, Segment, Offset, FALSE, FALSE); MmUnlockSectionSegment(Segment); @@ -1351,7 +1351,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, Context.Segment = MemoryArea->Data.SectionData.Segment; Context.Section = MemoryArea->Data.SectionData.Section; - Context.Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress); + Context.Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress; FileOffset = Context.Offset + Context.Segment->FileOffset; IsImageSection = Context.Section->AllocationAttributes & SEC_IMAGE ? TRUE : FALSE; @@ -1691,7 +1691,7 @@ MmWritePageSectionView(PMADDRESS_SPACE AddressSpace, Address = (PVOID)PAGE_ROUND_DOWN(Address); - Offset = (ULONG)((char*)Address - (ULONG)MemoryArea->BaseAddress); + Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress; /* * Get the segment and section. @@ -1855,7 +1855,7 @@ MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace, ULONG Entry; PFN_TYPE Page; - Offset = (ULONG)Address - (ULONG)MemoryArea->BaseAddress; + Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress; Entry = MmGetPageEntrySectionSegment(Segment, Offset); Page = MmGetPfnForProcess(AddressSpace->Process, Address); @@ -1887,14 +1887,17 @@ MmProtectSectionView(PMADDRESS_SPACE AddressSpace, { PMM_REGION Region; NTSTATUS Status; + ULONG_PTR MaxLength; - Length = - min(Length, (ULONG) ((char*)MemoryArea->BaseAddress + MemoryArea->Length - (char*)BaseAddress)); - Region = MmFindRegion(MemoryArea->BaseAddress, + MaxLength = (ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)BaseAddress; + if (Length > MaxLength) + Length = MaxLength; + + Region = MmFindRegion(MemoryArea->StartingAddress, &MemoryArea->Data.SectionData.RegionListHead, BaseAddress, NULL); *OldProtect = Region->Protect; - Status = MmAlterRegion(AddressSpace, MemoryArea->BaseAddress, + Status = MmAlterRegion(AddressSpace, MemoryArea->StartingAddress, &MemoryArea->Data.SectionData.RegionListHead, BaseAddress, Length, Region->Type, Protect, MmAlterViewAttributes); @@ -1915,7 +1918,7 @@ MmQuerySectionView(PMEMORY_AREA MemoryArea, PMEMORY_AREA CurrentMArea; KIRQL oldIrql; - Region = MmFindRegion(MemoryArea->BaseAddress, + Region = MmFindRegion((PVOID)MemoryArea->StartingAddress, &MemoryArea->Data.SectionData.RegionListHead, Address, &RegionBaseAddress); if (Region == NULL) @@ -1934,11 +1937,11 @@ MmQuerySectionView(PMEMORY_AREA MemoryArea, CurrentEntry = CurrentEntry->Flink; if (Info->AllocationBase == NULL) { - Info->AllocationBase = CurrentMArea->BaseAddress; + Info->AllocationBase = CurrentMArea->StartingAddress; } - else if (CurrentMArea->BaseAddress < Info->AllocationBase) + else if (CurrentMArea->StartingAddress < Info->AllocationBase) { - Info->AllocationBase = CurrentMArea->BaseAddress; + Info->AllocationBase = CurrentMArea->StartingAddress; } } KeReleaseSpinLock(&Section->ViewListLock, oldIrql); @@ -1949,11 +1952,12 @@ MmQuerySectionView(PMEMORY_AREA MemoryArea, else { Info->BaseAddress = RegionBaseAddress; - Info->AllocationBase = MemoryArea->BaseAddress; + Info->AllocationBase = MemoryArea->StartingAddress; Info->AllocationProtect = MemoryArea->Attributes; Info->Type = MEM_MAPPED; } - Info->RegionSize = PAGE_ROUND_UP(MemoryArea->Length); + Info->RegionSize = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress - + (ULONG_PTR)MemoryArea->StartingAddress); Info->State = MEM_COMMIT; Info->Protect = Region->Protect; @@ -3583,7 +3587,7 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, Address = (PVOID)PAGE_ROUND_DOWN(Address); - Offset = ((ULONG_PTR)Address - (ULONG_PTR)MArea->BaseAddress) + + Offset = ((ULONG_PTR)Address - (ULONG_PTR)MArea->StartingAddress) + MemoryArea->Data.SectionData.ViewOffset; Section = MArea->Data.SectionData.Section; @@ -3711,16 +3715,14 @@ MmUnmapViewOfSegment(PMADDRESS_SPACE AddressSpace, if (Section->AllocationAttributes & SEC_PHYSICALMEMORY) { Status = MmFreeMemoryArea(AddressSpace, - BaseAddress, - 0, + MemoryArea, NULL, NULL); } else { Status = MmFreeMemoryArea(AddressSpace, - BaseAddress, - 0, + MemoryArea, MmFreeSectionPage, MemoryArea); } @@ -4087,7 +4089,7 @@ MmAllocateSection (IN ULONG Length, PVOID BaseAddress) KEBUGCHECK(0); } Status = MmCreateVirtualMapping (NULL, - ((char*)Result + (i * PAGE_SIZE)), + (PVOID)(Result + (i * PAGE_SIZE)), PAGE_READWRITE, &Page, 1); @@ -4178,7 +4180,7 @@ MmMapViewOfSection(IN PVOID SectionObject, { ULONG i; ULONG NrSegments; - PVOID ImageBase; + ULONG_PTR ImageBase; ULONG ImageSize; PMM_IMAGE_SECTION_OBJECT ImageSectionObject; PMM_SECTION_SEGMENT SectionSegments; @@ -4188,10 +4190,10 @@ MmMapViewOfSection(IN PVOID SectionObject, NrSegments = ImageSectionObject->NrSegments; - ImageBase = *BaseAddress; - if (ImageBase == NULL) + ImageBase = (ULONG_PTR)*BaseAddress; + if (ImageBase == 0) { - ImageBase = (PVOID)ImageSectionObject->ImageBase; + ImageBase = ImageSectionObject->ImageBase; } ImageSize = 0; @@ -4207,7 +4209,7 @@ MmMapViewOfSection(IN PVOID SectionObject, } /* Check there is enough space to map the section at that point. */ - if (MmOpenMemoryAreaByRegion(AddressSpace, ImageBase, + if (MmOpenMemoryAreaByRegion(AddressSpace, (PVOID)ImageBase, PAGE_ROUND_UP(ImageSize)) != NULL) { /* Fail if the user requested a fixed base address. */ @@ -4217,8 +4219,8 @@ MmMapViewOfSection(IN PVOID SectionObject, return(STATUS_UNSUCCESSFUL); } /* Otherwise find a gap to map the image. */ - ImageBase = MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), PAGE_SIZE, FALSE); - if (ImageBase == NULL) + ImageBase = (ULONG_PTR)MmFindGap(AddressSpace, PAGE_ROUND_UP(ImageSize), PAGE_SIZE, FALSE); + if (ImageBase == 0) { MmUnlockAddressSpace(AddressSpace); return(STATUS_UNSUCCESSFUL); @@ -4250,7 +4252,7 @@ MmMapViewOfSection(IN PVOID SectionObject, } } - *BaseAddress = ImageBase; + *BaseAddress = (PVOID)ImageBase; } else { diff --git a/reactos/ntoskrnl/mm/virtual.c b/reactos/ntoskrnl/mm/virtual.c index c83aa887c58..0dcd39a5765 100644 --- a/reactos/ntoskrnl/mm/virtual.c +++ b/reactos/ntoskrnl/mm/virtual.c @@ -204,9 +204,10 @@ MiQueryVirtualMemory (IN HANDLE ProcessHandle, Info->State = MEM_FREE; Info->Protect = MemoryArea->Attributes; Info->AllocationProtect = MemoryArea->Attributes; - Info->BaseAddress = MemoryArea->BaseAddress; - Info->AllocationBase = MemoryArea->BaseAddress; - Info->RegionSize = MemoryArea->Length; + Info->BaseAddress = MemoryArea->StartingAddress; + Info->AllocationBase = MemoryArea->StartingAddress; + Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress - + (ULONG_PTR)MemoryArea->StartingAddress; Status = STATUS_SUCCESS; *ResultLength = sizeof(MEMORY_BASIC_INFORMATION); break; @@ -215,9 +216,10 @@ MiQueryVirtualMemory (IN HANDLE ProcessHandle, Info->State = MEM_COMMIT; Info->Protect = MemoryArea->Attributes; Info->AllocationProtect = MemoryArea->Attributes; - Info->BaseAddress = MemoryArea->BaseAddress; - Info->AllocationBase = MemoryArea->BaseAddress; - Info->RegionSize = MemoryArea->Length; + Info->BaseAddress = MemoryArea->StartingAddress; + Info->AllocationBase = MemoryArea->StartingAddress; + Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress - + (ULONG_PTR)MemoryArea->StartingAddress; Status = STATUS_SUCCESS; *ResultLength = sizeof(MEMORY_BASIC_INFORMATION); break; @@ -235,9 +237,10 @@ MiQueryVirtualMemory (IN HANDLE ProcessHandle, Info->State = MEM_COMMIT; Info->Protect = MemoryArea->Attributes; Info->AllocationProtect = MemoryArea->Attributes; - Info->BaseAddress = MemoryArea->BaseAddress; - Info->AllocationBase = MemoryArea->BaseAddress; - Info->RegionSize = MemoryArea->Length; + Info->BaseAddress = MemoryArea->StartingAddress; + Info->AllocationBase = MemoryArea->StartingAddress; + Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress - + (ULONG_PTR)MemoryArea->StartingAddress; Status = STATUS_SUCCESS; *ResultLength = sizeof(MEMORY_BASIC_INFORMATION); break; @@ -255,9 +258,10 @@ MiQueryVirtualMemory (IN HANDLE ProcessHandle, Info->State = MEM_COMMIT; Info->Protect = MemoryArea->Attributes; Info->AllocationProtect = MemoryArea->Attributes; - Info->BaseAddress = MemoryArea->BaseAddress; - Info->AllocationBase = MemoryArea->BaseAddress; - Info->RegionSize = MemoryArea->Length; + Info->BaseAddress = MemoryArea->StartingAddress; + Info->AllocationBase = MemoryArea->StartingAddress; + Info->RegionSize = (ULONG_PTR)MemoryArea->EndingAddress - + (ULONG_PTR)MemoryArea->StartingAddress; Status = STATUS_SUCCESS; *ResultLength = sizeof(MEMORY_BASIC_INFORMATION); break; diff --git a/reactos/ntoskrnl/ps/w32call.c b/reactos/ntoskrnl/ps/w32call.c index faa7d24a7a2..2318a6af27b 100644 --- a/reactos/ntoskrnl/ps/w32call.c +++ b/reactos/ntoskrnl/ps/w32call.c @@ -1,4 +1,4 @@ -/* $Id: w32call.c,v 1.21 2004/11/28 18:14:02 blight Exp $ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -163,11 +163,10 @@ VOID STATIC PsFreeCallbackStack(PVOID StackLimit) { MmLockAddressSpace(MmGetKernelAddressSpace()); - MmFreeMemoryArea(MmGetKernelAddressSpace(), - StackLimit, - MM_STACK_SIZE, - PsFreeCallbackStackPage, - NULL); + MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(), + StackLimit, + PsFreeCallbackStackPage, + NULL); MmUnlockAddressSpace(MmGetKernelAddressSpace()); }