ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
April 2021
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
21 participants
173 discussions
Start a n
N
ew thread
[reactos] 05/12: [NTOS:MM] Rewrite arch-specifics of the legacy Mm
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=43378411fb258a02d3384…
commit 43378411fb258a02d3384acb3e301eb1774a119a Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Mon Mar 22 09:52:11 2021 +0100 Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com> CommitDate: Thu Apr 8 15:40:37 2021 +0200 [NTOS:MM] Rewrite arch-specifics of the legacy Mm Properly handle PDE refcounting Clean-up of the internal API Enforce attaching to the process when modifying its memory layout, instead of making circonvoluted mappings which always end up being broken. --- ntoskrnl/include/internal/mm.h | 48 +-- ntoskrnl/mm/i386/page.c | 843 +++++++++++++++++++---------------------- ntoskrnl/mm/marea.c | 18 - ntoskrnl/mm/rmap.c | 30 +- ntoskrnl/mm/section.c | 17 +- 5 files changed, 429 insertions(+), 527 deletions(-) diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index 93c44e5bd05..d2cb0123bed 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -1034,8 +1034,7 @@ MmCreateVirtualMapping( struct _EPROCESS* Process, PVOID Address, ULONG flProtect, - PPFN_NUMBER Pages, - ULONG PageCount + PFN_NUMBER Page ); NTSTATUS @@ -1044,8 +1043,7 @@ MmCreateVirtualMappingUnsafe( struct _EPROCESS* Process, PVOID Address, ULONG flProtect, - PPFN_NUMBER Pages, - ULONG PageCount + PFN_NUMBER Page ); ULONG @@ -1080,13 +1078,6 @@ VOID NTAPI MmInitGlobalKernelPageDirectory(VOID); -VOID -NTAPI -MmGetPageFileMapping( - struct _EPROCESS *Process, - PVOID Address, - SWAPENTRY* SwapEntry); - VOID NTAPI MmDeletePageFileMapping( @@ -1103,16 +1094,16 @@ MmCreatePageFileMapping( SWAPENTRY SwapEntry ); -BOOLEAN +VOID NTAPI -MmIsPageSwapEntry( - struct _EPROCESS *Process, - PVOID Address -); +MmGetPageFileMapping( + PEPROCESS Process, + PVOID Address, + SWAPENTRY *SwapEntry); -VOID +BOOLEAN NTAPI -MmSetDirtyPage( +MmIsPageSwapEntry( struct _EPROCESS *Process, PVOID Address ); @@ -1156,6 +1147,12 @@ MmSetCleanPage( PVOID Address ); +VOID +NTAPI +MmSetDirtyBit(PEPROCESS Process, PVOID Address, BOOLEAN Bit); +#define MmSetCleanPage(__P, __A) MmSetDirtyBit(__P, __A, FALSE) +#define MmSetDirtyPage(__P, __A) MmSetDirtyBit(__P, __A, TRUE) + VOID NTAPI MmDeletePageTable( @@ -1208,21 +1205,6 @@ MmDeleteVirtualMapping( PPFN_NUMBER Page ); -BOOLEAN -NTAPI -MmIsDirtyPage( - struct _EPROCESS *Process, - PVOID Address -); - -VOID -NTAPI -MmClearPageAccessedBit(PEPROCESS Process, PVOID Address); - -BOOLEAN -NTAPI -MmIsPageAccessed(PEPROCESS Process, PVOID Address); - /* wset.c ********************************************************************/ NTSTATUS diff --git a/ntoskrnl/mm/i386/page.c b/ntoskrnl/mm/i386/page.c index e1aac494dcb..35b0921d0ae 100644 --- a/ntoskrnl/mm/i386/page.c +++ b/ntoskrnl/mm/i386/page.c @@ -134,17 +134,6 @@ ULONG MmProtectToValue[32] = /* FUNCTIONS ***************************************************************/ -static BOOLEAN MmUnmapPageTable(PULONG Pt, KIRQL OldIrql); - -VOID -MiFlushTlb(PULONG Pt, PVOID Address, KIRQL OldIrql) -{ - if ((Pt && MmUnmapPageTable(Pt, OldIrql)) || Address >= MmSystemRangeStart) - { - KeInvalidateTlbEntry(Address); - } -} - static ULONG ProtectToPTE(ULONG flProtect) { @@ -191,120 +180,38 @@ NTAPI MiFillSystemPageDirectory(IN PVOID Base, IN SIZE_T NumberOfBytes); -static PULONG -MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create, PKIRQL OldIrql) +PFN_NUMBER +NTAPI +MmGetPfnForProcess(PEPROCESS Process, + PVOID Address) { - PFN_NUMBER Pfn; - PULONG Pt; - PMMPDE PointerPde; - - if (Address < MmSystemRangeStart) - { - /* We should have a process for user land addresses */ - ASSERT(Process != NULL); + PMMPTE PointerPte; + PFN_NUMBER Page; - if(Process != PsGetCurrentProcess()) - { - PMMPDE PdeBase; - ULONG PdeOffset = MiGetPdeOffset(Address); - - ASSERT(!Create); - - PdeBase = MiMapPageInHyperSpace(PsGetCurrentProcess(), - PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]), - OldIrql); - if (PdeBase == NULL) - { - KeBugCheck(MEMORY_MANAGEMENT); - } - PointerPde = PdeBase + PdeOffset; - if (PointerPde->u.Hard.Valid == 0) - { - MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PdeBase, *OldIrql); - return NULL; - } - - Pfn = PointerPde->u.Hard.PageFrameNumber; - MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PdeBase, *OldIrql); - Pt = MiMapPageInHyperSpace(PsGetCurrentProcess(), Pfn, OldIrql); - if (Pt == NULL) - { - KeBugCheck(MEMORY_MANAGEMENT); - } - return Pt + MiAddressToPteOffset(Address); - } + /* Must be called for user mode only */ + ASSERT(Process != NULL); + ASSERT(Address < MmSystemRangeStart); - /* This is for our process */ - PointerPde = MiAddressToPde(Address); - Pt = (PULONG)MiAddressToPte(Address); + /* And for our process */ + ASSERT(Process == PsGetCurrentProcess()); - if ((PointerPde->u.Hard.Valid == 0) && (Create == FALSE)) - { - /* Do not fault PDE in if not needed */ - return NULL; - } + /* Lock for reading */ + MiLockProcessWorkingSetShared(Process, PsGetCurrentThread()); - return (PULONG)MiAddressToPte(Address); - } - - /* This is for kernel land address */ - ASSERT(Process == NULL); - PointerPde = MiAddressToPde(Address); - Pt = (PULONG)MiAddressToPte(Address); - if (PointerPde->u.Hard.Valid == 0) + if (MiQueryPageTableReferences(Address) == 0) { - /* Let ARM3 synchronize the PDE */ - if(!MiSynchronizeSystemPde(PointerPde)) - { - /* PDE (still) not valid, let ARM3 allocate one if asked */ - if(Create == FALSE) - return NULL; - MiFillSystemPageDirectory(Address, PAGE_SIZE); - } - } - return Pt; -} - -static BOOLEAN MmUnmapPageTable(PULONG Pt, KIRQL OldIrql) -{ - if (!IS_HYPERSPACE(Pt)) - { - return TRUE; + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + return 0; } - MiUnmapPageInHyperSpace(PsGetCurrentProcess(), Pt, OldIrql); - - return FALSE; -} - -static ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address) -{ - ULONG Pte; - PULONG Pt; - KIRQL OldIrql; + /* Make sure we can read the PTE */ + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); - Pt = MmGetPageTableForProcess(Process, Address, FALSE, &OldIrql); - if (Pt) - { - Pte = *Pt; - MmUnmapPageTable(Pt, OldIrql); - return Pte; - } - return 0; -} + PointerPte = MiAddressToPte(Address); + Page = PointerPte->u.Hard.Valid ? PFN_FROM_PTE(PointerPte) : 0; -PFN_NUMBER -NTAPI -MmGetPfnForProcess(PEPROCESS Process, - PVOID Address) -{ - ULONG Entry; - Entry = MmGetPageEntryForProcess(Process, Address); - if (!(Entry & PA_PRESENT)) - { - return 0; - } - return(PTE_TO_PFN(Entry)); + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + return Page; } VOID @@ -315,130 +222,150 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, * FUNCTION: Delete a virtual mapping */ { - BOOLEAN WasValid = FALSE; - PFN_NUMBER Pfn; + PMMPTE PointerPte; ULONG Pte; - PULONG Pt; - KIRQL OldIrql; - DPRINT("MmDeleteVirtualMapping(%p, %p, %p, %p)\n", - Process, Address, WasDirty, Page); + DPRINT("MmDeleteVirtualMapping(%p, %p, %p, %p)\n", Process, Address, WasDirty, Page); + + ASSERT(((ULONG_PTR)Address % PAGE_SIZE) == 0); - Pt = MmGetPageTableForProcess(Process, Address, FALSE, &OldIrql); + /* And we should be at low IRQL */ + ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); - if (Pt == NULL) + /* Make sure our PDE is valid, and that everything is going fine */ + if (Process == NULL) { - if (WasDirty != NULL) + if (Address < MmSystemRangeStart) { - *WasDirty = FALSE; + DPRINT1("NULL process given for user-mode mapping at %p\n", Address); + KeBugCheck(MEMORY_MANAGEMENT); } - if (Page != NULL) + + if (!MiSynchronizeSystemPde(MiAddressToPde(Address))) { - *Page = 0; + /* There can't be a page if there is no PDE */ + if (WasDirty) + *WasDirty = FALSE; + if (Page) + *Page = 0; + return; } - return; } - - /* - * Atomically set the entry to zero and get the old value. - */ - Pte = InterlockedExchangePte(Pt, 0); - - /* We count a mapping as valid if it's a present page, or it's a nonzero pfn with - * the swap bit unset, indicating a valid page protected to PAGE_NOACCESS. */ - WasValid = (Pte & PA_PRESENT) || ((Pte >> PAGE_SHIFT) && !(Pte & 0x800)); - if (WasValid) + else { - /* Flush the TLB since we transitioned this PTE - * from valid to invalid so any stale translations - * are removed from the cache */ - MiFlushTlb(Pt, Address, OldIrql); + if ((Address >= MmSystemRangeStart) || Add2Ptr(Address, PAGE_SIZE) >= MmSystemRangeStart) + { + DPRINT1("Process %p given for kernel-mode mapping at %p -- %lu pages starting at %Ix\n", Process, Address); + KeBugCheck(MEMORY_MANAGEMENT); + } - if (Address < MmSystemRangeStart) - { - /* Remove PDE reference */ - Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--; - ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_PER_PAGE); - } + /* Only for current process !!! */ + ASSERT(Process = PsGetCurrentProcess()); + MiLockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); - Pfn = PTE_TO_PFN(Pte); - } - else - { - MmUnmapPageTable(Pt, OldIrql); - Pfn = 0; + /* No PDE --> No page */ + if (MiQueryPageTableReferences(Address) == 0) + { + MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); + if (WasDirty) + *WasDirty = 0; + if (Page) + *Page = 0; + return; + } + + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); } - /* - * Return some information to the caller - */ - if (WasDirty != NULL) + PointerPte = MiAddressToPte(Address); + Pte = InterlockedExchangePte(PointerPte, 0); + + if (Pte == 0) { - *WasDirty = ((Pte & PA_DIRTY) && (Pte & PA_PRESENT)) ? TRUE : FALSE; + /* There was nothing here */ + if (Address < MmSystemRangeStart) + MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); + if (WasDirty) + *WasDirty = 0; + if (Page) + *Page = 0; + return; } - if (Page != NULL) + + /* It must have been present, or not a swap entry */ + ASSERT(FlagOn(Pte, PA_PRESENT) || !FlagOn(Pte, 0x800)); + + if (FlagOn(Pte, PA_PRESENT)) + KeInvalidateTlbEntry(Address); + + if (Address < MmSystemRangeStart) { - *Page = Pfn; + /* Remove PDE reference */ + MiDecrementPageTableReferences(Address); + if (MiQueryPageTableReferences(Address) == 0) + { + KIRQL OldIrql = MiAcquirePfnLock(); + MiDeletePte(MiAddressToPte(PointerPte), PointerPte, Process, NULL); + MiReleasePfnLock(OldIrql); + } + + MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); } -} -VOID -NTAPI -MmGetPageFileMapping(PEPROCESS Process, PVOID Address, - SWAPENTRY* SwapEntry) -/* - * FUNCTION: Get a page file mapping - */ -{ - ULONG Entry = MmGetPageEntryForProcess(Process, Address); - *SwapEntry = Entry >> 1; + if (WasDirty) + *WasDirty = FlagOn(Pte, PA_DIRTY); + if (Page) + *Page = PTE_TO_PFN(Pte); } + VOID NTAPI -MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, - SWAPENTRY* SwapEntry) -/* - * FUNCTION: Delete a virtual mapping - */ +MmDeletePageFileMapping( + PEPROCESS Process, + PVOID Address, + SWAPENTRY* SwapEntry) { + PMMPTE PointerPte; ULONG Pte; - PULONG Pt; - KIRQL OldIrql; - Pt = MmGetPageTableForProcess(Process, Address, FALSE, &OldIrql); + /* This should not be called for kernel space anymore */ + ASSERT(Process != NULL); + ASSERT(Address < MmSystemRangeStart); - if (Pt == NULL) - { - *SwapEntry = 0; - return; - } + /* And we don't support deleting for other process */ + ASSERT(Process == PsGetCurrentProcess()); - /* - * Atomically set the entry to zero and get the old value. - */ - Pte = InterlockedExchangePte(Pt, 0); + /* And we should be at low IRQL */ + ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); - if (Address < MmSystemRangeStart) - { - /* Remove PDE reference */ - Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--; - ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_PER_PAGE); - } + /* We are tinkering with the PDE here. Ensure it will be there */ + MiLockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); - /* We don't need to flush here because page file entries - * are invalid translations, so the processor won't cache them */ - MmUnmapPageTable(Pt, OldIrql); + /* Callers must ensure there is actually something there */ + ASSERT(MiAddressToPde(Address)->u.Long != 0); - if ((Pte & PA_PRESENT) || !(Pte & 0x800)) + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); + + PointerPte = MiAddressToPte(Address); + Pte = InterlockedExchangePte(PointerPte, 0); + if (!FlagOn(Pte, 0x800) || FlagOn(Pte, PA_PRESENT)) { - DPRINT1("Pte %x (want not 1 and 0x800)\n", Pte); - KeBugCheck(MEMORY_MANAGEMENT); + KeBugCheckEx(MEMORY_MANAGEMENT, Pte, (ULONG_PTR)Process, (ULONG_PTR)Address, 0); } - /* - * Return some information to the caller - */ + /* This used to be a non-zero PTE, now we can let the PDE go. */ + MiDecrementPageTableReferences(Address); + if (MiQueryPageTableReferences(Address) == 0) + { + /* We can let it go */ + KIRQL OldIrql = MiAcquirePfnLock(); + MiDeletePte(MiAddressToPte(PointerPte), PointerPte, Process, NULL); + MiReleasePfnLock(OldIrql); + } + + MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); + *SwapEntry = Pte >> 1; } @@ -459,149 +386,160 @@ Mmi386MakeKernelPageTableGlobal(PVOID Address) BOOLEAN NTAPI -MmIsDirtyPage(PEPROCESS Process, PVOID Address) +MmIsPagePresent(PEPROCESS Process, PVOID Address) { - return MmGetPageEntryForProcess(Process, Address) & PA_DIRTY ? TRUE : FALSE; -} + BOOLEAN Ret; -VOID -NTAPI -MmSetCleanPage(PEPROCESS Process, PVOID Address) -{ - PULONG Pt; - ULONG Pte; - KIRQL OldIrql; - - if (Address < MmSystemRangeStart && Process == NULL) + if (Address >= MmSystemRangeStart) { - DPRINT1("MmSetCleanPage is called for user space without a process.\n"); - KeBugCheck(MEMORY_MANAGEMENT); - } + ASSERT(Process == NULL); + if (!MiSynchronizeSystemPde(MiAddressToPde(Address))) + { + /* It can't be present if there is no PDE */ + return FALSE; + } - Pt = MmGetPageTableForProcess(Process, Address, FALSE, &OldIrql); - if (Pt == NULL) - { - KeBugCheck(MEMORY_MANAGEMENT); + return MiAddressToPte(Address)->u.Hard.Valid; } - do - { - Pte = *Pt; - } while (Pte != InterlockedCompareExchangePte(Pt, Pte & ~PA_DIRTY, Pte)); + ASSERT(Process != NULL); + ASSERT(Process == PsGetCurrentProcess()); - if (!(Pte & PA_PRESENT)) + MiLockProcessWorkingSetShared(Process, PsGetCurrentThread()); + + if (MiQueryPageTableReferences(Address) == 0) { - KeBugCheck(MEMORY_MANAGEMENT); + /* It can't be present if there is no PDE */ + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + return FALSE; } - else if (Pte & PA_DIRTY) + + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); + + Ret = MiAddressToPte(Address)->u.Hard.Valid; + + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + + return Ret; +} + +BOOLEAN +NTAPI +MmIsDisabledPage(PEPROCESS Process, PVOID Address) +{ + BOOLEAN Ret; + ULONG Pte; + + if (Address >= MmSystemRangeStart) { - MiFlushTlb(Pt, Address, OldIrql); + ASSERT(Process == NULL); + if (!MiSynchronizeSystemPde(MiAddressToPde(Address))) + { + /* It's not disabled if it's not present */ + return FALSE; + } + + Pte = MiAddressToPte(Address)->u.Long; } else { - MmUnmapPageTable(Pt, OldIrql); + ASSERT(Process != NULL); + ASSERT(Process == PsGetCurrentProcess()); + + MiLockProcessWorkingSetShared(Process, PsGetCurrentThread()); + + if (MiQueryPageTableReferences(Address) == 0) + { + /* It can't be disabled if there is no PDE */ + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + return FALSE; + } + + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); + + Pte = MiAddressToPte(Address)->u.Long; } + + Ret = !FlagOn(Pte, PA_PRESENT) && !FlagOn(Pte, 0x800) && (PAGE_MASK(Pte) != 0); + + if (Address < MmSystemRangeStart) + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + + return Ret; } -VOID +BOOLEAN NTAPI -MmSetDirtyPage(PEPROCESS Process, PVOID Address) +MmIsPageSwapEntry(PEPROCESS Process, PVOID Address) { - PULONG Pt; + BOOLEAN Ret; ULONG Pte; - KIRQL OldIrql; - if (Address < MmSystemRangeStart && Process == NULL) + /* We never set swap entries for kernel addresses */ + if (Address >= MmSystemRangeStart) { - DPRINT1("MmSetDirtyPage is called for user space without a process.\n"); - KeBugCheck(MEMORY_MANAGEMENT); + ASSERT(Process == NULL); + return FALSE; } - Pt = MmGetPageTableForProcess(Process, Address, FALSE, &OldIrql); - if (Pt == NULL) - { - KeBugCheck(MEMORY_MANAGEMENT); - } + ASSERT(Process != NULL); + ASSERT(Process == PsGetCurrentProcess()); - do - { - Pte = *Pt; - } while (Pte != InterlockedCompareExchangePte(Pt, Pte | PA_DIRTY, Pte)); + MiLockProcessWorkingSetShared(Process, PsGetCurrentThread()); - if (!(Pte & PA_PRESENT)) + if (MiQueryPageTableReferences(Address) == 0) { - KeBugCheck(MEMORY_MANAGEMENT); - } - else - { - /* The processor will never clear this bit itself, therefore - * we do not need to flush the TLB here when setting it */ - MmUnmapPageTable(Pt, OldIrql); + /* There can't be a swap entry if there is no PDE */ + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + return FALSE; } + + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); + + Pte = MiAddressToPte(Address)->u.Long; + Ret = !FlagOn(Pte, PA_PRESENT) && FlagOn(Pte, 0x800); + + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + + return Ret; } VOID NTAPI -MmClearPageAccessedBit(PEPROCESS Process, PVOID Address) +MmGetPageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY* SwapEntry) { - PULONG Pt; - LONG Pte; - KIRQL OldIrql; + ULONG Pte; - if (Address < MmSystemRangeStart && Process == NULL) + /* We never set swap entries for kernel addresses */ + if (Address >= MmSystemRangeStart) { - DPRINT1("MmClearPageAccessedBit is called for user space without a process.\n"); - KeBugCheck(MEMORY_MANAGEMENT); + ASSERT(Process == NULL); + *SwapEntry = 0; + return; } - Pt = MmGetPageTableForProcess(Process, Address, FALSE, &OldIrql); - if (Pt == NULL) - { - KeBugCheck(MEMORY_MANAGEMENT); - } + ASSERT(Process != NULL); + ASSERT(Process == PsGetCurrentProcess()); - do - { - Pte = *Pt; - } while (Pte != InterlockedCompareExchangePte(Pt, Pte & ~PA_ACCESSED, Pte)); + MiLockProcessWorkingSetShared(Process, PsGetCurrentThread()); - if (!(Pte & PA_PRESENT)) + if (MiQueryPageTableReferences(Address) == 0) { - KeBugCheck(MEMORY_MANAGEMENT); + /* There can't be a swap entry if there is no PDE */ + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + *SwapEntry = 0; + return; } - MiFlushTlb(Pt, Address, OldIrql); -} + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); -BOOLEAN -NTAPI -MmIsPageAccessed(PEPROCESS Process, PVOID Address) -{ - return BooleanFlagOn(MmGetPageEntryForProcess(Process, Address), PA_ACCESSED); -} - -BOOLEAN -NTAPI -MmIsPagePresent(PEPROCESS Process, PVOID Address) -{ - return MmGetPageEntryForProcess(Process, Address) & PA_PRESENT; -} - -BOOLEAN -NTAPI -MmIsDisabledPage(PEPROCESS Process, PVOID Address) -{ - ULONG_PTR Entry = MmGetPageEntryForProcess(Process, Address); - return !(Entry & PA_PRESENT) && !(Entry & 0x800) && (Entry >> PAGE_SHIFT); -} + Pte = MiAddressToPte(Address)->u.Long; + if (!FlagOn(Pte, PA_PRESENT) && FlagOn(Pte, 0x800)) + *SwapEntry = Pte >> 1; + else + *SwapEntry = 0; -BOOLEAN -NTAPI -MmIsPageSwapEntry(PEPROCESS Process, PVOID Address) -{ - ULONG Entry; - Entry = MmGetPageEntryForProcess(Process, Address); - return !(Entry & PA_PRESENT) && (Entry & 0x800); + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); } NTSTATUS @@ -610,56 +548,39 @@ MmCreatePageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY SwapEntry) { - PULONG Pt; + PMMPTE PointerPte; ULONG Pte; - KIRQL OldIrql; - if (Process == NULL && Address < MmSystemRangeStart) - { - DPRINT1("No process\n"); - KeBugCheck(MEMORY_MANAGEMENT); - } - if (Process != NULL && Address >= MmSystemRangeStart) - { - DPRINT1("Setting kernel address with process context\n"); - KeBugCheck(MEMORY_MANAGEMENT); - } + /* This should not be called for kernel space anymore */ + ASSERT(Process != NULL); + ASSERT(Address < MmSystemRangeStart); + + /* And we don't support creating for other process */ + ASSERT(Process == PsGetCurrentProcess()); if (SwapEntry & (1 << 31)) { KeBugCheck(MEMORY_MANAGEMENT); } - Pt = MmGetPageTableForProcess(Process, Address, FALSE, &OldIrql); - if (Pt == NULL) - { - /* Nobody should page out an address that hasn't even been mapped */ - /* But we might place a wait entry first, requiring the page table */ - if (SwapEntry != MM_WAIT_ENTRY) - { - KeBugCheck(MEMORY_MANAGEMENT); - } - Pt = MmGetPageTableForProcess(Process, Address, TRUE, &OldIrql); - } - Pte = InterlockedExchangePte(Pt, SwapEntry << 1); + /* We are tinkering with the PDE here. Ensure it will be there */ + ASSERT(Process == PsGetCurrentProcess()); + MiLockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); + + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); + + PointerPte = MiAddressToPte(Address); + Pte = InterlockedExchangePte(PointerPte, SwapEntry << 1); if (Pte != 0) { KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0); } - if (Address < MmSystemRangeStart) - { - /* Add PDE reference */ - Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++; - ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_PER_PAGE); - } + /* This used to be a 0 PTE, now we need a valid PDE to keep it around */ + MiIncrementPageTableReferences(Address); + MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); - /* We don't need to flush the TLB here because it - * only caches valid translations and a zero PTE - * is not a valid translation */ - MmUnmapPageTable(Pt, OldIrql); - - return(STATUS_SUCCESS); + return STATUS_SUCCESS; } @@ -668,50 +589,41 @@ NTAPI MmCreateVirtualMappingUnsafe(PEPROCESS Process, PVOID Address, ULONG flProtect, - PPFN_NUMBER Pages, - ULONG PageCount) + PFN_NUMBER Page) { ULONG Attributes; - PVOID Addr; - ULONG i; - ULONG oldPdeOffset, PdeOffset; - PULONG Pt = NULL; + PMMPTE PointerPte; ULONG Pte; - KIRQL OldIrql; - DPRINT("MmCreateVirtualMappingUnsafe(%p, %p, %lu, %p (%x), %lu)\n", - Process, Address, flProtect, Pages, *Pages, PageCount); + DPRINT("MmCreateVirtualMappingUnsafe(%p, %p, %lu, %x)\n", + Process, Address, flProtect, Page); ASSERT(((ULONG_PTR)Address % PAGE_SIZE) == 0); + /* Make sure our PDE is valid, and that everything is going fine */ if (Process == NULL) { if (Address < MmSystemRangeStart) { - DPRINT1("NULL process given for user-mode mapping at %p -- %lu pages starting at %Ix\n", Address, PageCount, *Pages); - KeBugCheck(MEMORY_MANAGEMENT); - } - if (PageCount > 0x10000 || - (ULONG_PTR) Address / PAGE_SIZE + PageCount > 0x100000) - { - DPRINT1("Page count too large for kernel-mode mapping at %p -- %lu pages starting at %Ix\n", Address, PageCount, *Pages); + DPRINT1("NULL process given for user-mode mapping at %p\n", Address); KeBugCheck(MEMORY_MANAGEMENT); } + if (!MiSynchronizeSystemPde(MiAddressToPde(Address))) + MiFillSystemPageDirectory(Address, PAGE_SIZE); } else { - if (Address >= MmSystemRangeStart) + if ((Address >= MmSystemRangeStart) || Add2Ptr(Address, PAGE_SIZE) >= MmSystemRangeStart) { - DPRINT1("Process %p given for kernel-mode mapping at %p -- %lu pages starting at %Ix\n", Process, Address, PageCount, *Pages); - KeBugCheck(MEMORY_MANAGEMENT); - } - if (PageCount > (ULONG_PTR)MmSystemRangeStart / PAGE_SIZE || - (ULONG_PTR) Address / PAGE_SIZE + PageCount > - (ULONG_PTR)MmSystemRangeStart / PAGE_SIZE) - { - DPRINT1("Page count too large for process %p user-mode mapping at %p -- %lu pages starting at %Ix\n", Process, Address, PageCount, *Pages); + DPRINT1("Process %p given for kernel-mode mapping at %p -- %lu pages starting at %Ix\n", Process, Address); KeBugCheck(MEMORY_MANAGEMENT); } + + /* Only for current process !!! */ + ASSERT(Process = PsGetCurrentProcess()); + MiLockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); + + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); } Attributes = ProtectToPTE(flProtect); @@ -725,58 +637,28 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process, Attributes |= PA_USER; } - Addr = Address; - /* MmGetPageTableForProcess should be called on the first run, so - * let this trigger it */ - oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr) + 1; - for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE)) - { - if (!(Attributes & PA_PRESENT) && Pages[i] != 0) - { - DPRINT1("Setting physical address but not allowing access at address " - "0x%p with attributes %x/%x.\n", - Addr, Attributes, flProtect); - KeBugCheck(MEMORY_MANAGEMENT); - } - PdeOffset = ADDR_TO_PDE_OFFSET(Addr); - if (oldPdeOffset != PdeOffset) - { - if(Pt) MmUnmapPageTable(Pt, OldIrql); - Pt = MmGetPageTableForProcess(Process, Addr, TRUE, &OldIrql); - if (Pt == NULL) - { - KeBugCheck(MEMORY_MANAGEMENT); - } - } - else - { - Pt++; - } - oldPdeOffset = PdeOffset; - - Pte = InterlockedExchangePte(Pt, PFN_TO_PTE(Pages[i]) | Attributes); + /* This must be for a valid address */ + ASSERT(FlagOn(Attributes, PA_PRESENT)); - /* There should not be anything valid here */ - if (Pte != 0) - { - DPRINT1("Bad PTE %lx at %p for %p + %lu\n", Pte, Pt, Address, i); - KeBugCheck(MEMORY_MANAGEMENT); - } + PointerPte = MiAddressToPte(Address); + Pte = InterlockedExchangePte(PointerPte, PFN_TO_PTE(Page) | Attributes); + /* There should not have been anything valid here */ + if (Pte != 0) + { + DPRINT1("Bad PTE %lx at %p for %p\n", Pte, PointerPte, Address); + KeBugCheck(MEMORY_MANAGEMENT); + } - /* We don't need to flush the TLB here because it only caches valid translations - * and we're moving this PTE from invalid to valid so it can't be cached right now */ + /* We don't need to flush the TLB here because it only caches valid translations + * and we're moving this PTE from invalid to valid so it can't be cached right now */ - if (Addr < MmSystemRangeStart) - { - /* Add PDE reference */ - Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Addr)]++; - ASSERT(Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Addr)] <= PTE_PER_PAGE); - } + if (Address < MmSystemRangeStart) + { + /* Add PDE reference */ + MiIncrementPageTableReferences(Address); + MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); } - ASSERT(Addr > Address); - MmUnmapPageTable(Pt, OldIrql); - return(STATUS_SUCCESS); } @@ -785,45 +667,60 @@ NTAPI MmCreateVirtualMapping(PEPROCESS Process, PVOID Address, ULONG flProtect, - PPFN_NUMBER Pages, - ULONG PageCount) + PFN_NUMBER Page) { - ULONG i; - ASSERT((ULONG_PTR)Address % PAGE_SIZE == 0); - for (i = 0; i < PageCount; i++) + if (!MmIsPageInUse(Page)) { - if (!MmIsPageInUse(Pages[i])) - { - DPRINT1("Page at address %x not in use\n", PFN_TO_PTE(Pages[i])); - KeBugCheck(MEMORY_MANAGEMENT); - } + DPRINT1("Page at address %x not in use\n", PFN_TO_PTE(Page)); + KeBugCheck(MEMORY_MANAGEMENT); } - return(MmCreateVirtualMappingUnsafe(Process, - Address, - flProtect, - Pages, - PageCount)); + return MmCreateVirtualMappingUnsafe(Process, Address, flProtect, Page); } ULONG NTAPI MmGetPageProtect(PEPROCESS Process, PVOID Address) { - ULONG Entry; + ULONG_PTR Pte; ULONG Protect; - Entry = MmGetPageEntryForProcess(Process, Address); + if (Address >= MmSystemRangeStart) + { + ASSERT(Process == NULL); + + if (!MiSynchronizeSystemPde(MiAddressToPde(Address))) + return PAGE_NOACCESS; + } + else + { + ASSERT(Address < MmSystemRangeStart); + ASSERT(Process != NULL); + + ASSERT(Process == PsGetCurrentProcess()); + MiLockProcessWorkingSetShared(Process, PsGetCurrentThread()); - if (!(Entry & PA_PRESENT)) + if (MiQueryPageTableReferences(Address) == 0) + { + /* It can't be present if there is no PDE */ + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + return PAGE_NOACCESS; + } + + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); + } + + Pte = MiAddressToPte(Address)->u.Long; + + if (!(Pte & PA_PRESENT)) { Protect = PAGE_NOACCESS; } else { - if (Entry & PA_READWRITE) + if (Pte & PA_READWRITE) { Protect = PAGE_READWRITE; } @@ -831,20 +728,23 @@ MmGetPageProtect(PEPROCESS Process, PVOID Address) { Protect = PAGE_EXECUTE_READ; } - if (Entry & PA_CD) + if (Pte & PA_CD) { Protect |= PAGE_NOCACHE; } - if (Entry & PA_WT) + if (Pte & PA_WT) { Protect |= PAGE_WRITETHROUGH; } - if (!(Entry & PA_USER)) + if (!(Pte & PA_USER)) { Protect |= PAGE_SYSTEM; } - } + + if (Address < MmSystemRangeStart) + MiUnlockProcessWorkingSetShared(Process, PsGetCurrentThread()); + return(Protect); } @@ -853,43 +753,80 @@ NTAPI MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect) { ULONG Attributes = 0; - PULONG Pt; + PMMPTE PointerPte; ULONG Pte; - KIRQL OldIrql; DPRINT("MmSetPageProtect(Process %p Address %p flProtect %x)\n", Process, Address, flProtect); + ASSERT(Process != NULL); + ASSERT(Address < MmSystemRangeStart); + + ASSERT(Process == PsGetCurrentProcess()); + + MiLockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); + + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); + Attributes = ProtectToPTE(flProtect); Attributes &= 0xfff; - if (Address >= MmSystemRangeStart) - { - Attributes &= ~PA_USER; - } - else - { - Attributes |= PA_USER; - } + Attributes |= PA_USER; + + PointerPte = MiAddressToPte(Address); + Pte = InterlockedExchangePte(PointerPte, PAGE_MASK(PointerPte->u.Long) | Attributes | (PointerPte->u.Long & (PA_ACCESSED|PA_DIRTY))); - Pt = MmGetPageTableForProcess(Process, Address, FALSE, &OldIrql); - if (Pt == NULL) + // We should be able to bring a page back from PAGE_NOACCESS + if ((Pte & 0x800) || !(Pte >> PAGE_SHIFT)) { + DPRINT1("Invalid Pte %lx\n", Pte); KeBugCheck(MEMORY_MANAGEMENT); } - Pte = InterlockedExchangePte(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY))); - // We should be able to bring a page back from PAGE_NOACCESS + if ((Pte & 0xFFF) != Attributes) + KeInvalidateTlbEntry(Address); + + MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); +} + +VOID +NTAPI +MmSetDirtyBit(PEPROCESS Process, PVOID Address, BOOLEAN Bit) +{ + PMMPTE PointerPte; + ULONG Pte; + + DPRINT("MmSetDirtyBit(Process %p Address %p Bit %x)\n", + Process, Address, Bit); + + ASSERT(Process != NULL); + ASSERT(Address < MmSystemRangeStart); + + ASSERT(Process == PsGetCurrentProcess()); + + MiLockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); + + MiMakePdeExistAndMakeValid(MiAddressToPde(Address), Process, MM_NOIRQL); + + PointerPte = MiAddressToPte(Address); + Pte = PointerPte->u.Long; + if (Bit) + Pte |= PA_DIRTY; + else + Pte &= ~PA_DIRTY; + Pte = InterlockedExchangePte(PointerPte, Pte); + + // We shouldnl't set dirty bit on non-mapped adresses if ((Pte & 0x800) || !(Pte >> PAGE_SHIFT)) { DPRINT1("Invalid Pte %lx\n", Pte); KeBugCheck(MEMORY_MANAGEMENT); } - if((Pte & Attributes) != Attributes) - MiFlushTlb(Pt, Address, OldIrql); - else - MmUnmapPageTable(Pt, OldIrql); + if (!Bit) + KeInvalidateTlbEntry(Address); + + MiUnlockProcessWorkingSetUnsafe(Process, PsGetCurrentThread()); } CODE_SEG("INIT") diff --git a/ntoskrnl/mm/marea.c b/ntoskrnl/mm/marea.c index 92eebc173cb..1942dd76b27 100644 --- a/ntoskrnl/mm/marea.c +++ b/ntoskrnl/mm/marea.c @@ -328,24 +328,6 @@ MmFreeMemoryArea( FreePage(FreePageContext, MemoryArea, (PVOID)Address, Page, SwapEntry, (BOOLEAN)Dirty); } -#if (_MI_PAGING_LEVELS == 2) - /* Remove page table reference */ - ASSERT(KeGetCurrentIrql() <= APC_LEVEL); - if ((SwapEntry || Page) && ((PVOID)Address < MmSystemRangeStart)) - { - ASSERT(AddressSpace != MmGetKernelAddressSpace()); - if (MiQueryPageTableReferences((PVOID)Address) == 0) - { - /* No PTE relies on this PDE. Release it */ - KIRQL OldIrql = MiAcquirePfnLock(); - PMMPDE PointerPde = MiAddressToPde(Address); - ASSERT(PointerPde->u.Hard.Valid == 1); - MiDeletePte(PointerPde, MiPdeToPte(PointerPde), Process, NULL); - ASSERT(PointerPde->u.Hard.Valid == 0); - MiReleasePfnLock(OldIrql); - } - } -#endif } if (Process != NULL && diff --git a/ntoskrnl/mm/rmap.c b/ntoskrnl/mm/rmap.c index c680a8f7a9f..64758cc5b89 100644 --- a/ntoskrnl/mm/rmap.c +++ b/ntoskrnl/mm/rmap.c @@ -102,18 +102,26 @@ GetEntry: MmLockAddressSpace(AddressSpace); - if (MmGetPfnForProcess(Process, Address) != Page) + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address); + if (MemoryArea == NULL || MemoryArea->DeleteInProgress) { - /* This changed in the short window where we didn't have any locks */ MmUnlockAddressSpace(AddressSpace); ExReleaseRundownProtection(&Process->RundownProtect); ObDereferenceObject(Process); goto GetEntry; } - MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address); - if (MemoryArea == NULL || MemoryArea->DeleteInProgress) + + /* Attach to it, if needed */ + ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess); + if (Process != PsInitialSystemProcess) + KeAttachProcess(&Process->Pcb); + + if (MmGetPfnForProcess(Process, Address) != Page) { + /* This changed in the short window where we didn't have any locks */ + if (Process != PsInitialSystemProcess) + KeDetachProcess(); MmUnlockAddressSpace(AddressSpace); ExReleaseRundownProtection(&Process->RundownProtect); ObDereferenceObject(Process); @@ -140,6 +148,8 @@ GetEntry: { /* The segment is being read or something. Give up */ MmUnlockSectionSegment(Segment); + if (Process != PsInitialSystemProcess) + KeDetachProcess(); MmUnlockAddressSpace(AddressSpace); ExReleaseRundownProtection(&Process->RundownProtect); ObDereferenceObject(Process); @@ -160,11 +170,6 @@ GetEntry: /* This page is private to the process */ MmUnlockSectionSegment(Segment); - /* Attach to it, if needed */ - ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess); - if (Process != PsInitialSystemProcess) - KeAttachProcess(&Process->Pcb); - /* Check if we should write it back to the page file */ SwapEntry = MmGetSavedSwapEntryPage(Page); @@ -179,7 +184,7 @@ GetEntry: Address, NULL); /* We can't, so let this page in the Process VM */ - MmCreateVirtualMapping(Process, Address, Region->Protect, &Page, 1); + MmCreateVirtualMapping(Process, Address, Region->Protect, Page); MmInsertRmap(Page, Process, Address); MmSetDirtyPage(Process, Address); @@ -219,7 +224,7 @@ GetEntry: MmFreeSwapPage(SwapEntry); /* We can't, so let this page in the Process VM */ - MmCreateVirtualMapping(Process, Address, Region->Protect, &Page, 1); + MmCreateVirtualMapping(Process, Address, Region->Protect, Page); MmInsertRmap(Page, Process, Address); MmSetDirtyPage(Process, Address); @@ -241,7 +246,6 @@ GetEntry: } /* We can finally let this page go */ - MmUnlockAddressSpace(AddressSpace); if (Process != PsInitialSystemProcess) KeDetachProcess(); @@ -262,6 +266,8 @@ GetEntry: Released = MmUnsharePageEntrySectionSegment(MemoryArea, Segment, &Offset, Dirty, TRUE, NULL); MmUnlockSectionSegment(Segment); + if (Process != PsInitialSystemProcess) + KeDetachProcess(); MmUnlockAddressSpace(AddressSpace); ExReleaseRundownProtection(&Process->RundownProtect); diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index 2485d5bb5f5..0b6b8e80416 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -1636,8 +1636,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, Status = MmCreateVirtualMapping(Process, PAddress, Region->Protect, - &Page, - 1); + Page); if (!NT_SUCCESS(Status)) { DPRINT("MmCreateVirtualMapping failed, not out of memory\n"); @@ -1679,8 +1678,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, Status = MmCreateVirtualMappingUnsafe(Process, PAddress, Region->Protect, - &Page, - 1); + Page); if (!NT_SUCCESS(Status)) { DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n"); @@ -1729,7 +1727,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SSE(Page << PAGE_SHIFT, 1)); MmUnlockSectionSegment(Segment); - Status = MmCreateVirtualMapping(Process, PAddress, Attributes, &Page, 1); + Status = MmCreateVirtualMapping(Process, PAddress, Attributes, Page); if (!NT_SUCCESS(Status)) { DPRINT1("Unable to create virtual mapping\n"); @@ -1828,8 +1826,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, Status = MmCreateVirtualMapping(Process, PAddress, Attributes, - &Page, - 1); + Page); if (!NT_SUCCESS(Status)) { DPRINT1("Unable to create virtual mapping\n"); @@ -1857,8 +1854,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, Status = MmCreateVirtualMapping(Process, PAddress, Attributes, - &Page, - 1); + Page); if (!NT_SUCCESS(Status)) { DPRINT1("Unable to create virtual mapping\n"); @@ -1985,8 +1981,7 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace, Status = MmCreateVirtualMapping(Process, PAddress, Region->Protect, - &NewPage, - 1); + NewPage); if (!NT_SUCCESS(Status)) { DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
3 years, 8 months
1
0
0
0
[reactos] 04/12: [NTOS:MM] Get rid of MmRosFlushVirtualMemory
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b445005c7086ef76a0ace…
commit b445005c7086ef76a0acefc022878d47ada1487c Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Wed Mar 10 15:24:31 2021 +0100 Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com> CommitDate: Thu Apr 8 15:40:37 2021 +0200 [NTOS:MM] Get rid of MmRosFlushVirtualMemory It's not used anywhere now, and it will eventually be gone --- ntoskrnl/include/internal/mm.h | 8 ----- ntoskrnl/mm/ARM3/virtual.c | 6 ++-- ntoskrnl/mm/section.c | 75 ------------------------------------------ 3 files changed, 4 insertions(+), 85 deletions(-) diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index f5dd0a4e049..93c44e5bd05 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -1402,14 +1402,6 @@ MmMakePagesDirty( _In_ PVOID Address, _In_ ULONG Length); -NTSTATUS -NTAPI -MmRosFlushVirtualMemory( - _In_ PEPROCESS Process, - _Inout_ PVOID* Address, - _Inout_ PSIZE_T Length, - _Out_ PIO_STATUS_BLOCK Iosb); - NTSTATUS NTAPI MmFlushSegment( diff --git a/ntoskrnl/mm/ARM3/virtual.c b/ntoskrnl/mm/ARM3/virtual.c index 986b345e6c6..eb03fa15e75 100644 --- a/ntoskrnl/mm/ARM3/virtual.c +++ b/ntoskrnl/mm/ARM3/virtual.c @@ -1356,8 +1356,10 @@ MmFlushVirtualMemory(IN PEPROCESS Process, OUT PIO_STATUS_BLOCK IoStatusBlock) { PAGED_CODE(); - /* For now we call the old Mm */ - return MmRosFlushVirtualMemory(Process, BaseAddress, RegionSize, IoStatusBlock); + + UNIMPLEMENTED; + + return STATUS_NOT_IMPLEMENTED; } ULONG diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index 5df50f191ef..2485d5bb5f5 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -4534,81 +4534,6 @@ MmArePagesResident( return Ret; } -NTSTATUS -NTAPI -MmRosFlushVirtualMemory( - _In_ PEPROCESS Process, - _Inout_ PVOID* Address, - _Inout_ PSIZE_T Length, - _Out_ PIO_STATUS_BLOCK Iosb) -{ - PMEMORY_AREA MemoryArea; - PMM_SECTION_SEGMENT Segment; - LARGE_INTEGER SegmentOffset, RangeEnd; - PMMSUPPORT AddressSpace = Process ? &Process->Vm : MmGetKernelAddressSpace(); - PVOID CurrentAddress; - - PAGED_CODE(); - - MmLockAddressSpace(AddressSpace); - - DPRINT("Flushing Process %p at %p --> 0x%x", Process, *Address, *Length); - - MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, *Address); - if ((MemoryArea == NULL) || (MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) || - (MemoryArea->VadNode.u.VadFlags.VadType == VadImageMap)) - { - DPRINT1("Unable to find memory area at address %p.\n", Address); - MmUnlockAddressSpace(AddressSpace); - return STATUS_NOT_MAPPED_VIEW; - } - - Segment = MemoryArea->SectionData.Segment; - - SegmentOffset.QuadPart = PAGE_ROUND_DOWN(*Address) - MA_GetStartingAddress(MemoryArea) - + MemoryArea->SectionData.ViewOffset; - RangeEnd.QuadPart = PAGE_ROUND_UP((ULONG_PTR)*Address + *Length) - MA_GetStartingAddress(MemoryArea) - + MemoryArea->SectionData.ViewOffset; - - CurrentAddress = *Address; - - MmUnlockAddressSpace(AddressSpace); - - MmLockSectionSegment(Segment); - - Iosb->Information = 0; - while (SegmentOffset.QuadPart < RangeEnd.QuadPart) - { - ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset); - - /* Let any pending read proceed */ - while (MM_IS_WAIT_PTE(Entry)) - { - MmUnlockSectionSegment(Segment); - YieldProcessor(); - MmLockSectionSegment(Segment); - Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset); - } - - /* We are called from Cc, this can't be backed by the page files */ - ASSERT(!IS_SWAP_FROM_SSE(Entry)); - - /* At this point, there may be a valid page there */ - if (Entry != 0) - { - /* This will write the page to disk, if needed */ - MmCheckDirtySegment(Segment, &SegmentOffset, Process ? MmIsDirtyPage(Process, CurrentAddress) : FALSE, FALSE); - Iosb->Information += PAGE_SIZE; - } - SegmentOffset.QuadPart += PAGE_SIZE; - CurrentAddress = (PVOID)((ULONG_PTR)CurrentAddress + PAGE_SIZE); - } - - MmUnlockSectionSegment(Segment); - - return STATUS_SUCCESS; -} - /* Like CcPurgeCache but for the in-memory segment */ BOOLEAN NTAPI
3 years, 8 months
1
0
0
0
[reactos] 03/12: [NTOS:MM] Get rid of MmSetCleanAllRmaps and MmIsDirtyPageRmap
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9e121fb6c25077dedf9cf…
commit 9e121fb6c25077dedf9cfeb74edda3f1ad411dbf Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Wed Mar 10 15:16:29 2021 +0100 Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com> CommitDate: Thu Apr 8 15:40:37 2021 +0200 [NTOS:MM] Get rid of MmSetCleanAllRmaps and MmIsDirtyPageRmap Everything is wrong with them. Bad locking. Bad logic. --- ntoskrnl/include/internal/mm.h | 7 ------ ntoskrnl/mm/rmap.c | 55 ------------------------------------------ ntoskrnl/mm/section.c | 5 +--- 3 files changed, 1 insertion(+), 66 deletions(-) diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index d05360c28be..f5dd0a4e049 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -903,13 +903,6 @@ VOID NTAPI MmInitializeRmapList(VOID); -VOID -NTAPI -MmSetCleanAllRmaps(PFN_NUMBER Page); -BOOLEAN -NTAPI -MmIsDirtyPageRmap(PFN_NUMBER Page); - NTSTATUS NTAPI MmPageOutPhysicalAddress(PFN_NUMBER Page); diff --git a/ntoskrnl/mm/rmap.c b/ntoskrnl/mm/rmap.c index 973b8342a5e..c680a8f7a9f 100644 --- a/ntoskrnl/mm/rmap.c +++ b/ntoskrnl/mm/rmap.c @@ -307,61 +307,6 @@ WriteSegment: return STATUS_UNSUCCESSFUL; } -VOID -NTAPI -MmSetCleanAllRmaps(PFN_NUMBER Page) -{ - PMM_RMAP_ENTRY current_entry; - KIRQL OldIrql; - - OldIrql = MiAcquirePfnLock(); - current_entry = MmGetRmapListHeadPage(Page); - if (current_entry == NULL) - { - DPRINT1("MmSetCleanAllRmaps: No rmaps.\n"); - KeBugCheck(MEMORY_MANAGEMENT); - } - while (current_entry != NULL) - { - if (!RMAP_IS_SEGMENT(current_entry->Address)) - MmSetCleanPage(current_entry->Process, current_entry->Address); - current_entry = current_entry->Next; - } - MiReleasePfnLock(OldIrql); -} - -BOOLEAN -NTAPI -MmIsDirtyPageRmap(PFN_NUMBER Page) -{ - PMM_RMAP_ENTRY current_entry; - KIRQL OldIrql; - BOOLEAN Dirty = FALSE; - - OldIrql = MiAcquirePfnLock(); - current_entry = MmGetRmapListHeadPage(Page); - if (current_entry == NULL) - { - DPRINT1("MmIsDirtyPageRmap: No rmaps.\n"); - KeBugCheck(MEMORY_MANAGEMENT); - } - while (current_entry != NULL) - { - if (!RMAP_IS_SEGMENT(current_entry->Address)) - { - if (MmIsDirtyPage(current_entry->Process, current_entry->Address)) - { - Dirty = TRUE; - break; - } - } - current_entry = current_entry->Next; - } - MiReleasePfnLock(OldIrql); - - return Dirty; -} - VOID NTAPI MmInsertRmap(PFN_NUMBER Page, PEPROCESS Process, diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index 88392afee7d..5df50f191ef 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -4848,9 +4848,6 @@ MmCheckDirtySegment( Entry = WRITE_SSE(Entry); MmSetPageEntrySectionSegment(Segment, Offset, Entry); - /* Tell the other users that we are clean again */ - MmSetCleanAllRmaps(Page); - MmUnlockSectionSegment(Segment); if (FlagOn(*Segment->Flags, MM_DATAFILE_SEGMENT)) @@ -4915,7 +4912,7 @@ MmCheckDirtySegment( else { /* Check if someone dirtified this page while we were not looking */ - DirtyAgain = IS_DIRTY_SSE(Entry) || MmIsDirtyPageRmap(Page); + DirtyAgain = IS_DIRTY_SSE(Entry); } /* Drop the reference we got, deleting the write altogether. */
3 years, 8 months
1
0
0
0
[reactos] 02/12: [NTOS:MM] Let ARM3 handle invalid PDE for itself.
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7bffb92099936d1487680…
commit 7bffb92099936d1487680efba433f45c3316defa Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Fri Feb 19 16:57:33 2021 +0100 Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com> CommitDate: Thu Apr 8 15:40:37 2021 +0200 [NTOS:MM] Let ARM3 handle invalid PDE for itself. --- ntoskrnl/mm/i386/page.c | 38 ++++++-------------------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/ntoskrnl/mm/i386/page.c b/ntoskrnl/mm/i386/page.c index 4690a9a5d15..e1aac494dcb 100644 --- a/ntoskrnl/mm/i386/page.c +++ b/ntoskrnl/mm/i386/page.c @@ -186,17 +186,6 @@ ProtectToPTE(ULONG flProtect) return(Attributes); } -NTSTATUS -NTAPI -MiDispatchFault(IN ULONG FaultCode, - IN PVOID Address, - IN PMMPTE PointerPte, - IN PMMPTE PointerProtoPte, - IN BOOLEAN Recursive, - IN PEPROCESS Process, - IN PVOID TrapInformation, - IN PVOID Vad); - NTSTATUS NTAPI MiFillSystemPageDirectory(IN PVOID Base, @@ -244,32 +233,17 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create, PKIRQ } return Pt + MiAddressToPteOffset(Address); } + /* This is for our process */ PointerPde = MiAddressToPde(Address); Pt = (PULONG)MiAddressToPte(Address); - if (PointerPde->u.Hard.Valid == 0) + + if ((PointerPde->u.Hard.Valid == 0) && (Create == FALSE)) { - NTSTATUS Status; - if (Create == FALSE) - { - return NULL; - } - ASSERT(PointerPde->u.Long == 0); - - MI_WRITE_INVALID_PTE(PointerPde, DemandZeroPde); - // Tiny HACK: Parameter 1 is the architecture specific FaultCode for an access violation (i.e. page is present) - Status = MiDispatchFault(0x1, - Pt, - PointerPde, - NULL, - FALSE, - PsGetCurrentProcess(), - NULL, - NULL); - DBG_UNREFERENCED_LOCAL_VARIABLE(Status); - ASSERT(KeAreAllApcsDisabled() == TRUE); - ASSERT(PointerPde->u.Hard.Valid == 1); + /* Do not fault PDE in if not needed */ + return NULL; } + return (PULONG)MiAddressToPte(Address); }
3 years, 8 months
1
0
0
0
[reactos] 01/12: [NTOS:MM] Fix a bit the page-out/page-in logic
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=36a92e6ea5823ce684dfb…
commit 36a92e6ea5823ce684dfb1886494bebc918ff6ae Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Fri Feb 5 15:04:07 2021 +0100 Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com> CommitDate: Thu Apr 8 15:40:37 2021 +0200 [NTOS:MM] Fix a bit the page-out/page-in logic - Do not lock the section segment when we are serving a fault for a process private page. - Do not keep the process address space lock while writing to pagefile. - Do not wait for an event that might never be set. --- ntoskrnl/cache/section/newmm.h | 10 ---- ntoskrnl/include/internal/mm.h | 3 +- ntoskrnl/mm/i386/page.c | 27 ++-------- ntoskrnl/mm/mmfault.c | 5 +- ntoskrnl/mm/rmap.c | 47 +++++++++++------ ntoskrnl/mm/section.c | 111 ++++++++++++++++++----------------------- 6 files changed, 88 insertions(+), 115 deletions(-) diff --git a/ntoskrnl/cache/section/newmm.h b/ntoskrnl/cache/section/newmm.h index 2efcd9cf7d5..cf40d688edf 100644 --- a/ntoskrnl/cache/section/newmm.h +++ b/ntoskrnl/cache/section/newmm.h @@ -17,16 +17,6 @@ #define SEC_CACHE (0x20000000) -#define MiWaitForPageEvent(Process,Address) do { \ - DPRINT("MiWaitForPageEvent %p:%p #\n", Process, Address); \ - KeWaitForSingleObject(&MmWaitPageEvent, 0, KernelMode, FALSE, NULL); \ -} while(0) - -#define MiSetPageEvent(Process,Address) do { \ - DPRINT("MiSetPageEvent %p:%p #\n",Process, (PVOID)(Address)); \ - KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE); \ -} while(0) - /* We store 8 bits of location with a page association */ #define ENTRIES_PER_ELEMENT 256 diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index 074dbd4e454..d05360c28be 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -1376,7 +1376,8 @@ NTAPI MmAccessFaultSectionView( PMMSUPPORT AddressSpace, MEMORY_AREA* MemoryArea, - PVOID Address + PVOID Address, + BOOLEAN Locked ); VOID diff --git a/ntoskrnl/mm/i386/page.c b/ntoskrnl/mm/i386/page.c index b541b5d4752..4690a9a5d15 100644 --- a/ntoskrnl/mm/i386/page.c +++ b/ntoskrnl/mm/i386/page.c @@ -219,6 +219,8 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create, PKIRQ PMMPDE PdeBase; ULONG PdeOffset = MiGetPdeOffset(Address); + ASSERT(!Create); + PdeBase = MiMapPageInHyperSpace(PsGetCurrentProcess(), PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0]), OldIrql); @@ -229,29 +231,8 @@ MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create, PKIRQ PointerPde = PdeBase + PdeOffset; if (PointerPde->u.Hard.Valid == 0) { - KAPC_STATE ApcState; - NTSTATUS Status; - - if (!Create) - { - MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PdeBase, *OldIrql); - return NULL; - } - - KeStackAttachProcess(&Process->Pcb, &ApcState); - - Status = MiDispatchFault(0x1, - MiAddressToPte(Address), - MiAddressToPde(Address), - NULL, - FALSE, - Process, - NULL, - NULL); - - KeUnstackDetachProcess(&ApcState); - if (!NT_SUCCESS(Status)) - return NULL; + MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PdeBase, *OldIrql); + return NULL; } Pfn = PointerPde->u.Hard.PageFrameNumber; diff --git a/ntoskrnl/mm/mmfault.c b/ntoskrnl/mm/mmfault.c index 75f7b584a22..410b2f558e8 100644 --- a/ntoskrnl/mm/mmfault.c +++ b/ntoskrnl/mm/mmfault.c @@ -77,7 +77,8 @@ MmpAccessFault(KPROCESSOR_MODE Mode, case MEMORY_AREA_SECTION_VIEW: Status = MmAccessFaultSectionView(AddressSpace, MemoryArea, - (PVOID)Address); + (PVOID)Address, + !FromMdl); break; #ifdef NEWCC case MEMORY_AREA_CACHE: @@ -169,7 +170,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode, Status = MmNotPresentFaultSectionView(AddressSpace, MemoryArea, (PVOID)Address, - FromMdl); + !FromMdl); break; #ifdef NEWCC case MEMORY_AREA_CACHE: diff --git a/ntoskrnl/mm/rmap.c b/ntoskrnl/mm/rmap.c index a2169eeb54f..973b8342a5e 100644 --- a/ntoskrnl/mm/rmap.c +++ b/ntoskrnl/mm/rmap.c @@ -141,15 +141,13 @@ GetEntry: /* The segment is being read or something. Give up */ MmUnlockSectionSegment(Segment); MmUnlockAddressSpace(AddressSpace); - if (Address < MmSystemRangeStart) - { - ExReleaseRundownProtection(&Process->RundownProtect); - ObDereferenceObject(Process); - } + ExReleaseRundownProtection(&Process->RundownProtect); + ObDereferenceObject(Process); return(STATUS_UNSUCCESSFUL); } /* Delete this virtual mapping in the process */ + MmDeleteRmap(Page, Process, Address); MmDeleteVirtualMapping(Process, Address, &Dirty, &MapPage); /* We checked this earlier */ @@ -162,6 +160,11 @@ GetEntry: /* This page is private to the process */ MmUnlockSectionSegment(Segment); + /* Attach to it, if needed */ + ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess); + if (Process != PsInitialSystemProcess) + KeAttachProcess(&Process->Pcb); + /* Check if we should write it back to the page file */ SwapEntry = MmGetSavedSwapEntryPage(Page); @@ -177,14 +180,14 @@ GetEntry: /* We can't, so let this page in the Process VM */ MmCreateVirtualMapping(Process, Address, Region->Protect, &Page, 1); + MmInsertRmap(Page, Process, Address); MmSetDirtyPage(Process, Address); MmUnlockAddressSpace(AddressSpace); - if (Address < MmSystemRangeStart) - { - ExReleaseRundownProtection(&Process->RundownProtect); - ObDereferenceObject(Process); - } + if (Process != PsInitialSystemProcess) + KeDetachProcess(); + ExReleaseRundownProtection(&Process->RundownProtect); + ObDereferenceObject(Process); return STATUS_UNSUCCESSFUL; } @@ -192,7 +195,18 @@ GetEntry: if (Dirty) { + SWAPENTRY Dummy; + + /* Put a wait entry into the process and unlock */ + MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY); + MmUnlockAddressSpace(AddressSpace); + Status = MmWriteToSwapPage(SwapEntry, Page); + + MmLockAddressSpace(AddressSpace); + MmDeletePageFileMapping(Process, Address, &Dummy); + ASSERT(Dummy == MM_WAIT_ENTRY); + if (!NT_SUCCESS(Status)) { /* We failed at saving the content of this page. Keep it in */ @@ -206,9 +220,12 @@ GetEntry: /* We can't, so let this page in the Process VM */ MmCreateVirtualMapping(Process, Address, Region->Protect, &Page, 1); + MmInsertRmap(Page, Process, Address); MmSetDirtyPage(Process, Address); MmUnlockAddressSpace(AddressSpace); + if (Process != PsInitialSystemProcess) + KeDetachProcess(); ExReleaseRundownProtection(&Process->RundownProtect); ObDereferenceObject(Process); @@ -223,10 +240,11 @@ GetEntry: MmSetSavedSwapEntryPage(Page, 0); } - MmUnlockAddressSpace(AddressSpace); - /* We can finally let this page go */ - MmDeleteRmap(Page, Process, Address); + + MmUnlockAddressSpace(AddressSpace); + if (Process != PsInitialSystemProcess) + KeDetachProcess(); #if DBG OldIrql = MiAcquirePfnLock(); ASSERT(MmGetRmapListHeadPage(Page) == NULL); @@ -240,9 +258,6 @@ GetEntry: return STATUS_SUCCESS; } - /* Delete this RMAP */ - MmDeleteRmap(Page, Process, Address); - /* One less mapping referencing this segment */ Released = MmUnsharePageEntrySectionSegment(MemoryArea, Segment, &Offset, Dirty, TRUE, NULL); diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index 3ff8098937d..88392afee7d 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -1461,7 +1461,11 @@ MmAlterViewAttributes(PMMSUPPORT AddressSpace, MmGetPageFileMapping(Process, Address, &SwapEntry); if (SwapEntry != MM_WAIT_ENTRY) break; - MiWaitForPageEvent(Process, Address); + MmUnlockSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); + YieldProcessor(); + MmLockAddressSpace(AddressSpace); + MmLockSectionSegment(Segment); } while (TRUE); @@ -1522,6 +1526,8 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); SWAPENTRY SwapEntry; + ASSERT(Locked); + /* * There is a window between taking the page fault and locking the * address space when another thread could load the page so we check @@ -1577,39 +1583,6 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, return STATUS_GUARD_PAGE_VIOLATION; } - /* - * Lock the segment - */ - MmLockSectionSegment(Segment); - Entry = MmGetPageEntrySectionSegment(Segment, &Offset); - /* - * Check if this page needs to be mapped COW - */ - if ((Segment->WriteCopy) && - (Region->Protect == PAGE_READWRITE || - Region->Protect == PAGE_EXECUTE_READWRITE)) - { - Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ; - } - else - { - Attributes = Region->Protect; - } - - /* - * Check if someone else is already handling this fault, if so wait - * for them - */ - if (Entry && MM_IS_WAIT_PTE(Entry)) - { - MmUnlockSectionSegment(Segment); - MmUnlockAddressSpace(AddressSpace); - MiWaitForPageEvent(NULL, NULL); - MmLockAddressSpace(AddressSpace); - DPRINT("Address 0x%p\n", Address); - return STATUS_MM_RESTART_OPERATION; - } - HasSwapEntry = MmIsPageSwapEntry(Process, Address); /* See if we should use a private page */ @@ -1620,22 +1593,21 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MmGetPageFileMapping(Process, Address, &SwapEntry); if (SwapEntry == MM_WAIT_ENTRY) { - MmUnlockSectionSegment(Segment); MmUnlockAddressSpace(AddressSpace); - MiWaitForPageEvent(NULL, NULL); + YieldProcessor(); MmLockAddressSpace(AddressSpace); return STATUS_MM_RESTART_OPERATION; } /* - * Must be private page we have swapped out. - */ + * Must be private page we have swapped out. + */ /* * Sanity check */ - MmDeletePageFileMapping(Process, Address, &SwapEntry); - MmUnlockSectionSegment(Segment); + MmDeletePageFileMapping(Process, Address, &DummyEntry); + ASSERT(DummyEntry == SwapEntry); /* Tell everyone else we are serving the fault. */ MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY); @@ -1650,18 +1622,17 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, KeBugCheck(MEMORY_MANAGEMENT); } - if (HasSwapEntry) + Status = MmReadFromSwapPage(SwapEntry, Page); + if (!NT_SUCCESS(Status)) { - Status = MmReadFromSwapPage(SwapEntry, Page); - if (!NT_SUCCESS(Status)) - { - DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status); - KeBugCheck(MEMORY_MANAGEMENT); - } + DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status); + KeBugCheck(MEMORY_MANAGEMENT); } MmLockAddressSpace(AddressSpace); MmDeletePageFileMapping(Process, PAddress, &DummyEntry); + ASSERT(DummyEntry == MM_WAIT_ENTRY); + Status = MmCreateVirtualMapping(Process, PAddress, Region->Protect, @@ -1677,8 +1648,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, /* * Store the swap entry for later use. */ - if (HasSwapEntry) - MmSetSavedSwapEntryPage(Page, SwapEntry); + MmSetSavedSwapEntryPage(Page, SwapEntry); /* * Add the page to the process's working set @@ -1687,11 +1657,15 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, /* * Finish the operation */ - MiSetPageEvent(Process, Address); DPRINT("Address 0x%p\n", Address); return STATUS_SUCCESS; } + /* + * Lock the segment + */ + MmLockSectionSegment(Segment); + /* * Satisfying a page fault on a map of /Device/PhysicalMemory is easy */ @@ -1717,16 +1691,29 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, /* * Cleanup and release locks */ - MiSetPageEvent(Process, Address); DPRINT("Address 0x%p\n", Address); return STATUS_SUCCESS; } + /* + * Check if this page needs to be mapped COW + */ + if ((Segment->WriteCopy) && + (Region->Protect == PAGE_READWRITE || + Region->Protect == PAGE_EXECUTE_READWRITE)) + { + Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ; + } + else + { + Attributes = Region->Protect; + } + + /* * Get the entry corresponding to the offset within the section */ Entry = MmGetPageEntrySectionSegment(Segment, &Offset); - if (Entry == 0) { /* @@ -1752,7 +1739,6 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, if (Process) MmInsertRmap(Page, Process, Address); - MiSetPageEvent(Process, Address); DPRINT("Address 0x%p\n", Address); return STATUS_SUCCESS; } @@ -1792,7 +1778,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, { MmUnlockSectionSegment(Segment); MmUnlockAddressSpace(AddressSpace); - MiWaitForPageEvent(NULL, NULL); + YieldProcessor(); MmLockAddressSpace(AddressSpace); return STATUS_MM_RESTART_OPERATION; } @@ -1800,6 +1786,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, /* * Release all our locks and read in the page from disk */ + MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY)); MmUnlockSectionSegment(Segment); MmUnlockAddressSpace(AddressSpace); @@ -1826,7 +1813,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, * that has a pending page-in. */ Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset); - if (Entry != Entry1) + if (Entry1 != MAKE_SWAP_SSE(MM_WAIT_ENTRY)) { DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1); KeBugCheck(MEMORY_MANAGEMENT); @@ -1859,7 +1846,6 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MmSetPageEntrySectionSegment(Segment, &Offset, Entry); MmUnlockSectionSegment(Segment); - MiSetPageEvent(Process, Address); DPRINT("Address 0x%p\n", Address); return STATUS_SUCCESS; } @@ -1886,7 +1872,6 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace, MmSharePageEntrySectionSegment(Segment, &Offset); MmUnlockSectionSegment(Segment); - MiSetPageEvent(Process, Address); DPRINT("Address 0x%p\n", Address); return STATUS_SUCCESS; } @@ -1896,7 +1881,8 @@ NTSTATUS NTAPI MmAccessFaultSectionView(PMMSUPPORT AddressSpace, MEMORY_AREA* MemoryArea, - PVOID Address) + PVOID Address, + BOOLEAN Locked) { PMM_SECTION_SEGMENT Segment; PFN_NUMBER OldPage; @@ -1911,7 +1897,7 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace, DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address); /* Make sure we have a page mapping for this address. */ - Status = MmNotPresentFaultSectionView(AddressSpace, MemoryArea, Address, TRUE); + Status = MmNotPresentFaultSectionView(AddressSpace, MemoryArea, Address, Locked); if (!NT_SUCCESS(Status)) { /* This is invalid access ! */ @@ -2011,7 +1997,6 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace, if (Process) MmInsertRmap(NewPage, Process, PAddress); - MiSetPageEvent(Process, Address); DPRINT("Address 0x%p\n", Address); return STATUS_SUCCESS; } @@ -3383,7 +3368,7 @@ MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, MmUnlockSectionSegment(Segment); MmUnlockAddressSpace(AddressSpace); - MiWaitForPageEvent(NULL, NULL); + YieldProcessor(); MmLockAddressSpace(AddressSpace); MmLockSectionSegment(Segment); @@ -4600,7 +4585,7 @@ MmRosFlushVirtualMemory( while (MM_IS_WAIT_PTE(Entry)) { MmUnlockSectionSegment(Segment); - MiWaitForPageEvent(NULL, NULL); + YieldProcessor(); MmLockSectionSegment(Segment); Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset); } @@ -5010,7 +4995,7 @@ MmMakePagesDirty( { MmUnlockSectionSegment(Segment); MmUnlockAddressSpace(AddressSpace); - MiWaitForPageEvent(NULL, NULL); + YieldProcessor(); MmLockAddressSpace(AddressSpace); MmLockSectionSegment(Segment); Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset);
3 years, 8 months
1
0
0
0
[reactos] 01/01: [CMAKE] Fix a file name
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c4232ae995708a591609d…
commit c4232ae995708a591609d97e80a007061ea489e3 Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Thu Apr 8 15:34:35 2021 +0200 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Thu Apr 8 15:35:22 2021 +0200 [CMAKE] Fix a file name --- modules/rostests/winetests/dxdiagn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rostests/winetests/dxdiagn/CMakeLists.txt b/modules/rostests/winetests/dxdiagn/CMakeLists.txt index b448156e85f..d9864273e9f 100644 --- a/modules/rostests/winetests/dxdiagn/CMakeLists.txt +++ b/modules/rostests/winetests/dxdiagn/CMakeLists.txt @@ -1,7 +1,7 @@ list(APPEND SOURCE container.c - provider + provider.c testlist.c) add_executable(dxdiagn_winetest ${SOURCE})
3 years, 8 months
1
0
0
0
[reactos] 01/01: [BROWSEUI] auto-completion: Support large number items (#3592)
by Katayama Hirofumi MZ
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=773ad7aebccad04744b20…
commit 773ad7aebccad04744b2064cfed7fe917d0bd367 Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com> AuthorDate: Thu Apr 8 15:02:05 2021 +0900 Commit: GitHub <noreply(a)github.com> CommitDate: Thu Apr 8 15:02:05 2021 +0900 [BROWSEUI] auto-completion: Support large number items (#3592) If the items are too many, enable filtering in item enumeration. CORE-9281 --- dll/win32/browseui/CAutoComplete.cpp | 176 +++++++++++++++++++++++------------ dll/win32/browseui/CAutoComplete.h | 32 ++++--- 2 files changed, 133 insertions(+), 75 deletions(-) diff --git a/dll/win32/browseui/CAutoComplete.cpp b/dll/win32/browseui/CAutoComplete.cpp index 6f2033d9f9f..e7a078c10a3 100644 --- a/dll/win32/browseui/CAutoComplete.cpp +++ b/dll/win32/browseui/CAutoComplete.cpp @@ -32,7 +32,7 @@ #define CX_LIST 30160 // width of m_hwndList (very wide but alright) #define CY_LIST 288 // maximum height of drop-down window #define CY_ITEM 18 // default height of listview item -#define COMPLETION_TIMEOUT 250 // in milliseconds +#define COMPLETION_TIMEOUT 300 // in milliseconds #define MAX_ITEM_COUNT 1000 // the maximum number of items #define WATCH_TIMER_ID 0xFEEDBEEF // timer ID to watch m_rcEdit #define WATCH_INTERVAL 300 // in milliseconds @@ -640,6 +640,7 @@ CAutoComplete::CAutoComplete() , m_bDowner(TRUE), m_dwOptions(ACO_AUTOAPPEND | ACO_AUTOSUGGEST) , m_bEnabled(TRUE), m_hwndCombo(NULL), m_hFont(NULL), m_bResized(FALSE) , m_hwndEdit(NULL), m_fnOldEditProc(NULL), m_fnOldWordBreakProc(NULL) + , m_bPartialList(FALSE), m_dwTick(0) { } @@ -667,46 +668,46 @@ CAutoComplete::~CAutoComplete() m_pACList.Release(); } -BOOL CAutoComplete::CanAutoSuggest() +inline BOOL CAutoComplete::CanAutoSuggest() const { return !!(m_dwOptions & ACO_AUTOSUGGEST) && m_bEnabled; } -BOOL CAutoComplete::CanAutoAppend() +inline BOOL CAutoComplete::CanAutoAppend() const { return !!(m_dwOptions & ACO_AUTOAPPEND) && m_bEnabled; } -BOOL CAutoComplete::UseTab() +inline BOOL CAutoComplete::UseTab() const { return !!(m_dwOptions & ACO_USETAB) && m_bEnabled; } -BOOL CAutoComplete::IsComboBoxDropped() +inline BOOL CAutoComplete::IsComboBoxDropped() const { if (!::IsWindow(m_hwndCombo)) return FALSE; return (BOOL)::SendMessageW(m_hwndCombo, CB_GETDROPPEDSTATE, 0, 0); } -BOOL CAutoComplete::FilterPrefixes() +inline BOOL CAutoComplete::FilterPrefixes() const { return !!(m_dwOptions & ACO_FILTERPREFIXES) && m_bEnabled; } -INT CAutoComplete::GetItemCount() +inline INT CAutoComplete::GetItemCount() const { return m_outerList.GetSize(); } -CStringW CAutoComplete::GetItemText(INT iItem) +CStringW CAutoComplete::GetItemText(INT iItem) const { if (iItem < 0 || m_outerList.GetSize() <= iItem) return L""; return m_outerList[iItem]; } -CStringW CAutoComplete::GetEditText() +inline CStringW CAutoComplete::GetEditText() const { WCHAR szText[L_MAX_URL_LENGTH]; if (::GetWindowTextW(m_hwndEdit, szText, _countof(szText))) @@ -721,9 +722,8 @@ VOID CAutoComplete::SetEditText(LPCWSTR pszText) m_bInSetText = FALSE; } -CStringW CAutoComplete::GetStemText() +inline CStringW CAutoComplete::GetStemText(const CStringW& strText) const { - CStringW strText = GetEditText(); INT ich = strText.ReverseFind(L'\\'); if (ich == -1) return L""; // no stem @@ -1284,7 +1284,7 @@ VOID CAutoComplete::UpdateDropDownState() } // calculate the positions of the controls -VOID CAutoComplete::CalcRects(BOOL bDowner, RECT& rcList, RECT& rcScrollBar, RECT& rcSizeBox) +VOID CAutoComplete::CalcRects(BOOL bDowner, RECT& rcList, RECT& rcScrollBar, RECT& rcSizeBox) const { // get the client rectangle RECT rcClient; @@ -1354,7 +1354,7 @@ VOID CAutoComplete::LoadQuickComplete(LPCWSTR pwszRegKeyPath, LPCWSTR pwszQuickC } } -CStringW CAutoComplete::GetQuickEdit(LPCWSTR pszText) +CStringW CAutoComplete::GetQuickEdit(LPCWSTR pszText) const { if (pszText[0] == 0 || m_strQuickComplete.IsEmpty()) return pszText; @@ -1444,20 +1444,45 @@ VOID CAutoComplete::RepositionDropDown() ShowWindow(SW_SHOWNOACTIVATE); } -INT CAutoComplete::ReLoadInnerList() +inline BOOL +CAutoComplete::DoesMatch(const CStringW& strTarget, const CStringW& strText) const { - m_innerList.RemoveAll(); // clear contents + CStringW strBody; + if (DropPrefix(strTarget, strBody)) + { + if (::StrCmpNIW(strBody, strText, strText.GetLength()) == 0) + return TRUE; + } + else if (::StrCmpNIW(strTarget, strText, strText.GetLength()) == 0) + { + return TRUE; + } + return FALSE; +} - if (!m_pEnum) - return 0; +VOID CAutoComplete::ScrapeOffList(const CStringW& strText, CSimpleArray<CStringW>& array) +{ + for (INT iItem = array.GetSize() - 1; iItem >= 0; --iItem) + { + if (!DoesMatch(array[iItem], strText)) + array.RemoveAt(iItem); + } +} + +VOID CAutoComplete::ReLoadInnerList(const CStringW& strText) +{ + m_innerList.RemoveAll(); // clear contents + m_bPartialList = FALSE; - DWORD dwTick = ::GetTickCount(); // used for timeout + if (!m_pEnum || strText.IsEmpty()) + return; // reload the items LPWSTR pszItem; ULONG cGot; + CStringW strTarget; HRESULT hr; - for (ULONG cTotal = 0; cTotal < MAX_ITEM_COUNT; ++cTotal) + for (;;) { // get next item hr = m_pEnum->Next(1, &pszItem, &cGot); @@ -1465,23 +1490,45 @@ INT CAutoComplete::ReLoadInnerList() if (hr != S_OK) break; - m_innerList.Add(pszItem); // append item to m_innerList + strTarget = pszItem; ::CoTaskMemFree(pszItem); // free + if (m_bPartialList) // if items are too many + { + // do filter the items + if (DoesMatch(strTarget, strText)) + { + m_innerList.Add(strTarget); + + if (m_innerList.GetSize() >= MAX_ITEM_COUNT) + break; + } + } + else + { + m_innerList.Add(strTarget); // append item to m_innerList + + // if items are too many + if (m_innerList.GetSize() >= MAX_ITEM_COUNT) + { + // filter the items now + m_bPartialList = TRUE; + ScrapeOffList(strText, m_innerList); + + if (m_innerList.GetSize() >= MAX_ITEM_COUNT) + break; + } + } + // check the timeout - if (::GetTickCount() - dwTick >= COMPLETION_TIMEOUT) + if (::GetTickCount() - m_dwTick >= COMPLETION_TIMEOUT) break; // too late } - - return m_innerList.GetSize(); // the number of items } // update inner list and m_strText and m_strStemText -INT CAutoComplete::UpdateInnerList() +VOID CAutoComplete::UpdateInnerList(const CStringW& strText) { - // get text - CStringW strText = GetEditText(); - BOOL bReset = FALSE, bExpand = FALSE; // flags // if previous text was empty @@ -1493,7 +1540,7 @@ INT CAutoComplete::UpdateInnerList() m_strText = strText; // do expand the items if the stem is changed - CStringW strStemText = GetStemText(); + CStringW strStemText = GetStemText(strText); if (m_strStemText.CompareNoCase(strStemText) != 0) { m_strStemText = strStemText; @@ -1501,6 +1548,10 @@ INT CAutoComplete::UpdateInnerList() bExpand = !m_strStemText.IsEmpty(); } + // if the previous enumeration is too large + if (m_bPartialList) + bReset = bExpand = TRUE; // retry enumeratation + // reset if necessary if (bReset && m_pEnum) { @@ -1521,55 +1572,57 @@ INT CAutoComplete::UpdateInnerList() if (bExpand || m_innerList.GetSize() == 0) { // reload the inner list - ReLoadInnerList(); + ReLoadInnerList(strText); } - - return m_innerList.GetSize(); } -INT CAutoComplete::UpdateOuterList() +VOID CAutoComplete::UpdateOuterList(const CStringW& strText) { - CStringW strText = GetEditText(); // get the text + if (strText.IsEmpty()) + { + m_outerList.RemoveAll(); + return; + } - // update the outer list from the inner list - m_outerList.RemoveAll(); - for (INT iItem = 0; iItem < m_innerList.GetSize(); ++iItem) + if (m_bPartialList) { - // is the beginning matched? - const CStringW& strTarget = m_innerList[iItem]; - CStringW strBody; - if (DropPrefix(strTarget, strBody)) + // it is already filtered + m_outerList = m_innerList; + } + else + { + // do filtering + m_outerList.RemoveAll(); + for (INT iItem = 0; iItem < m_innerList.GetSize(); ++iItem) { - if (::StrCmpNIW(strBody, strText, strText.GetLength()) == 0) - { + const CStringW& strTarget = m_innerList[iItem]; + + if (DoesMatch(strTarget, strText)) m_outerList.Add(strTarget); - continue; - } - } - if (::StrCmpNIW(strTarget, strText, strText.GetLength()) == 0) - { - m_outerList.Add(strTarget); + + // check the timeout + if (::GetTickCount() - m_dwTick >= COMPLETION_TIMEOUT) + break; // too late } } - // sort the list - DoSort(m_outerList); - // unique - DoUniqueAndTrim(m_outerList); + if (::GetTickCount() - m_dwTick < COMPLETION_TIMEOUT) + { + // sort and unique + DoSort(m_outerList); + DoUniqueAndTrim(m_outerList); + } // set the item count of the virtual listview - INT cItems = m_outerList.GetSize(); - if (strText.IsEmpty()) - cItems = 0; - m_hwndList.SendMessageW(LVM_SETITEMCOUNT, cItems, 0); - - return cItems; // the number of items + m_hwndList.SendMessageW(LVM_SETITEMCOUNT, m_outerList.GetSize(), 0); } VOID CAutoComplete::UpdateCompletion(BOOL bAppendOK) { TRACE("CAutoComplete::UpdateCompletion(%p, %d)\n", this, bAppendOK); + m_dwTick = GetTickCount(); // to check the timeout + CStringW strText = GetEditText(); if (m_strText.CompareNoCase(strText) == 0) { @@ -1578,8 +1631,8 @@ VOID CAutoComplete::UpdateCompletion(BOOL bAppendOK) } // update inner list - UINT cItems = UpdateInnerList(); - if (cItems == 0) // no items + UpdateInnerList(strText); + if (m_innerList.GetSize() <= 0) // no items { HideDropDown(); return; @@ -1591,7 +1644,8 @@ VOID CAutoComplete::UpdateCompletion(BOOL bAppendOK) SelectItem(-1); // select none m_bInSelectItem = FALSE; - if (UpdateOuterList()) + UpdateOuterList(strText); + if (m_outerList.GetSize() > 0) RepositionDropDown(); else HideDropDown(); diff --git a/dll/win32/browseui/CAutoComplete.h b/dll/win32/browseui/CAutoComplete.h index 5da346ebb85..51ef81b135a 100644 --- a/dll/win32/browseui/CAutoComplete.h +++ b/dll/win32/browseui/CAutoComplete.h @@ -140,17 +140,17 @@ public: HWND CreateDropDown(); virtual ~CAutoComplete(); - BOOL CanAutoSuggest(); - BOOL CanAutoAppend(); - BOOL UseTab(); - BOOL IsComboBoxDropped(); - BOOL FilterPrefixes(); - INT GetItemCount(); - CStringW GetItemText(INT iItem); + BOOL CanAutoSuggest() const; + BOOL CanAutoAppend() const; + BOOL UseTab() const; + BOOL IsComboBoxDropped() const; + BOOL FilterPrefixes() const; + INT GetItemCount() const; + CStringW GetItemText(INT iItem) const; - CStringW GetEditText(); + CStringW GetEditText() const; VOID SetEditText(LPCWSTR pszText); - CStringW GetStemText(); + CStringW GetStemText(const CStringW& strText) const; VOID SetEditSel(INT ich0, INT ich1); VOID ShowDropDown(); @@ -194,6 +194,8 @@ protected: HWND m_hwndEdit; // the textbox WNDPROC m_fnOldEditProc; // old textbox procedure EDITWORDBREAKPROCW m_fnOldWordBreakProc; + BOOL m_bPartialList; // is the list partial? + DWORD m_dwTick; // to check timeout // The following variables are non-POD: CStringW m_strText; // internal text (used in selecting item and reverting text) CStringW m_strStemText; // dirname + '\\' @@ -207,14 +209,16 @@ protected: CSimpleArray<CStringW> m_outerList; // owner data for virtual listview // protected methods VOID UpdateDropDownState(); - VOID CalcRects(BOOL bDowner, RECT& rcListView, RECT& rcScrollBar, RECT& rcSizeBox); + VOID CalcRects(BOOL bDowner, RECT& rcListView, RECT& rcScrollBar, RECT& rcSizeBox) const; VOID LoadQuickComplete(LPCWSTR pwszRegKeyPath, LPCWSTR pwszQuickComplete); - CStringW GetQuickEdit(LPCWSTR pszText); + CStringW GetQuickEdit(LPCWSTR pszText) const; VOID RepositionDropDown(); - INT ReLoadInnerList(); - INT UpdateInnerList(); - INT UpdateOuterList(); + VOID ReLoadInnerList(const CStringW& strText); + VOID UpdateInnerList(const CStringW& strText); + VOID UpdateOuterList(const CStringW& strText); VOID UpdateCompletion(BOOL bAppendOK); + VOID ScrapeOffList(const CStringW& strText, CSimpleArray<CStringW>& array); + BOOL DoesMatch(const CStringW& strTarget, const CStringW& strText) const; // message map BEGIN_MSG_MAP(CAutoComplete) MESSAGE_HANDLER(WM_CREATE, OnCreate)
3 years, 8 months
1
0
0
0
[reactos] 01/01: Revert "[NTOS:MM] Allow MiMapPageInHyperSpace to be called from DISPATCH_LEVEL"
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=82c908195c01ded6e2406…
commit 82c908195c01ded6e2406855f5febf79c9fe9ec1 Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Wed Apr 7 23:26:44 2021 +0200 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Apr 7 23:26:44 2021 +0200 Revert "[NTOS:MM] Allow MiMapPageInHyperSpace to be called from DISPATCH_LEVEL" This reverts commit 8404d1a6ff897f5210860ba52d70c3a6e86f3fbb. Not ready for prime time, sorry. --- ntoskrnl/include/internal/mm.h | 21 ++++++--------------- ntoskrnl/mm/ARM3/hypermap.c | 34 ++++++++-------------------------- 2 files changed, 14 insertions(+), 41 deletions(-) diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index 4718fcabcc3..074dbd4e454 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -1011,26 +1011,17 @@ MmZeroPageThread( ); /* hypermap.c *****************************************************************/ -_Acquires_lock_(Process->HyperSpaceLock) -_When_(OldIrql == 0, _IRQL_requires_(DISPATCH_LEVEL)) -_When_(OldIrql != 0, _IRQL_requires_(PASSIVE_LEVEL)) -_When_(OldIrql != 0, _At_(*OldIrql, IRQL_saves_)) -_When_(OldIrql != 0, _IRQL_raises_(DISPATCH_LEVEL)) PVOID NTAPI -MiMapPageInHyperSpace(_In_ PEPROCESS Process, - _In_ PFN_NUMBER Page, - _Out_opt_ PKIRQL OldIrql); +MiMapPageInHyperSpace(IN PEPROCESS Process, + IN PFN_NUMBER Page, + IN PKIRQL OldIrql); -_Requires_lock_held_(Process->HyperSpaceLock) -_Releases_lock_(Process->HyperSpaceLock) -_IRQL_requires_(DISPATCH_LEVEL) -_When_(OldIrql != MM_NOIRQL, _At_(OldIrql, _IRQL_restores_)) VOID NTAPI -MiUnmapPageInHyperSpace(_In_ PEPROCESS Process, - _In_ PVOID Address, - _In_ KIRQL OldIrql); +MiUnmapPageInHyperSpace(IN PEPROCESS Process, + IN PVOID Address, + IN KIRQL OldIrql); PVOID NTAPI diff --git a/ntoskrnl/mm/ARM3/hypermap.c b/ntoskrnl/mm/ARM3/hypermap.c index 88d1a1ea06c..4113814e6a6 100644 --- a/ntoskrnl/mm/ARM3/hypermap.c +++ b/ntoskrnl/mm/ARM3/hypermap.c @@ -23,24 +23,16 @@ MMPTE HyperTemplatePte; /* PRIVATE FUNCTIONS **********************************************************/ -_Acquires_lock_(Process->HyperSpaceLock) -_When_(OldIrql == 0, _IRQL_requires_(DISPATCH_LEVEL)) -_When_(OldIrql != 0, _IRQL_requires_(PASSIVE_LEVEL)) -_When_(OldIrql != 0, _At_(*OldIrql, _IRQL_saves_)) -_When_(OldIrql != 0, _IRQL_raises_(DISPATCH_LEVEL)) PVOID NTAPI -MiMapPageInHyperSpace(_In_ PEPROCESS Process, - _In_ PFN_NUMBER Page, - _Out_opt_ PKIRQL OldIrql) +MiMapPageInHyperSpace(IN PEPROCESS Process, + IN PFN_NUMBER Page, + IN PKIRQL OldIrql) { MMPTE TempPte; PMMPTE PointerPte; PFN_NUMBER Offset; - ASSERT(((OldIrql != NULL) && (KeGetCurrentIrql() == PASSIVE_LEVEL)) - || ((OldIrql == NULL) && (KeGetCurrentIrql() == DISPATCH_LEVEL))); - // // Never accept page 0 or non-physical pages // @@ -62,10 +54,7 @@ MiMapPageInHyperSpace(_In_ PEPROCESS Process, // Acquire the hyperlock // ASSERT(Process == PsGetCurrentProcess()); - if (OldIrql != NULL) - KeAcquireSpinLock(&Process->HyperSpaceLock, OldIrql); - else - KeAcquireSpinLockAtDpcLevel(&Process->HyperSpaceLock); + KeAcquireSpinLock(&Process->HyperSpaceLock, OldIrql); // // Now get the first free PTE @@ -97,15 +86,11 @@ MiMapPageInHyperSpace(_In_ PEPROCESS Process, return MiPteToAddress(PointerPte); } -_Requires_lock_held_(Process->HyperSpaceLock) -_Releases_lock_(Process->HyperSpaceLock) -_IRQL_requires_(DISPATCH_LEVEL) -_When_(OldIrql != MM_NOIRQL, _At_(OldIrql, _IRQL_restores_)) VOID NTAPI -MiUnmapPageInHyperSpace(_In_ PEPROCESS Process, - _In_ PVOID Address, - _In_ KIRQL OldIrql) +MiUnmapPageInHyperSpace(IN PEPROCESS Process, + IN PVOID Address, + IN KIRQL OldIrql) { ASSERT(Process == PsGetCurrentProcess()); @@ -118,10 +103,7 @@ MiUnmapPageInHyperSpace(_In_ PEPROCESS Process, // Release the hyperlock // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - if (OldIrql == MM_NOIRQL) - KeReleaseSpinLockFromDpcLevel(&Process->HyperSpaceLock); - else - KeReleaseSpinLock(&Process->HyperSpaceLock, OldIrql); + KeReleaseSpinLock(&Process->HyperSpaceLock, OldIrql); } PVOID
3 years, 8 months
1
0
0
0
[reactos] 01/01: [NTOS:MM] Allow MiMapPageInHyperSpace to be called from DISPATCH_LEVEL
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8404d1a6ff897f5210860…
commit 8404d1a6ff897f5210860ba52d70c3a6e86f3fbb Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Wed Apr 7 23:05:51 2021 +0200 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Apr 7 23:09:26 2021 +0200 [NTOS:MM] Allow MiMapPageInHyperSpace to be called from DISPATCH_LEVEL Also annotate it to show its behaviour. --- ntoskrnl/include/internal/mm.h | 21 +++++++++++++++------ ntoskrnl/mm/ARM3/hypermap.c | 34 ++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index 074dbd4e454..4718fcabcc3 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -1011,17 +1011,26 @@ MmZeroPageThread( ); /* hypermap.c *****************************************************************/ +_Acquires_lock_(Process->HyperSpaceLock) +_When_(OldIrql == 0, _IRQL_requires_(DISPATCH_LEVEL)) +_When_(OldIrql != 0, _IRQL_requires_(PASSIVE_LEVEL)) +_When_(OldIrql != 0, _At_(*OldIrql, IRQL_saves_)) +_When_(OldIrql != 0, _IRQL_raises_(DISPATCH_LEVEL)) PVOID NTAPI -MiMapPageInHyperSpace(IN PEPROCESS Process, - IN PFN_NUMBER Page, - IN PKIRQL OldIrql); +MiMapPageInHyperSpace(_In_ PEPROCESS Process, + _In_ PFN_NUMBER Page, + _Out_opt_ PKIRQL OldIrql); +_Requires_lock_held_(Process->HyperSpaceLock) +_Releases_lock_(Process->HyperSpaceLock) +_IRQL_requires_(DISPATCH_LEVEL) +_When_(OldIrql != MM_NOIRQL, _At_(OldIrql, _IRQL_restores_)) VOID NTAPI -MiUnmapPageInHyperSpace(IN PEPROCESS Process, - IN PVOID Address, - IN KIRQL OldIrql); +MiUnmapPageInHyperSpace(_In_ PEPROCESS Process, + _In_ PVOID Address, + _In_ KIRQL OldIrql); PVOID NTAPI diff --git a/ntoskrnl/mm/ARM3/hypermap.c b/ntoskrnl/mm/ARM3/hypermap.c index 4113814e6a6..88d1a1ea06c 100644 --- a/ntoskrnl/mm/ARM3/hypermap.c +++ b/ntoskrnl/mm/ARM3/hypermap.c @@ -23,16 +23,24 @@ MMPTE HyperTemplatePte; /* PRIVATE FUNCTIONS **********************************************************/ +_Acquires_lock_(Process->HyperSpaceLock) +_When_(OldIrql == 0, _IRQL_requires_(DISPATCH_LEVEL)) +_When_(OldIrql != 0, _IRQL_requires_(PASSIVE_LEVEL)) +_When_(OldIrql != 0, _At_(*OldIrql, _IRQL_saves_)) +_When_(OldIrql != 0, _IRQL_raises_(DISPATCH_LEVEL)) PVOID NTAPI -MiMapPageInHyperSpace(IN PEPROCESS Process, - IN PFN_NUMBER Page, - IN PKIRQL OldIrql) +MiMapPageInHyperSpace(_In_ PEPROCESS Process, + _In_ PFN_NUMBER Page, + _Out_opt_ PKIRQL OldIrql) { MMPTE TempPte; PMMPTE PointerPte; PFN_NUMBER Offset; + ASSERT(((OldIrql != NULL) && (KeGetCurrentIrql() == PASSIVE_LEVEL)) + || ((OldIrql == NULL) && (KeGetCurrentIrql() == DISPATCH_LEVEL))); + // // Never accept page 0 or non-physical pages // @@ -54,7 +62,10 @@ MiMapPageInHyperSpace(IN PEPROCESS Process, // Acquire the hyperlock // ASSERT(Process == PsGetCurrentProcess()); - KeAcquireSpinLock(&Process->HyperSpaceLock, OldIrql); + if (OldIrql != NULL) + KeAcquireSpinLock(&Process->HyperSpaceLock, OldIrql); + else + KeAcquireSpinLockAtDpcLevel(&Process->HyperSpaceLock); // // Now get the first free PTE @@ -86,11 +97,15 @@ MiMapPageInHyperSpace(IN PEPROCESS Process, return MiPteToAddress(PointerPte); } +_Requires_lock_held_(Process->HyperSpaceLock) +_Releases_lock_(Process->HyperSpaceLock) +_IRQL_requires_(DISPATCH_LEVEL) +_When_(OldIrql != MM_NOIRQL, _At_(OldIrql, _IRQL_restores_)) VOID NTAPI -MiUnmapPageInHyperSpace(IN PEPROCESS Process, - IN PVOID Address, - IN KIRQL OldIrql) +MiUnmapPageInHyperSpace(_In_ PEPROCESS Process, + _In_ PVOID Address, + _In_ KIRQL OldIrql) { ASSERT(Process == PsGetCurrentProcess()); @@ -103,7 +118,10 @@ MiUnmapPageInHyperSpace(IN PEPROCESS Process, // Release the hyperlock // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); - KeReleaseSpinLock(&Process->HyperSpaceLock, OldIrql); + if (OldIrql == MM_NOIRQL) + KeReleaseSpinLockFromDpcLevel(&Process->HyperSpaceLock); + else + KeReleaseSpinLock(&Process->HyperSpaceLock, OldIrql); } PVOID
3 years, 8 months
1
0
0
0
[reactos] 01/01: [INF] Disable the AddInterface directive temporarily, in order to install volume devices.
by Eric Kohl
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=81fd88e249e28aab275eb…
commit 81fd88e249e28aab275ebd45cd31782051adc13b Author: Eric Kohl <eric.kohl(a)reactos.org> AuthorDate: Wed Apr 7 22:39:47 2021 +0200 Commit: Eric Kohl <eric.kohl(a)reactos.org> CommitDate: Wed Apr 7 22:39:47 2021 +0200 [INF] Disable the AddInterface directive temporarily, in order to install volume devices. CORE-17530 --- media/inf/volume.inf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/inf/volume.inf b/media/inf/volume.inf index 69a0b59aee4..c4f99022316 100644 --- a/media/inf/volume.inf +++ b/media/inf/volume.inf @@ -34,7 +34,7 @@ HKR, , SilentInstall, 0, "1" [VolumeInstall] [VolumeInstall.Interfaces] -AddInterface = {53F5630D-B6BF-11D0-94F2-00A0C91EFb8B} +;AddInterface = {53F5630D-B6BF-11D0-94F2-00A0C91EFb8B} ;-------------------------------- STRINGS -------------------------------
3 years, 8 months
1
0
0
0
← Newer
1
...
11
12
13
14
15
16
17
18
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Results per page:
10
25
50
100
200