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
February 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
30 participants
434 discussions
Start a n
N
ew thread
[reactos] 87/100: [NTOS:MM] Use 64-bit integer to count references on segments
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3e43aa1305fa2865c3e61…
commit 3e43aa1305fa2865c3e61647e5c51857c9a1c9fd Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Wed Jan 27 16:20:08 2021 +0100 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 [NTOS:MM] Use 64-bit integer to count references on segments --- ntoskrnl/include/internal/mm.h | 8 +++++--- ntoskrnl/mm/rmap.c | 2 +- ntoskrnl/mm/section.c | 25 +++---------------------- 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index dad1a08bf33..86ed4dfb23a 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -168,7 +168,7 @@ typedef struct _MM_SECTION_SEGMENT FAST_MUTEX Lock; /* lock which protects the page directory */ LARGE_INTEGER RawLength; /* length of the segment which is part of the mapped file */ LARGE_INTEGER Length; /* absolute length of the segment */ - PULONG ReferenceCount; + PLONG64 ReferenceCount; ULONG SectionCount; ULONG Protection; PULONG Flags; @@ -182,9 +182,11 @@ typedef struct _MM_SECTION_SEGMENT ULONG Characteristics; } Image; - ULONG RefCount; + LONG64 RefCount; ULONG SegFlags; + ULONGLONG LastPage; + RTL_GENERIC_TABLE PageTable; } MM_SECTION_SEGMENT, *PMM_SECTION_SEGMENT; @@ -192,7 +194,7 @@ typedef struct _MM_IMAGE_SECTION_OBJECT { PFILE_OBJECT FileObject; - ULONG RefCount; + LONG64 RefCount; ULONG SegFlags; SECTION_IMAGE_INFORMATION ImageInformation; diff --git a/ntoskrnl/mm/rmap.c b/ntoskrnl/mm/rmap.c index f50e680e401..5b7ffe3a3da 100644 --- a/ntoskrnl/mm/rmap.c +++ b/ntoskrnl/mm/rmap.c @@ -525,7 +525,7 @@ MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset) return NULL; } - InterlockedIncrementUL(Result->Segment->ReferenceCount); + InterlockedIncrement64(Result->Segment->ReferenceCount); MiReleasePfnLock(OldIrql); return Result; } diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index a223ba0e302..524b282f606 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -107,7 +107,7 @@ MiGrabDataSection(PSECTION_OBJECT_POINTERS SectionObjectPointer) } ASSERT(Segment->SegFlags & MM_DATAFILE_SEGMENT); - InterlockedIncrementUL(&Segment->RefCount); + InterlockedIncrement64(&Segment->RefCount); break; } @@ -996,7 +996,7 @@ MmDereferenceSegment(PMM_SECTION_SEGMENT Segment) /* Lock the PFN lock because we mess around with SectionObjectPointers */ OldIrql = MiAcquirePfnLock(); - if (InterlockedDecrementUL(Segment->ReferenceCount) > 0) + if (InterlockedDecrement64(Segment->ReferenceCount) > 0) { /* Nothing to do yet */ MiReleasePfnLock(OldIrql); @@ -2049,25 +2049,6 @@ MmpDeleteSection(PVOID ObjectBody) ASSERT(ImageSectionObject->RefCount > 0); MmDereferenceSegment(ImageSectionObject->Segments); } -#ifdef NEWCC - else if (Section->Segment && Section->Segment->Flags & MM_DATAFILE_SEGMENT) - { - ULONG RefCount = 0; - PMM_SECTION_SEGMENT Segment = Section->Segment; - - if (Segment && - (RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0) - { - DPRINT("Freeing section segment\n"); - Section->Segment = NULL; - MmFinalizeSegment(Segment); - } - else - { - DPRINT("RefCount %d\n", RefCount); - } - } -#endif else { PMM_SECTION_SEGMENT Segment = (PMM_SECTION_SEGMENT)Section->Segment; @@ -3339,7 +3320,7 @@ MmMapViewOfSegment( return(Status); } - InterlockedIncrementUL(Segment->ReferenceCount); + InterlockedIncrement64(Segment->ReferenceCount); MArea->SectionData.Segment = Segment; MArea->SectionData.ViewOffset.QuadPart = ViewOffset;
3 years, 10 months
1
0
0
0
[reactos] 86/100: [NTOS:CC] Make sure to purge the Mm side in CcPurgeCacheSection
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=cc6bc02b916cd2084c9aa…
commit cc6bc02b916cd2084c9aa8ef5efccfdc7f14d7a4 Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Wed Jan 27 16:19:07 2021 +0100 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 [NTOS:CC] Make sure to purge the Mm side in CcPurgeCacheSection --- ntoskrnl/cc/fs.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ntoskrnl/cc/fs.c b/ntoskrnl/cc/fs.c index 161833d14e2..bef6502f73f 100644 --- a/ntoskrnl/cc/fs.c +++ b/ntoskrnl/cc/fs.c @@ -180,7 +180,10 @@ CcPurgeCacheSection ( SharedCacheMap = SectionObjectPointer->SharedCacheMap; if (!SharedCacheMap) - return FALSE; + { + Success = TRUE; + goto purgeMm; + } StartOffset = FileOffset != NULL ? FileOffset->QuadPart : 0; if (Length == 0 || FileOffset == NULL) @@ -257,6 +260,11 @@ CcPurgeCacheSection ( ASSERT(Refs == 0); } + /* Now make sure that Mm doesn't hold some pages here. */ +purgeMm: + if (Success) + Success = MmPurgeSegment(SectionObjectPointer, FileOffset, Length); + return Success; }
3 years, 10 months
1
0
0
0
[reactos] 85/100: [NTOS:CC] Be sure to flush the whole file in CcFlushCache
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d0bf98663b198696a936d…
commit d0bf98663b198696a936dc6f8c4921db282f4bee Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Wed Jan 27 15:29:57 2021 +0100 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 [NTOS:CC] Be sure to flush the whole file in CcFlushCache --- ntoskrnl/cc/view.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index 06ec86788a9..591168eeba0 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -906,12 +906,19 @@ CcFlushCache ( CCTRACE(CC_API_DEBUG, "SectionObjectPointers=%p FileOffset=0x%I64X Length=%lu\n", SectionObjectPointers, FileOffset ? FileOffset->QuadPart : 0LL, Length); - if (!SectionObjectPointers || !SectionObjectPointers->SharedCacheMap) + if (!SectionObjectPointers) { Status = STATUS_INVALID_PARAMETER; goto quit; } + if (!SectionObjectPointers->SharedCacheMap) + { + /* Forward this to Mm */ + MmFlushSegment(SectionObjectPointers, FileOffset, Length, IoStatus); + return; + } + SharedCacheMap = SectionObjectPointers->SharedCacheMap; ASSERT(SharedCacheMap); if (FileOffset) @@ -934,8 +941,14 @@ CcFlushCache ( IoStatus->Information = 0; } + /* + * We flush the VACBs that we find here. + * If there is no (dirty) VACB, it doesn't mean that there is no data to flush, so we call Mm to be sure. + * This is suboptimal, but this is due to the lack of granularity of how we track dirty cache data + */ while (FlushStart < FlushEnd) { + BOOLEAN DirtyVacb = FALSE; PROS_VACB vacb = CcRosLookupVacb(SharedCacheMap, FlushStart); if (vacb != NULL) @@ -947,6 +960,7 @@ CcFlushCache ( { goto quit; } + DirtyVacb = TRUE; } CcRosReleaseVacb(SharedCacheMap, vacb, FALSE, FALSE); @@ -955,11 +969,39 @@ CcFlushCache ( IoStatus->Information += VACB_MAPPING_GRANULARITY; } + if (!DirtyVacb) + { + IO_STATUS_BLOCK MmIosb; + LARGE_INTEGER MmOffset; + + MmOffset.QuadPart = FlushStart; + + if (FlushEnd - (FlushEnd % VACB_MAPPING_GRANULARITY) <= FlushStart) + { + /* The whole range fits within a VACB chunk. */ + Status = MmFlushSegment(SectionObjectPointers, &MmOffset, FlushEnd - FlushStart, &MmIosb); + } + else + { + ULONG MmLength = VACB_MAPPING_GRANULARITY - (FlushStart % VACB_MAPPING_GRANULARITY); + Status = MmFlushSegment(SectionObjectPointers, &MmOffset, MmLength, &MmIosb); + } + + if (!NT_SUCCESS(Status)) + goto quit; + + if (IoStatus) + IoStatus->Information += MmIosb.Information; + } + if (!NT_SUCCESS(RtlLongLongAdd(FlushStart, VACB_MAPPING_GRANULARITY, &FlushStart))) { /* We're at the end of file ! */ break; } + + /* Round down to next VACB start now */ + FlushStart -= FlushStart % VACB_MAPPING_GRANULARITY; } quit:
3 years, 10 months
1
0
0
0
[reactos] 84/100: [NTOS:MM] Introduce MmPurgeSegment & MmFlushSegment
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=90c6a65efe7384269f27f…
commit 90c6a65efe7384269f27fe419e164868c8654fff Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Wed Jan 27 13:03:06 2021 +0100 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 [NTOS:MM] Introduce MmPurgeSegment & MmFlushSegment Those will back CcFlushCache and CcPurgeCache. --- ntoskrnl/include/internal/mm.h | 25 ++++- ntoskrnl/mm/section.c | 241 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 247 insertions(+), 19 deletions(-) diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index bd9ea25e0b7..dad1a08bf33 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -1241,10 +1241,14 @@ MmFindRegion( #define DIRTY_SSE(E) ((E) | 2) #define CLEAN_SSE(E) ((E) & ~2) #define IS_DIRTY_SSE(E) ((E) & 2) +#define WRITE_SSE(E) ((E) | 4) +#define IS_WRITE_SSE(E) ((E) & 4) #define PAGE_FROM_SSE(E) ((E) & 0xFFFFF000) -#define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFC) >> 2) -#define MAX_SHARE_COUNT 0x3FF -#define MAKE_SSE(P, C) ((ULONG_PTR)((P) | ((C) << 2))) +#define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFC) >> 3) +#define MAX_SHARE_COUNT 0x1FF +#define MAKE_SSE(P, C) ((ULONG_PTR)((P) | ((C) << 3))) +#define BUMPREF_SSE(E) (PAGE_FROM_SSE(E) | ((SHARE_COUNT_FROM_SSE(E) + 1) << 3) | ((E) & 0x7)) +#define DECREF_SSE(E) (PAGE_FROM_SSE(E) | ((SHARE_COUNT_FROM_SSE(E) - 1) << 3) | ((E) & 0x7)) VOID NTAPI @@ -1375,6 +1379,21 @@ MmRosFlushVirtualMemory( _Inout_ PSIZE_T Length, _Out_ PIO_STATUS_BLOCK Iosb); +NTSTATUS +NTAPI +MmFlushSegment( + _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, + _In_opt_ PLARGE_INTEGER Offset, + _In_ ULONG Length, + _In_opt_ PIO_STATUS_BLOCK Iosb); + +BOOLEAN +NTAPI +MmPurgeSegment( + _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, + _In_opt_ PLARGE_INTEGER Offset, + _In_ ULONG Length); + BOOLEAN NTAPI MmCheckDirtySegment( diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index 7ff5485ae81..a223ba0e302 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -60,6 +60,8 @@ extern MMSESSION MmSession; +static LARGE_INTEGER TinyTime = {{-1L, -1L}}; + #ifndef NEWCC KEVENT MmWaitPageEvent; @@ -83,6 +85,37 @@ _MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line) } #endif +static +PMM_SECTION_SEGMENT +MiGrabDataSection(PSECTION_OBJECT_POINTERS SectionObjectPointer) +{ + KIRQL OldIrql = MiAcquirePfnLock(); + PMM_SECTION_SEGMENT Segment = NULL; + + while (TRUE) + { + Segment = SectionObjectPointer->DataSectionObject; + if (!Segment) + break; + + if (Segment->SegFlags & (MM_SEGMENT_INCREATE | MM_SEGMENT_INDELETE)) + { + MiReleasePfnLock(OldIrql); + KeDelayExecutionThread(KernelMode, FALSE, &TinyTime); + OldIrql = MiAcquirePfnLock(); + continue; + } + + ASSERT(Segment->SegFlags & MM_DATAFILE_SEGMENT); + InterlockedIncrementUL(&Segment->RefCount); + break; + } + + MiReleasePfnLock(OldIrql); + + return Segment; +} + /* Somewhat grotesque, but eh... */ PMM_IMAGE_SECTION_OBJECT ImageSectionObjectFromSegment(PMM_SECTION_SEGMENT Segment) { @@ -1028,7 +1061,6 @@ MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset) { ULONG_PTR Entry; - BOOLEAN Dirty; Entry = MmGetPageEntrySectionSegment(Segment, Offset); if (Entry == 0) @@ -1045,11 +1077,7 @@ MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, { KeBugCheck(MEMORY_MANAGEMENT); } - Dirty = IS_DIRTY_SSE(Entry); - Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) + 1); - if (Dirty) - Entry = DIRTY_SSE(Entry); - MmSetPageEntrySectionSegment(Segment, Offset, Entry); + MmSetPageEntrySectionSegment(Segment, Offset, BUMPREF_SSE(Entry)); } BOOLEAN @@ -1080,8 +1108,7 @@ MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea, { KeBugCheck(MEMORY_MANAGEMENT); } - Dirty = Dirty || IS_DIRTY_SSE(Entry); - Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) - 1); + Entry = DECREF_SSE(Entry); if (Dirty) Entry = DIRTY_SSE(Entry); if (SHARE_COUNT_FROM_SSE(Entry) > 0) @@ -1094,7 +1121,7 @@ MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea, return FALSE; } - if (Dirty && (MemoryArea->VadNode.u.VadFlags.VadType != VadImageMap)) + if (IS_DIRTY_SSE(Entry) && (MemoryArea->VadNode.u.VadFlags.VadType != VadImageMap)) { ASSERT(!Segment->WriteCopy); ASSERT(MmGetSavedSwapEntryPage(Page) == 0); @@ -1105,10 +1132,10 @@ MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea, } /* Only valid case for shared dirty pages is shared image section */ - ASSERT(!Dirty || (Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)); + ASSERT(!IS_DIRTY_SSE(Entry) || (Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)); SwapEntry = MmGetSavedSwapEntryPage(Page); - if (Dirty && !SwapEntry) + if (IS_DIRTY_SSE(Entry) && !SwapEntry) { SwapEntry = MmAllocSwapPage(); if (!SwapEntry) @@ -1119,7 +1146,7 @@ MmUnsharePageEntrySectionSegment(PMEMORY_AREA MemoryArea, } } - if (Dirty) + if (IS_DIRTY_SSE(Entry)) { NTSTATUS Status = MmWriteToSwapPage(SwapEntry, Page); if (!NT_SUCCESS(Status)) @@ -4703,6 +4730,185 @@ MmRosFlushVirtualMemory( return STATUS_SUCCESS; } +/* Like CcPurgeCache but for the in-memory segment */ +BOOLEAN +NTAPI +MmPurgeSegment( + _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, + _In_opt_ PLARGE_INTEGER Offset, + _In_ ULONG Length) +{ + LARGE_INTEGER PurgeStart, PurgeEnd; + PMM_SECTION_SEGMENT Segment; + + Segment = MiGrabDataSection(SectionObjectPointer); + if (!Segment) + { + /* Nothing to purge */ + return STATUS_SUCCESS; + } + + PurgeStart.QuadPart = Offset ? Offset->QuadPart : 0LL; + if (Length && Offset) + { + if (!NT_SUCCESS(RtlLongLongAdd(PurgeStart.QuadPart, Length, &PurgeEnd.QuadPart))) + return FALSE; + } + + MmLockSectionSegment(Segment); + + if (!Length || !Offset) + { + /* We must calculate the length for ourselves */ + /* FIXME: All of this is suboptimal */ + ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable); + /* No page. Nothing to purge */ + if (!ElemCount) + { + MmUnlockSectionSegment(Segment); + MmDereferenceSegment(Segment); + return TRUE; + } + + PCACHE_SECTION_PAGE_TABLE PageTable = RtlGetElementGenericTable(&Segment->PageTable, ElemCount - 1); + PurgeEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE; + } + + while (PurgeStart.QuadPart < PurgeEnd.QuadPart) + { + ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, &PurgeStart); + + if (Entry == 0) + { + PurgeStart.QuadPart += PAGE_SIZE; + continue; + } + + if (IS_SWAP_FROM_SSE(Entry)) + { + ASSERT(SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY); + /* The page is currently being read. Meaning someone will need it soon. Bad luck */ + MmUnlockSectionSegment(Segment); + MmDereferenceSegment(Segment); + return FALSE; + } + + if (IS_WRITE_SSE(Entry)) + { + /* We're trying to purge an entry which is being written. Restart this loop iteration */ + MmUnlockSectionSegment(Segment); + KeDelayExecutionThread(KernelMode, FALSE, &TinyTime); + MmLockSectionSegment(Segment); + continue; + } + + if (SHARE_COUNT_FROM_SSE(Entry) > 0) + { + /* This page is currently in use. Bad luck */ + MmUnlockSectionSegment(Segment); + MmDereferenceSegment(Segment); + return FALSE; + } + + /* We can let this page go */ + MmSetPageEntrySectionSegment(Segment, &PurgeStart, 0); + MmReleasePageMemoryConsumer(MC_USER, PFN_FROM_SSE(Entry)); + + PurgeStart.QuadPart += PAGE_SIZE; + } + + /* This page is currently in use. Bad luck */ + MmUnlockSectionSegment(Segment); + MmDereferenceSegment(Segment); + return TRUE; +} + +NTSTATUS +NTAPI +MmFlushSegment( + _In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, + _In_opt_ PLARGE_INTEGER Offset, + _In_ ULONG Length, + _In_opt_ PIO_STATUS_BLOCK Iosb) +{ + LARGE_INTEGER FlushStart, FlushEnd; + NTSTATUS Status; + + if (Offset) + { + FlushStart = *Offset; + Status = RtlLongLongAdd(FlushStart.QuadPart, Length, &FlushEnd.QuadPart); + if (!NT_SUCCESS(Status)) + return Status; + } + + if (Iosb) + Iosb->Information = 0; + + PMM_SECTION_SEGMENT Segment = MiGrabDataSection(SectionObjectPointer); + if (!Segment) + { + /* Nothing to flush */ + if (Iosb) + Iosb->Status = STATUS_SUCCESS; + return STATUS_SUCCESS; + } + + ASSERT(*Segment->Flags & MM_DATAFILE_SEGMENT); + + MmLockSectionSegment(Segment); + + if (!Offset) + { + FlushStart.QuadPart = 0; + + /* FIXME: All of this is suboptimal */ + ULONG ElemCount = RtlNumberGenericTableElements(&Segment->PageTable); + /* No page. Nothing to flush */ + if (!ElemCount) + { + MmUnlockSectionSegment(Segment); + MmDereferenceSegment(Segment); + if (Iosb) + { + Iosb->Status = STATUS_SUCCESS; + Iosb->Information = 0; + } + return STATUS_SUCCESS; + } + + PCACHE_SECTION_PAGE_TABLE PageTable = RtlGetElementGenericTable(&Segment->PageTable, ElemCount - 1); + FlushEnd.QuadPart = PageTable->FileOffset.QuadPart + _countof(PageTable->PageEntries) * PAGE_SIZE; + } + + FlushStart.QuadPart >>= PAGE_SHIFT; + FlushStart.QuadPart <<= PAGE_SHIFT; + + while (FlushStart.QuadPart < FlushEnd.QuadPart) + { + ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, &FlushStart); + + if (IS_DIRTY_SSE(Entry)) + { + MmCheckDirtySegment(Segment, &FlushStart, FALSE, FALSE); + + if (Iosb) + Iosb->Information += PAGE_SIZE; + } + + FlushStart.QuadPart += PAGE_SIZE; + } + + MmUnlockSectionSegment(Segment); + + MmDereferenceSegment(Segment); + + if (Iosb) + Iosb->Status = STATUS_SUCCESS; + + return STATUS_SUCCESS; +} + _Requires_exclusive_lock_held_(Segment->Lock) BOOLEAN NTAPI @@ -4718,6 +4924,8 @@ MmCheckDirtySegment( ASSERT(Segment->Locked); + ASSERT((Offset->QuadPart % PAGE_SIZE) == 0); + DPRINT("Checking segment for file %wZ at offset 0x%I64X.\n", &Segment->FileObject->FileName, Offset->QuadPart); Entry = MmGetPageEntrySectionSegment(Segment, Offset); @@ -4733,9 +4941,10 @@ MmCheckDirtySegment( ASSERT(!Segment->WriteCopy); ASSERT(Segment->SegFlags & MM_DATAFILE_SEGMENT); - /* Insert the cleaned entry back. Keep one ref to the page so nobody pages it out again behind us */ - MmSetPageEntrySectionSegment(Segment, Offset, - MAKE_SSE(Page << PAGE_SHIFT, SHARE_COUNT_FROM_SSE(Entry) + 1)); + /* Insert the cleaned entry back. Mark it as write in progress, and clear the dirty bit. */ + Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) + 1); + Entry = WRITE_SSE(Entry); + MmSetPageEntrySectionSegment(Segment, Offset, Entry); /* Tell the other users that we are clean again */ MmSetCleanAllRmaps(Page); @@ -4772,7 +4981,7 @@ MmCheckDirtySegment( DirtyAgain = IS_DIRTY_SSE(Entry) || MmIsDirtyPageRmap(Page); } - /* Drop the reference we got */ + /* Drop the reference we got, deleting the write altogether. */ Entry = MAKE_SSE(Page << PAGE_SHIFT, SHARE_COUNT_FROM_SSE(Entry) - 1); if (DirtyAgain) {
3 years, 10 months
1
0
0
0
[reactos] 83/100: [NTOS:MM] Make the page LRU list a real LRU list.
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8a8b4db447c36232addbe…
commit 8a8b4db447c36232addbe4693953182d355c0408 Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Wed Jan 27 10:29:07 2021 +0100 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 [NTOS:MM] Make the page LRU list a real LRU list. Also, implement flushing mapped sections to disk on shutdown. --- ntoskrnl/cache/section/newmm.h | 57 -------------- ntoskrnl/include/internal/mm.h | 69 ++++++++++++++--- ntoskrnl/mm/balance.c | 27 +++---- ntoskrnl/mm/freelist.c | 164 ++++++++++++++++++++++++++--------------- ntoskrnl/mm/mminit.c | 3 - ntoskrnl/mm/shutdown.c | 38 ++++++++++ 6 files changed, 214 insertions(+), 144 deletions(-) diff --git a/ntoskrnl/cache/section/newmm.h b/ntoskrnl/cache/section/newmm.h index edff99f3d85..3fb731c6ace 100644 --- a/ntoskrnl/cache/section/newmm.h +++ b/ntoskrnl/cache/section/newmm.h @@ -3,22 +3,6 @@ #include <internal/arch/mm.h> /* TYPES *********************************************************************/ - -#define PFN_FROM_SSE(E) ((PFN_NUMBER)((E) >> PAGE_SHIFT)) -#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001) -#define MM_IS_WAIT_PTE(E) \ - (IS_SWAP_FROM_SSE(E) && SWAPENTRY_FROM_SSE(E) == MM_WAIT_ENTRY) -#define MAKE_PFN_SSE(P) ((ULONG_PTR)((P) << PAGE_SHIFT)) -#define SWAPENTRY_FROM_SSE(E) ((E) >> 1) -#define MAKE_SWAP_SSE(S) (((ULONG_PTR)(S) << 1) | 0x1) -#define DIRTY_SSE(E) ((E) | 2) -#define CLEAN_SSE(E) ((E) & ~2) -#define IS_DIRTY_SSE(E) ((E) & 2) -#define PAGE_FROM_SSE(E) ((E) & 0xFFFFF000) -#define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFC) >> 2) -#define MAX_SHARE_COUNT 0x3FF -#define MAKE_SSE(P, C) ((ULONG_PTR)((P) | ((C) << 2))) - #define MM_SEGMENT_FINALIZE (0x40000000) #define RMAP_SEGMENT_MASK ~((ULONG_PTR)0xff) @@ -123,25 +107,6 @@ VOID NTAPI MiInitializeSectionPageTable(PMM_SECTION_SEGMENT Segment); -NTSTATUS -NTAPI -_MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, - PLARGE_INTEGER Offset, - ULONG_PTR Entry, - const char *file, - int line); - -ULONG_PTR -NTAPI -_MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, - PLARGE_INTEGER Offset, - const char *file, - int line); - -#define MmSetPageEntrySectionSegment(S,O,E) _MmSetPageEntrySectionSegment(S,O,E,__FILE__,__LINE__) - -#define MmGetPageEntrySectionSegment(S,O) _MmGetPageEntrySectionSegment(S,O,__FILE__,__LINE__) - typedef VOID (NTAPI *FREE_SECTION_PAGE_FUN)( PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset); @@ -151,12 +116,6 @@ NTAPI MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage); -/* Yields a lock */ -PMM_SECTION_SEGMENT -NTAPI -MmGetSectionAssociation(PFN_NUMBER Page, - PLARGE_INTEGER Offset); - NTSTATUS NTAPI MmSetSectionAssociation(PFN_NUMBER Page, @@ -267,22 +226,6 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address); -VOID -NTAPI -_MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, - const char *file, - int line); - -#define MmLockSectionSegment(x) _MmLockSectionSegment(x,__FILE__,__LINE__) - -VOID -NTAPI -_MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, - const char *file, - int line); - -#define MmUnlockSectionSegment(x) _MmUnlockSectionSegment(x,__FILE__,__LINE__) - VOID MmFreeCacheSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index 4db21f72199..bd9ea25e0b7 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -357,6 +357,8 @@ typedef struct _MMPFN // HACK until WS lists are supported MMWSLE Wsle; + struct _MMPFN* NextLRU; + struct _MMPFN* PreviousLRU; } MMPFN, *PMMPFN; extern PMMPFN MmPfnDatabase; @@ -877,6 +879,11 @@ NTSTATUS NTAPI MmPageOutPhysicalAddress(PFN_NUMBER Page); +PMM_SECTION_SEGMENT +NTAPI +MmGetSectionAssociation(PFN_NUMBER Page, + PLARGE_INTEGER Offset); + /* freelist.c **********************************************************/ FORCEINLINE @@ -950,20 +957,12 @@ MiGetPfnEntryIndex(IN PMMPFN Pfn1) PFN_NUMBER NTAPI -MmGetLRUNextUserPage(PFN_NUMBER PreviousPage); +MmGetLRUNextUserPage(PFN_NUMBER PreviousPage, BOOLEAN MoveToLast); PFN_NUMBER NTAPI MmGetLRUFirstUserPage(VOID); -VOID -NTAPI -MmInsertLRULastUserPage(PFN_NUMBER Page); - -VOID -NTAPI -MmRemoveLRUUserPage(PFN_NUMBER Page); - VOID NTAPI MmDumpArmPfnDatabase( @@ -1232,6 +1231,37 @@ MmFindRegion( /* section.c *****************************************************************/ +#define PFN_FROM_SSE(E) ((PFN_NUMBER)((E) >> PAGE_SHIFT)) +#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001) +#define MM_IS_WAIT_PTE(E) \ + (IS_SWAP_FROM_SSE(E) && SWAPENTRY_FROM_SSE(E) == MM_WAIT_ENTRY) +#define MAKE_PFN_SSE(P) ((ULONG_PTR)((P) << PAGE_SHIFT)) +#define SWAPENTRY_FROM_SSE(E) ((E) >> 1) +#define MAKE_SWAP_SSE(S) (((ULONG_PTR)(S) << 1) | 0x1) +#define DIRTY_SSE(E) ((E) | 2) +#define CLEAN_SSE(E) ((E) & ~2) +#define IS_DIRTY_SSE(E) ((E) & 2) +#define PAGE_FROM_SSE(E) ((E) & 0xFFFFF000) +#define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFC) >> 2) +#define MAX_SHARE_COUNT 0x3FF +#define MAKE_SSE(P, C) ((ULONG_PTR)((P) | ((C) << 2))) + +VOID +NTAPI +_MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, + const char *file, + int line); + +#define MmLockSectionSegment(x) _MmLockSectionSegment(x,__FILE__,__LINE__) + +VOID +NTAPI +_MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, + const char *file, + int line); + +#define MmUnlockSectionSegment(x) _MmUnlockSectionSegment(x,__FILE__,__LINE__) + VOID NTAPI MmGetImageInformation( @@ -1372,6 +1402,27 @@ MmExtendSection( _In_ PVOID Section, _Inout_ PLARGE_INTEGER NewSize); +/* sptab.c *******************************************************************/ + +NTSTATUS +NTAPI +_MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, + PLARGE_INTEGER Offset, + ULONG_PTR Entry, + const char *file, + int line); + +ULONG_PTR +NTAPI +_MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, + PLARGE_INTEGER Offset, + const char *file, + int line); + +#define MmSetPageEntrySectionSegment(S,O,E) _MmSetPageEntrySectionSegment(S,O,E,__FILE__,__LINE__) + +#define MmGetPageEntrySectionSegment(S,O) _MmGetPageEntrySectionSegment(S,O,__FILE__,__LINE__) + /* sysldr.c ******************************************************************/ VOID diff --git a/ntoskrnl/mm/balance.c b/ntoskrnl/mm/balance.c index 34dddf5dbfa..f9067c58a13 100644 --- a/ntoskrnl/mm/balance.c +++ b/ntoskrnl/mm/balance.c @@ -80,11 +80,7 @@ MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page) KeBugCheck(MEMORY_MANAGEMENT); } - if (MmGetReferenceCountPage(Page) == 1) - { - if(Consumer == MC_USER) MmRemoveLRUUserPage(Page); - (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed); - } + (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed); MmDereferencePage(Page); @@ -142,7 +138,6 @@ NTSTATUS MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages) { PFN_NUMBER CurrentPage; - PFN_NUMBER NextPage; NTSTATUS Status; (*NrFreedPages) = 0; @@ -158,13 +153,14 @@ MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages) (*NrFreedPages)++; } - NextPage = MmGetLRUNextUserPage(CurrentPage); - if (NextPage <= CurrentPage) - { - /* We wrapped around, so we're done */ - break; - } - CurrentPage = NextPage; + CurrentPage = MmGetLRUNextUserPage(CurrentPage, TRUE); + } + + if (CurrentPage) + { + KIRQL OldIrql = MiAcquirePfnLock(); + MmDereferencePage(CurrentPage); + MiReleasePfnLock(OldIrql); } return STATUS_SUCCESS; @@ -209,14 +205,13 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, /* * Allocate always memory for the non paged pool and for the pager thread. */ - if ((Consumer == MC_SYSTEM) /* || MiIsBalancerThread() */) + if (Consumer == MC_SYSTEM) { Page = MmAllocPage(Consumer); if (Page == 0) { KeBugCheck(NO_PAGES_AVAILABLE); } - if (Consumer == MC_USER) MmInsertLRULastUserPage(Page); *AllocatedPage = Page; if (MmAvailablePages < MiMinimumAvailablePages) MmRebalanceMemoryConsumers(); @@ -257,7 +252,6 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, KeBugCheck(NO_PAGES_AVAILABLE); } - if(Consumer == MC_USER) MmInsertLRULastUserPage(Page); *AllocatedPage = Page; if (MmAvailablePages < MiMinimumAvailablePages) @@ -276,7 +270,6 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, { KeBugCheck(NO_PAGES_AVAILABLE); } - if(Consumer == MC_USER) MmInsertLRULastUserPage(Page); *AllocatedPage = Page; if (MmAvailablePages < MiMinimumAvailablePages) diff --git a/ntoskrnl/mm/freelist.c b/ntoskrnl/mm/freelist.c index 5cc22ce38b1..35c6336dcc6 100644 --- a/ntoskrnl/mm/freelist.c +++ b/ntoskrnl/mm/freelist.c @@ -35,95 +35,127 @@ SIZE_T MmPagedPoolCommit; SIZE_T MmPeakCommitment; SIZE_T MmtotalCommitLimitMaximum; -static RTL_BITMAP MiUserPfnBitMap; +PMMPFN FirstUserLRUPfn; +PMMPFN LastUserLRUPfn; /* FUNCTIONS *************************************************************/ -VOID -NTAPI -MiInitializeUserPfnBitmap(VOID) -{ - PVOID Bitmap; - - /* Allocate enough buffer for the PFN bitmap and align it on 32-bits */ - Bitmap = ExAllocatePoolWithTag(NonPagedPool, - (((MmHighestPhysicalPage + 1) + 31) / 32) * 4, - TAG_MM); - ASSERT(Bitmap); - - /* Initialize it and clear all the bits to begin with */ - RtlInitializeBitMap(&MiUserPfnBitMap, - Bitmap, - (ULONG)MmHighestPhysicalPage + 1); - RtlClearAllBits(&MiUserPfnBitMap); -} - PFN_NUMBER NTAPI MmGetLRUFirstUserPage(VOID) { - ULONG Position; + PFN_NUMBER Page; KIRQL OldIrql; /* Find the first user page */ OldIrql = MiAcquirePfnLock(); - Position = RtlFindSetBits(&MiUserPfnBitMap, 1, 0); + + if (FirstUserLRUPfn == NULL) + { + MiReleasePfnLock(OldIrql); + return 0; + } + + Page = MiGetPfnEntryIndex(FirstUserLRUPfn); + MmReferencePage(Page); + MiReleasePfnLock(OldIrql); - if (Position == 0xFFFFFFFF) return 0; - /* Return it */ - ASSERT(Position != 0); - ASSERT_IS_ROS_PFN(MiGetPfnEntry(Position)); - return Position; + return Page; } +static VOID -NTAPI -MmInsertLRULastUserPage(PFN_NUMBER Pfn) +MmInsertLRULastUserPage(PFN_NUMBER Page) { - KIRQL OldIrql; + MI_ASSERT_PFN_LOCK_HELD(); - /* Set the page as a user page */ - ASSERT(Pfn != 0); - ASSERT_IS_ROS_PFN(MiGetPfnEntry(Pfn)); - ASSERT(!RtlCheckBit(&MiUserPfnBitMap, (ULONG)Pfn)); - OldIrql = MiAcquirePfnLock(); - RtlSetBit(&MiUserPfnBitMap, (ULONG)Pfn); - MiReleasePfnLock(OldIrql); -} + PMMPFN Pfn = MiGetPfnEntry(Page); -PFN_NUMBER -NTAPI -MmGetLRUNextUserPage(PFN_NUMBER PreviousPfn) -{ - ULONG Position; - KIRQL OldIrql; + if (FirstUserLRUPfn == NULL) + FirstUserLRUPfn = Pfn; - /* Find the next user page */ - OldIrql = MiAcquirePfnLock(); - Position = RtlFindSetBits(&MiUserPfnBitMap, 1, (ULONG)PreviousPfn + 1); - MiReleasePfnLock(OldIrql); - if (Position == 0xFFFFFFFF) return 0; + Pfn->PreviousLRU = LastUserLRUPfn; - /* Return it */ - ASSERT(Position != 0); - ASSERT_IS_ROS_PFN(MiGetPfnEntry(Position)); - return Position; + if (LastUserLRUPfn != NULL) + LastUserLRUPfn->NextLRU = Pfn; + LastUserLRUPfn = Pfn; } +static VOID -NTAPI MmRemoveLRUUserPage(PFN_NUMBER Page) { - KIRQL OldIrql; + MI_ASSERT_PFN_LOCK_HELD(); /* Unset the page as a user page */ ASSERT(Page != 0); - ASSERT_IS_ROS_PFN(MiGetPfnEntry(Page)); - ASSERT(RtlCheckBit(&MiUserPfnBitMap, (ULONG)Page)); + + PMMPFN Pfn = MiGetPfnEntry(Page); + + ASSERT_IS_ROS_PFN(Pfn); + + if (Pfn->PreviousLRU) + { + ASSERT(Pfn->PreviousLRU->NextLRU == Pfn); + Pfn->PreviousLRU->NextLRU = Pfn->NextLRU; + } + else + { + ASSERT(FirstUserLRUPfn == Pfn); + FirstUserLRUPfn = Pfn->NextLRU; + } + + if (Pfn->NextLRU) + { + ASSERT(Pfn->NextLRU->PreviousLRU == Pfn); + Pfn->NextLRU->PreviousLRU = Pfn->PreviousLRU; + } + else + { + ASSERT(Pfn == LastUserLRUPfn); + LastUserLRUPfn = Pfn->PreviousLRU; + } + + Pfn->PreviousLRU = Pfn->NextLRU = NULL; +} + +PFN_NUMBER +NTAPI +MmGetLRUNextUserPage(PFN_NUMBER PreviousPage, BOOLEAN MoveToLast) +{ + PFN_NUMBER Page = 0; + KIRQL OldIrql; + + /* Find the next user page */ OldIrql = MiAcquirePfnLock(); - RtlClearBit(&MiUserPfnBitMap, (ULONG)Page); + + PMMPFN PreviousPfn = MiGetPfnEntry(PreviousPage); + PMMPFN NextPfn = PreviousPfn->NextLRU; + + /* + * Move this one at the end of the list. + * It may be freed by MmDereferencePage below. + * If it's not, then it means it is still hanging in some process address space. + * This avoids paging-out e.g. ntdll early just because it's mapped first time. + */ + if (MoveToLast) + { + MmRemoveLRUUserPage(PreviousPage); + MmInsertLRULastUserPage(PreviousPage); + } + + if (NextPfn) + { + Page = MiGetPfnEntryIndex(NextPfn); + MmReferencePage(Page); + } + + MmDereferencePage(PreviousPage); + MiReleasePfnLock(OldIrql); + + return Page; } BOOLEAN @@ -548,6 +580,13 @@ MmDereferencePage(PFN_NUMBER Pfn) Pfn1->u3.e2.ReferenceCount--; if (Pfn1->u3.e2.ReferenceCount == 0) { + /* Apply LRU hack */ + if (Pfn1->u4.MustBeCached) + { + MmRemoveLRUUserPage(Pfn); + Pfn1->u4.MustBeCached = 0; + } + /* Mark the page temporarily as valid, we're going to make it free soon */ Pfn1->u3.e1.PageLocation = ActiveAndValid; @@ -590,6 +629,15 @@ MmAllocPage(ULONG Type) Pfn1->u1.SwapEntry = 0; Pfn1->RmapListHead = NULL; + Pfn1->NextLRU = NULL; + Pfn1->PreviousLRU = NULL; + + if (Type == MC_USER) + { + Pfn1->u4.MustBeCached = 1; /* HACK again */ + MmInsertLRULastUserPage(PfnOffset); + } + MiReleasePfnLock(OldIrql); return PfnOffset; } diff --git a/ntoskrnl/mm/mminit.c b/ntoskrnl/mm/mminit.c index 6c1a5f274d6..3e58ad9bbc8 100644 --- a/ntoskrnl/mm/mminit.c +++ b/ntoskrnl/mm/mminit.c @@ -17,8 +17,6 @@ /* GLOBALS *******************************************************************/ -VOID NTAPI MiInitializeUserPfnBitmap(VOID); - BOOLEAN Mm64BitPhysicalAddress = FALSE; ULONG MmReadClusterSize; // @@ -235,7 +233,6 @@ MmInitSystem(IN ULONG Phase, MiDbgDumpAddressSpace(); MmInitGlobalKernelPageDirectory(); - MiInitializeUserPfnBitmap(); MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory); MmInitializeRmapList(); MmInitSectionImplementation(); diff --git a/ntoskrnl/mm/shutdown.c b/ntoskrnl/mm/shutdown.c index c80cc527a30..89beca88fac 100644 --- a/ntoskrnl/mm/shutdown.c +++ b/ntoskrnl/mm/shutdown.c @@ -21,6 +21,44 @@ VOID MiShutdownSystem(VOID) { ULONG i; + PFN_NUMBER Page; + BOOLEAN Dirty; + + /* Loop through all the pages owned by the legacy Mm and page them out, if needed. */ + /* We do it twice, since flushing can cause the FS to dirtify new pages */ + do + { + Dirty = FALSE; + + Page = MmGetLRUFirstUserPage(); + while (Page) + { + LARGE_INTEGER SegmentOffset; + PMM_SECTION_SEGMENT Segment = MmGetSectionAssociation(Page, &SegmentOffset); + + if (Segment) + { + if ((*Segment->Flags) & MM_DATAFILE_SEGMENT) + { + MmLockSectionSegment(Segment); + + ULONG_PTR Entry = MmGetPageEntrySectionSegment(Segment, &SegmentOffset); + + if (!IS_SWAP_FROM_SSE(Entry) && IS_DIRTY_SSE(Entry)) + { + Dirty = TRUE; + MmCheckDirtySegment(Segment, &SegmentOffset, FALSE, TRUE); + } + + MmUnlockSectionSegment(Segment); + } + + MmDereferenceSegment(Segment); + } + + Page = MmGetLRUNextUserPage(Page, FALSE); + } + } while (Dirty); /* Loop through all the paging files */ for (i = 0; i < MmNumberOfPagingFiles; i++)
3 years, 10 months
1
0
0
0
[reactos] 82/100: [NTOS:FSRTL] Properly leave FsRtl when returning STATUS_CANT_WAIT
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bde2ee571a40808899512…
commit bde2ee571a408088995127ef654e88c9512786bd Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Wed Jan 27 09:22:32 2021 +0100 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 [NTOS:FSRTL] Properly leave FsRtl when returning STATUS_CANT_WAIT --- ntoskrnl/fsrtl/fastio.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ntoskrnl/fsrtl/fastio.c b/ntoskrnl/fsrtl/fastio.c index a056b67e109..ce629f77a02 100644 --- a/ntoskrnl/fsrtl/fastio.c +++ b/ntoskrnl/fsrtl/fastio.c @@ -1714,9 +1714,13 @@ FsRtlAcquireFileForCcFlushEx(IN PFILE_OBJECT FileObject) /* Return either success or inability to wait. In case of other failure - fall through */ - if (Status == STATUS_SUCCESS || - Status == STATUS_CANT_WAIT) + if (NT_SUCCESS(Status)) + return Status; + + if (Status == STATUS_CANT_WAIT) { + DPRINT1("STATUS_CANT_WAIT\n"); + FsRtlExitFileSystem(); return Status; } }
3 years, 10 months
1
0
0
0
[reactos] 81/100: [NTOS:MM] Fix unlocking on failure path
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3efc5b17347ad614cd807…
commit 3efc5b17347ad614cd807535625fbf12ca82a8e6 Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Tue Jan 26 11:21:08 2021 +0100 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 [NTOS:MM] Fix unlocking on failure path --- ntoskrnl/mm/ARM3/section.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ntoskrnl/mm/ARM3/section.c b/ntoskrnl/mm/ARM3/section.c index fddaf752031..aeccb2adf28 100644 --- a/ntoskrnl/mm/ARM3/section.c +++ b/ntoskrnl/mm/ARM3/section.c @@ -1243,6 +1243,8 @@ MiLoadUserSymbols(IN PCONTROL_AREA ControlArea, _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ExFreePoolWithTag(LdrEntry, 'bDmM'); + ExReleaseResourceLite(&PsLoadedModuleResource); + KeLeaveCriticalRegion(); _SEH2_YIELD(return); } _SEH2_END;
3 years, 10 months
1
0
0
0
[reactos] 80/100: [NTOS:MM] Remove unused field
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d23dbdda4cf1d30a7d518…
commit d23dbdda4cf1d30a7d518cc1c01bb4daebc33b7f Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Mon Jan 25 09:43:50 2021 +0100 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 [NTOS:MM] Remove unused field --- ntoskrnl/include/internal/mm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h index 05f89c50cb9..4db21f72199 100644 --- a/ntoskrnl/include/internal/mm.h +++ b/ntoskrnl/include/internal/mm.h @@ -185,7 +185,6 @@ typedef struct _MM_SECTION_SEGMENT ULONG RefCount; ULONG SegFlags; - LIST_ENTRY ListOfSegments; RTL_GENERIC_TABLE PageTable; } MM_SECTION_SEGMENT, *PMM_SECTION_SEGMENT;
3 years, 10 months
1
0
0
0
[reactos] 79/100: [NTOS:MM] Do not acquire Pfn lock in MmGetRmapListHead
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f201b8af788349cc081b6…
commit f201b8af788349cc081b68d0868cfff4df3ece1c Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Mon Jan 25 09:24:54 2021 +0100 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 [NTOS:MM] Do not acquire Pfn lock in MmGetRmapListHead All callers already hold it --- ntoskrnl/mm/freelist.c | 15 ++++----------- ntoskrnl/mm/rmap.c | 4 ++++ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/ntoskrnl/mm/freelist.c b/ntoskrnl/mm/freelist.c index ba16362f546..5cc22ce38b1 100644 --- a/ntoskrnl/mm/freelist.c +++ b/ntoskrnl/mm/freelist.c @@ -426,12 +426,10 @@ PMM_RMAP_ENTRY NTAPI MmGetRmapListHeadPage(PFN_NUMBER Pfn) { - KIRQL oldIrql; - PMM_RMAP_ENTRY ListHead; PMMPFN Pfn1; - /* Lock PFN database */ - oldIrql = MiAcquirePfnLock(); + /* PFN database must be locked */ + MI_ASSERT_PFN_LOCK_HELD(); /* Get the entry */ Pfn1 = MiGetPfnEntry(Pfn); @@ -439,19 +437,14 @@ MmGetRmapListHeadPage(PFN_NUMBER Pfn) if (!MI_IS_ROS_PFN(Pfn1)) { - MiReleasePfnLock(oldIrql); return NULL; } - /* Get the list head */ - ListHead = Pfn1->RmapListHead; - /* Should not have an RMAP for a non-active page */ ASSERT(MiIsPfnInUse(Pfn1) == TRUE); - /* Release PFN database and return rmap list head */ - MiReleasePfnLock(oldIrql); - return ListHead; + /* Get the list head */ + return Pfn1->RmapListHead; } VOID diff --git a/ntoskrnl/mm/rmap.c b/ntoskrnl/mm/rmap.c index 785539ea58d..f50e680e401 100644 --- a/ntoskrnl/mm/rmap.c +++ b/ntoskrnl/mm/rmap.c @@ -250,7 +250,11 @@ MmPageOutPhysicalAddress(PFN_NUMBER Page) /* We can finally let this page go */ MmDeleteRmap(Page, Process, Address); +#if DBG + OldIrql = MiAcquirePfnLock(); ASSERT(MmGetRmapListHeadPage(Page) == NULL); + MiReleasePfnLock(OldIrql); +#endif MmReleasePageMemoryConsumer(MC_USER, Page); if (Address < MmSystemRangeStart)
3 years, 10 months
1
0
0
0
[reactos] 78/100: |NTOS:MM] Simplify some code
by Jérôme Gardou
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=727e73f253a665cb8a74b…
commit 727e73f253a665cb8a74b2144d884d4c03241677 Author: Jérôme Gardou <jerome.gardou(a)reactos.org> AuthorDate: Mon Jan 25 09:23:46 2021 +0100 Commit: Jérôme Gardou <jerome.gardou(a)reactos.org> CommitDate: Wed Feb 3 09:41:23 2021 +0100 |NTOS:MM] Simplify some code --- ntoskrnl/cache/section/sptab.c | 45 ++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/ntoskrnl/cache/section/sptab.c b/ntoskrnl/cache/section/sptab.c index 7a2481a4752..f0cb3d36c2a 100644 --- a/ntoskrnl/cache/section/sptab.c +++ b/ntoskrnl/cache/section/sptab.c @@ -204,27 +204,30 @@ _MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, OldEntry, Entry); - if (PFN_FROM_SSE(Entry) == PFN_FROM_SSE(OldEntry)) { - /* Nothing */ - } else if (Entry && !IS_SWAP_FROM_SSE(Entry)) { - ASSERT(!OldEntry || IS_SWAP_FROM_SSE(OldEntry)); - MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset); - } else if (OldEntry && !IS_SWAP_FROM_SSE(OldEntry)) { - ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry)); + if (Entry && !IS_SWAP_FROM_SSE(Entry)) + { + /* We have a valid entry. See if we must do something */ + if (OldEntry && !IS_SWAP_FROM_SSE(OldEntry)) + { + /* The previous entry was valid. Shall we swap the Rmaps ? */ + if (PFN_FROM_SSE(Entry) != PFN_FROM_SSE(OldEntry)) + { + MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry)); + MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset); + } + } + else + { + /* We're switching to a valid entry from an invalid one. Add the Rmap */ + MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset); + } + } + else if (OldEntry && !IS_SWAP_FROM_SSE(OldEntry)) + { + /* We're switching to an invalid entry from a valid one */ MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry)); - } else if (IS_SWAP_FROM_SSE(Entry)) { - ASSERT(!IS_SWAP_FROM_SSE(OldEntry) || - SWAPENTRY_FROM_SSE(OldEntry) == MM_WAIT_ENTRY); - if (OldEntry && SWAPENTRY_FROM_SSE(OldEntry) != MM_WAIT_ENTRY) - MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry)); - } else if (IS_SWAP_FROM_SSE(OldEntry)) { - ASSERT(!IS_SWAP_FROM_SSE(Entry)); - if (Entry) - MmSetSectionAssociation(PFN_FROM_SSE(OldEntry), Segment, Offset); - } else { - /* We should not be replacing a page like this */ - ASSERT(FALSE); } + PageTable->PageEntries[PageIndex] = Entry; return STATUS_SUCCESS; } @@ -332,13 +335,13 @@ MmGetSectionAssociation(PFN_NUMBER Page, PMM_SECTION_SEGMENT Segment = NULL; PCACHE_SECTION_PAGE_TABLE PageTable; - PageTable = (PCACHE_SECTION_PAGE_TABLE)MmGetSegmentRmap(Page, - &RawOffset); + PageTable = MmGetSegmentRmap(Page, &RawOffset); if (PageTable) { Segment = PageTable->Segment; Offset->QuadPart = PageTable->FileOffset.QuadPart + ((ULONG64)RawOffset << PAGE_SHIFT); + ASSERT(PFN_FROM_SSE(PageTable->PageEntries[RawOffset]) == Page); } return Segment;
3 years, 10 months
1
0
0
0
← Newer
1
...
30
31
32
33
34
35
36
...
44
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Results per page:
10
25
50
100
200