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 2018
----- 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
24 participants
240 discussions
Start a n
N
ew thread
01/01: [NTOSKRNL] When initializing file cache, also allocate a private cache map if needed. Not used yet.
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=074e7e97fe140f0c9f627…
commit 074e7e97fe140f0c9f627378995784b2c8328349 Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Wed Feb 7 23:18:54 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Wed Feb 7 23:18:54 2018 +0100 [NTOSKRNL] When initializing file cache, also allocate a private cache map if needed. Not used yet. --- ntoskrnl/cc/fs.c | 19 +++++++++++++++++++ ntoskrnl/cc/view.c | 42 +++++++++++++++++++++++++++++++++++++++--- ntoskrnl/include/internal/cc.h | 2 ++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/ntoskrnl/cc/fs.c b/ntoskrnl/cc/fs.c index 38c9ae527c..fddf76079a 100644 --- a/ntoskrnl/cc/fs.c +++ b/ntoskrnl/cc/fs.c @@ -346,6 +346,25 @@ CcUninitializeCacheMap ( FALSE); } + /* Closing the handle, so kill the private cache map */ + if (FileObject->SectionObjectPointer->SharedCacheMap != NULL && + FileObject->PrivateCacheMap != NULL) + { + PPRIVATE_CACHE_MAP PrivateMap; + + PrivateMap = FileObject->PrivateCacheMap; + SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; + + /* Remove it from the file */ + KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql); + RemoveEntryList(&PrivateMap->PrivateLinks); + KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql); + + /* And free it */ + FileObject->PrivateCacheMap = NULL; + ExFreePoolWithTag(PrivateMap, 'cPcC'); + } + Status = CcRosReleaseFileCache(FileObject); if (UninitializeCompleteEvent) { diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index 1b4468cd41..145eb0d908 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -1209,17 +1209,19 @@ CcRosInitializeFileCache ( * FUNCTION: Initializes a shared cache map for a file object */ { + KIRQL OldIrql; + BOOLEAN Allocated; PROS_SHARED_CACHE_MAP SharedCacheMap; SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; DPRINT("CcRosInitializeFileCache(FileObject 0x%p, SharedCacheMap 0x%p)\n", FileObject, SharedCacheMap); + Allocated = FALSE; KeAcquireGuardedMutex(&ViewLock); if (SharedCacheMap == NULL) { - KIRQL OldIrql; - + Allocated = TRUE; SharedCacheMap = ExAllocateFromNPagedLookasideList(&SharedCacheMapLookasideList); if (SharedCacheMap == NULL) { @@ -1239,6 +1241,7 @@ CcRosInitializeFileCache ( SharedCacheMap->PinAccess = PinAccess; SharedCacheMap->DirtyPageThreshold = 0; SharedCacheMap->DirtyPages = 0; + InitializeListHead(&SharedCacheMap->PrivateList); KeInitializeSpinLock(&SharedCacheMap->CacheMapLock); InitializeListHead(&SharedCacheMap->CacheMapVacbListHead); FileObject->SectionObjectPointer->SharedCacheMap = SharedCacheMap; @@ -1249,7 +1252,40 @@ CcRosInitializeFileCache ( } if (FileObject->PrivateCacheMap == NULL) { - FileObject->PrivateCacheMap = SharedCacheMap; + PPRIVATE_CACHE_MAP PrivateMap; + + /* Allocate the private cache map for this handle */ + PrivateMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(PRIVATE_CACHE_MAP), 'cPcC'); + if (PrivateMap == NULL) + { + /* If we also allocated the shared cache map for this file, kill it */ + if (Allocated) + { + KeAcquireSpinLock(&iSharedCacheMapLock, &OldIrql); + RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks); + KeReleaseSpinLock(&iSharedCacheMapLock, OldIrql); + + FileObject->SectionObjectPointer->SharedCacheMap = NULL; + ObDereferenceObject(FileObject); + ExFreeToNPagedLookasideList(&SharedCacheMapLookasideList, SharedCacheMap); + } + + KeReleaseGuardedMutex(&ViewLock); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Initialize it */ + RtlZeroMemory(PrivateMap, sizeof(PRIVATE_CACHE_MAP)); + PrivateMap->NodeTypeCode = NODE_TYPE_PRIVATE_MAP; + PrivateMap->ReadAheadMask = 0xFFF; + PrivateMap->FileObject = FileObject; + + /* Link it to the file */ + KeAcquireSpinLock(&SharedCacheMap->CacheMapLock, &OldIrql); + InsertTailList(&SharedCacheMap->PrivateList, &PrivateMap->PrivateLinks); + KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, OldIrql); + + FileObject->PrivateCacheMap = PrivateMap; SharedCacheMap->OpenCount++; } KeReleaseGuardedMutex(&ViewLock); diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h index f78e9c0491..9679255697 100644 --- a/ntoskrnl/include/internal/cc.h +++ b/ntoskrnl/include/internal/cc.h @@ -163,6 +163,7 @@ typedef struct _ROS_SHARED_CACHE_MAP BOOLEAN PinAccess; PCACHE_MANAGER_CALLBACKS Callbacks; PVOID LazyWriteContext; + LIST_ENTRY PrivateList; KSPIN_LOCK CacheMapLock; ULONG OpenCount; ULONG DirtyPages; @@ -255,6 +256,7 @@ typedef struct _WORK_QUEUE_ENTRY extern LAZY_WRITER LazyWriter; #define NODE_TYPE_DEFERRED_WRITE 0x02FC +#define NODE_TYPE_PRIVATE_MAP 0x02FE VOID NTAPI
6 years, 10 months
1
0
0
0
01/01: [NTOSKRNL] Drop the CcTryToInitializeFileCache() which is actually doing nothing relevant
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0e932c7bef7641314c54b…
commit 0e932c7bef7641314c54b149a1b3a6a4589c2ef1 Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Wed Feb 7 22:23:25 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Wed Feb 7 22:23:49 2018 +0100 [NTOSKRNL] Drop the CcTryToInitializeFileCache() which is actually doing nothing relevant --- ntoskrnl/cc/view.c | 31 ------------------------------- ntoskrnl/include/internal/cc.h | 4 ---- ntoskrnl/mm/section.c | 12 +----------- 3 files changed, 1 insertion(+), 46 deletions(-) diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index 2e8fb6c51e..1b4468cd41 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -1197,37 +1197,6 @@ CcRosReleaseFileCache ( return STATUS_SUCCESS; } -NTSTATUS -NTAPI -CcTryToInitializeFileCache ( - PFILE_OBJECT FileObject) -{ - PROS_SHARED_CACHE_MAP SharedCacheMap; - NTSTATUS Status; - - KeAcquireGuardedMutex(&ViewLock); - - ASSERT(FileObject->SectionObjectPointer); - SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; - if (SharedCacheMap == NULL) - { - Status = STATUS_UNSUCCESSFUL; - } - else - { - if (FileObject->PrivateCacheMap == NULL) - { - FileObject->PrivateCacheMap = SharedCacheMap; - SharedCacheMap->OpenCount++; - } - Status = STATUS_SUCCESS; - } - KeReleaseGuardedMutex(&ViewLock); - - return Status; -} - - NTSTATUS NTAPI CcRosInitializeFileCache ( diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h index 3a44fda908..f78e9c0491 100644 --- a/ntoskrnl/include/internal/cc.h +++ b/ntoskrnl/include/internal/cc.h @@ -406,10 +406,6 @@ CcRosReleaseFileCache( PFILE_OBJECT FileObject ); -NTSTATUS -NTAPI -CcTryToInitializeFileCache(PFILE_OBJECT FileObject); - VOID NTAPI CcShutdownSystem(VOID); diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c index 5c954395a9..b588f1c617 100644 --- a/ntoskrnl/mm/section.c +++ b/ntoskrnl/mm/section.c @@ -3758,17 +3758,7 @@ MmCreateImageSection(PROS_SECTION_OBJECT *SectionObject, Section->SectionPageProtection = SectionPageProtection; Section->AllocationAttributes = AllocationAttributes; -#ifndef NEWCC - /* - * Initialized caching for this file object if previously caching - * was initialized for the same on disk file - */ - Status = CcTryToInitializeFileCache(FileObject); -#else - Status = STATUS_SUCCESS; -#endif - - if (!NT_SUCCESS(Status) || FileObject->SectionObjectPointer->ImageSectionObject == NULL) + if (FileObject->SectionObjectPointer->ImageSectionObject == NULL) { NTSTATUS StatusExeFmt;
6 years, 10 months
1
0
0
0
01/01: [NTOS:KE] Replace "Fatal System Error" with "BugCheck"
by Serge Gautherie
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6ece4e9fc22d664ea2485…
commit 6ece4e9fc22d664ea2485d04303e8ae10047f21f Author: Serge Gautherie <reactos-git_serge_171003(a)gautherie.fr> AuthorDate: Wed Feb 7 06:29:02 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Wed Feb 7 22:22:28 2018 +0100 [NTOS:KE] Replace "Fatal System Error" with "BugCheck" --- ntoskrnl/ke/bug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ntoskrnl/ke/bug.c b/ntoskrnl/ke/bug.c index a92acb1bab..2127d7207c 100644 --- a/ntoskrnl/ke/bug.c +++ b/ntoskrnl/ke/bug.c @@ -1070,8 +1070,8 @@ KeBugCheckWithTf(IN ULONG BugCheckCode, if ((BugCheckCode != MANUALLY_INITIATED_CRASH) && (KdDebuggerEnabled)) { /* Crash on the debugger console */ - DbgPrint("\n*** Fatal System Error: 0x%08lx\n" - " (0x%p,0x%p,0x%p,0x%p)\n\n", + DbgPrint("\n*** BugCheck: 0x%08lx\n" + " (0x%p,0x%p,0x%p,0x%p)\n\n", KiBugCheckData[0], KiBugCheckData[1], KiBugCheckData[2],
6 years, 10 months
1
0
0
0
09/09: [NTOSKRNL] Use the LockQueueMasterLock where appropriate
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=323f71a5519858222d749…
commit 323f71a5519858222d74917a0478de843e5d10d3 Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Wed Feb 7 21:35:22 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Wed Feb 7 21:37:17 2018 +0100 [NTOSKRNL] Use the LockQueueMasterLock where appropriate --- ntoskrnl/cc/copy.c | 5 ++++- ntoskrnl/cc/lazywrite.c | 4 +++- ntoskrnl/cc/view.c | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c index 7a84e23fb9..521d90b48e 100644 --- a/ntoskrnl/cc/copy.c +++ b/ntoskrnl/cc/copy.c @@ -628,6 +628,7 @@ CcDeferWrite ( IN ULONG BytesToWrite, IN BOOLEAN Retrying) { + KIRQL OldIrql; PDEFERRED_WRITE Context; PFSRTL_COMMON_FCB_HEADER Fcb; @@ -675,11 +676,13 @@ CcDeferWrite ( /* Try to execute the posted writes */ CcPostDeferredWrites(); - /* FIXME: lock master */ + /* Schedule a lazy writer run to handle deferred writes */ + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); if (!LazyWriter.ScanActive) { CcScheduleLazyWriteScan(FALSE); } + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); } /* diff --git a/ntoskrnl/cc/lazywrite.c b/ntoskrnl/cc/lazywrite.c index 4619aa8c69..292266d191 100644 --- a/ntoskrnl/cc/lazywrite.c +++ b/ntoskrnl/cc/lazywrite.c @@ -119,7 +119,6 @@ CcScanDpc( CcPostWorkQueue(WorkItem, &CcRegularWorkQueue); } -/* FIXME: handle master lock */ VOID CcLazyWriteScan(VOID) { @@ -165,6 +164,7 @@ CcLazyWriteScan(VOID) CcPostDeferredWrites(); } + /* Post items that were due for end of run */ while (!IsListEmpty(&ToPost)) { ListEntry = RemoveHeadList(&ToPost); @@ -173,7 +173,9 @@ CcLazyWriteScan(VOID) } /* We're no longer active */ + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); LazyWriter.ScanActive = FALSE; + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); } VOID CcScheduleLazyWriteScan( diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index e050a33c17..2e8fb6c51e 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -520,11 +520,13 @@ CcRosMarkDirtyVacb ( KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldIrql); KeReleaseGuardedMutex(&ViewLock); - /* FIXME: lock master */ + /* Schedule a lazy writer run to now that we have dirty VACB */ + oldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); if (!LazyWriter.ScanActive) { CcScheduleLazyWriteScan(FALSE); } + KeReleaseQueuedSpinLock(LockQueueMasterLock, oldIrql); } VOID
6 years, 10 months
1
0
0
0
08/09: [NTOSKRNL] Handle FSRTL_FLAG_LIMIT_MODIFIED_PAGES flag in CcDeferWrite(). Util now, CcDeferWrite() was ignoring limits per file object.
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=19c822341ba5ba29761b6…
commit 19c822341ba5ba29761b6ae1449e99789122396e Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Wed Feb 7 21:11:39 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Wed Feb 7 21:37:17 2018 +0100 [NTOSKRNL] Handle FSRTL_FLAG_LIMIT_MODIFIED_PAGES flag in CcDeferWrite(). Util now, CcDeferWrite() was ignoring limits per file object. --- ntoskrnl/cc/copy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c index 30360b6c31..7a84e23fb9 100644 --- a/ntoskrnl/cc/copy.c +++ b/ntoskrnl/cc/copy.c @@ -629,6 +629,7 @@ CcDeferWrite ( IN BOOLEAN Retrying) { PDEFERRED_WRITE Context; + PFSRTL_COMMON_FCB_HEADER Fcb; CCTRACE(CC_API_DEBUG, "FileObject=%p PostRoutine=%p Context1=%p Context2=%p BytesToWrite=%lu Retrying=%d\n", FileObject, PostRoutine, Context1, Context2, BytesToWrite, Retrying); @@ -642,6 +643,8 @@ CcDeferWrite ( return; } + Fcb = FileObject->FsContext; + /* Otherwise, initialize the context */ RtlZeroMemory(Context, sizeof(DEFERRED_WRITE)); Context->NodeTypeCode = NODE_TYPE_DEFERRED_WRITE; @@ -651,6 +654,7 @@ CcDeferWrite ( Context->Context1 = Context1; Context->Context2 = Context2; Context->BytesToWrite = BytesToWrite; + Context->LimitModifiedPages = BooleanFlagOn(Fcb->Flags, FSRTL_FLAG_LIMIT_MODIFIED_PAGES); /* And queue it */ if (Retrying)
6 years, 10 months
1
0
0
0
07/09: [NTOSKRNL] Add wait support in CcCanIWrite()
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c11e947f6135ee99bd046…
commit c11e947f6135ee99bd046c729b0ea81d714be2c9 Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Wed Feb 7 21:09:36 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Wed Feb 7 21:37:17 2018 +0100 [NTOSKRNL] Add wait support in CcCanIWrite() --- ntoskrnl/cc/copy.c | 68 ++++++++++++++++++++++++++++++++++++++++-- ntoskrnl/include/internal/cc.h | 1 + 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c index a150848bb2..30360b6c31 100644 --- a/ntoskrnl/cc/copy.c +++ b/ntoskrnl/cc/copy.c @@ -446,6 +446,8 @@ CcCanIWrite ( IN BOOLEAN Wait, IN BOOLEAN Retrying) { + KEVENT WaitEvent; + DEFERRED_WRITE Context; PFSRTL_COMMON_FCB_HEADER Fcb; PROS_SHARED_CACHE_MAP SharedCacheMap; @@ -455,7 +457,8 @@ CcCanIWrite ( /* We cannot write if dirty pages count is above threshold */ if (CcTotalDirtyPages > CcDirtyPageThreshold) { - return FALSE; + /* Can the caller wait till it's possible to write? */ + goto CanIWait; } /* We cannot write if dirty pages count will bring use above @@ -463,7 +466,8 @@ CcCanIWrite ( */ if (CcTotalDirtyPages + (BytesToWrite / PAGE_SIZE) > CcDirtyPageThreshold) { - return FALSE; + /* Can the caller wait till it's possible to write? */ + goto CanIWait; } /* Is there a limit per file object? */ @@ -479,17 +483,75 @@ CcCanIWrite ( /* Is dirty page count above local threshold? */ if (SharedCacheMap->DirtyPages > SharedCacheMap->DirtyPageThreshold) { - return FALSE; + /* Can the caller wait till it's possible to write? */ + goto CanIWait; } /* We cannot write if dirty pages count will bring use above * XXX: Might not be accurate */ if (SharedCacheMap->DirtyPages + (BytesToWrite / PAGE_SIZE) > SharedCacheMap->DirtyPageThreshold) + { + /* Can the caller wait till it's possible to write? */ + goto CanIWait; + } + + return TRUE; + +CanIWait: + /* If we reached that point, it means caller cannot write + * If he cannot wait, then fail and deny write + */ + if (!Wait) { return FALSE; } + /* Otherwise, if there are no deferred writes yet, start the lazy writer */ + if (IsListEmpty(&CcDeferredWrites)) + { + KIRQL OldIrql; + + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); + CcScheduleLazyWriteScan(TRUE); + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); + } + + /* Initialize our wait event */ + KeInitializeEvent(&WaitEvent, NotificationEvent, FALSE); + + /* And prepare a dummy context */ + Context.NodeTypeCode = NODE_TYPE_DEFERRED_WRITE; + Context.NodeByteSize = sizeof(DEFERRED_WRITE); + Context.FileObject = FileObject; + Context.BytesToWrite = BytesToWrite; + Context.LimitModifiedPages = BooleanFlagOn(Fcb->Flags, FSRTL_FLAG_LIMIT_MODIFIED_PAGES); + Context.Event = &WaitEvent; + + /* And queue it */ + if (Retrying) + { + /* To the top, if that's a retry */ + ExInterlockedInsertHeadList(&CcDeferredWrites, + &Context.DeferredWriteLinks, + &CcDeferredWriteSpinLock); + } + else + { + /* To the bottom, if that's a first time */ + ExInterlockedInsertTailList(&CcDeferredWrites, + &Context.DeferredWriteLinks, + &CcDeferredWriteSpinLock); + } + + /* Now, we'll loop until our event is set. When it is set, it means that caller + * can immediately write, and has to + */ + do + { + CcPostDeferredWrites(); + } while (KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, &CcIdleDelay) != STATUS_SUCCESS); + return TRUE; } diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h index 157b655b3a..3a44fda908 100644 --- a/ntoskrnl/include/internal/cc.h +++ b/ntoskrnl/include/internal/cc.h @@ -50,6 +50,7 @@ extern LIST_ENTRY CcIdleWorkerThreadList; extern LIST_ENTRY CcRegularWorkQueue; extern LIST_ENTRY CcPostTickWorkQueue; extern NPAGED_LOOKASIDE_LIST CcTwilightLookasideList; +extern LARGE_INTEGER CcIdleDelay; typedef struct _PF_SCENARIO_ID {
6 years, 10 months
1
0
0
0
06/09: [NTOSKRNL] Implement CcPostDeferredWrites() that executes deferred writes. Make use of it in the lazy writer
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=92e64a6c9bbd68c81914c…
commit 92e64a6c9bbd68c81914c7ce63c4888b9ca4d54b Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Wed Feb 7 20:27:55 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Wed Feb 7 21:37:17 2018 +0100 [NTOSKRNL] Implement CcPostDeferredWrites() that executes deferred writes. Make use of it in the lazy writer --- ntoskrnl/cc/copy.c | 77 ++++++++++++++++++++++++++++++++++++++++++ ntoskrnl/cc/lazywrite.c | 29 ++-------------- ntoskrnl/include/internal/cc.h | 3 ++ 3 files changed, 83 insertions(+), 26 deletions(-) diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c index ca39f7cc18..a150848bb2 100644 --- a/ntoskrnl/cc/copy.c +++ b/ntoskrnl/cc/copy.c @@ -361,6 +361,80 @@ CcCopyData ( return TRUE; } +VOID +CcPostDeferredWrites(VOID) +{ + ULONG WrittenBytes; + + /* We'll try to write as much as we can */ + WrittenBytes = 0; + while (TRUE) + { + KIRQL OldIrql; + PLIST_ENTRY ListEntry; + PDEFERRED_WRITE DeferredWrite; + + DeferredWrite = NULL; + + /* Lock our deferred writes list */ + KeAcquireSpinLock(&CcDeferredWriteSpinLock, &OldIrql); + for (ListEntry = CcDeferredWrites.Flink; + ListEntry != &CcDeferredWrites; + ListEntry = ListEntry->Flink) + { + /* Extract an entry */ + DeferredWrite = CONTAINING_RECORD(ListEntry, DEFERRED_WRITE, DeferredWriteLinks); + + /* Compute the modified bytes, based on what we already wrote */ + WrittenBytes += DeferredWrite->BytesToWrite; + /* We overflowed, give up */ + if (WrittenBytes < DeferredWrite->BytesToWrite) + { + DeferredWrite = NULL; + break; + } + + /* Check we can write */ + if (CcCanIWrite(DeferredWrite->FileObject, WrittenBytes, FALSE, TRUE)) + { + /* We can, so remove it from the list and stop looking for entry */ + RemoveEntryList(&DeferredWrite->DeferredWriteLinks); + break; + } + + /* If we don't accept modified pages, stop here */ + if (!DeferredWrite->LimitModifiedPages) + { + DeferredWrite = NULL; + break; + } + + /* Reset count as nothing was written yet */ + WrittenBytes -= DeferredWrite->BytesToWrite; + DeferredWrite = NULL; + } + KeReleaseSpinLock(&CcDeferredWriteSpinLock, OldIrql); + + /* Nothing to write found, give up */ + if (DeferredWrite == NULL) + { + break; + } + + /* If we have an event, set it and quit */ + if (DeferredWrite->Event) + { + KeSetEvent(DeferredWrite->Event, IO_NO_INCREMENT, FALSE); + } + /* Otherwise, call the write routine and free the context */ + else + { + DeferredWrite->PostRoutine(DeferredWrite->Context1, DeferredWrite->Context2); + ExFreePoolWithTag(DeferredWrite, 'CcDw'); + } + } +} + /* * @unimplemented */ @@ -532,6 +606,9 @@ CcDeferWrite ( &CcDeferredWriteSpinLock); } + /* Try to execute the posted writes */ + CcPostDeferredWrites(); + /* FIXME: lock master */ if (!LazyWriter.ScanActive) { diff --git a/ntoskrnl/cc/lazywrite.c b/ntoskrnl/cc/lazywrite.c index d38c6938b5..4619aa8c69 100644 --- a/ntoskrnl/cc/lazywrite.c +++ b/ntoskrnl/cc/lazywrite.c @@ -159,33 +159,10 @@ CcLazyWriteScan(VOID) DPRINT1("Lazy writer done (%d)\n", Count); } - /* Likely not optimal, but let's handle one deferred write now! */ - ListEntry = ExInterlockedRemoveHeadList(&CcDeferredWrites, &CcDeferredWriteSpinLock); - if (ListEntry != NULL) + /* If we have deferred writes, try them now! */ + if (!IsListEmpty(&CcDeferredWrites)) { - PDEFERRED_WRITE Context; - - /* Extract the context */ - Context = CONTAINING_RECORD(ListEntry, DEFERRED_WRITE, DeferredWriteLinks); - ASSERT(Context->NodeTypeCode == NODE_TYPE_DEFERRED_WRITE); - - /* Can we write now? */ - if (CcCanIWrite(Context->FileObject, Context->BytesToWrite, FALSE, TRUE)) - { - /* Yes! Do it, and destroy the associated context */ - Context->PostRoutine(Context->Context1, Context->Context2); - ExFreePoolWithTag(Context, 'CcDw'); - } - else - { - /* Otherwise, requeue it, but in tail, so that it doesn't block others - * This is clearly to improve, but given the poor algorithm used now - * It's better than nothing! - */ - ExInterlockedInsertTailList(&CcDeferredWrites, - &Context->DeferredWriteLinks, - &CcDeferredWriteSpinLock); - } + CcPostDeferredWrites(); } while (!IsListEmpty(&ToPost)) diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h index 820cf7a2cb..157b655b3a 100644 --- a/ntoskrnl/include/internal/cc.h +++ b/ntoskrnl/include/internal/cc.h @@ -428,6 +428,9 @@ CcScanDpc( VOID CcScheduleLazyWriteScan(BOOLEAN NoDelay); +VOID +CcPostDeferredWrites(VOID); + FORCEINLINE NTSTATUS CcRosAcquireVacbLock(
6 years, 10 months
1
0
0
0
05/09: [NTOSKRNL] Properly implement lazy writer activity watching. We get rid of the old iLazyWriterNotify event in favor of work items that contain an event that lazy writer will set once its done. To implement this, we rely on the newly introduced CcPostTickWorkQueue work queue that will contain work items that are to be queued once lazy writer is done.
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f4e67aa837c5c8190fe1d…
commit f4e67aa837c5c8190fe1d502a2ef277921e2e710 Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Wed Feb 7 18:56:13 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Wed Feb 7 21:37:17 2018 +0100 [NTOSKRNL] Properly implement lazy writer activity watching. We get rid of the old iLazyWriterNotify event in favor of work items that contain an event that lazy writer will set once its done. To implement this, we rely on the newly introduced CcPostTickWorkQueue work queue that will contain work items that are to be queued once lazy writer is done. Move the CcWaitForCurrentLazyWriterActivity() implementation to the lazy writer file, and reimplemented it using the new support mechanisms --- ntoskrnl/cc/cacheman.c | 4 +-- ntoskrnl/cc/copy.c | 26 -------------- ntoskrnl/cc/lazywrite.c | 79 +++++++++++++++++++++++++++++++++++++----- ntoskrnl/include/internal/cc.h | 2 +- 4 files changed, 72 insertions(+), 39 deletions(-) diff --git a/ntoskrnl/cc/cacheman.c b/ntoskrnl/cc/cacheman.c index 1718ddebca..aacf818c8a 100644 --- a/ntoskrnl/cc/cacheman.c +++ b/ntoskrnl/cc/cacheman.c @@ -52,6 +52,7 @@ CcInitializeCacheManager(VOID) /* Initialize lazy-writer lists */ InitializeListHead(&CcIdleWorkerThreadList); InitializeListHead(&CcRegularWorkQueue); + InitializeListHead(&CcPostTickWorkQueue); /* Define lazy writer threshold and the amount of workers, * depending on the system type @@ -106,9 +107,6 @@ CcInitializeCacheManager(VOID) /* Lookaside list for our work items */ ExInitializeNPagedLookasideList(&CcTwilightLookasideList, NULL, NULL, 0, sizeof(WORK_QUEUE_ENTRY), 'KWcC', 0); - /* HACK: for lazy writer watching */ - KeInitializeEvent(&iLazyWriterNotify, NotificationEvent, FALSE); - return TRUE; } diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c index 194526c559..ca39f7cc18 100644 --- a/ntoskrnl/cc/copy.c +++ b/ntoskrnl/cc/copy.c @@ -35,8 +35,6 @@ ULONG CcFastReadWait; ULONG CcFastReadNoWait; ULONG CcFastReadResourceMiss; -extern KEVENT iLazyWriterNotify; - /* FUNCTIONS *****************************************************************/ VOID @@ -598,30 +596,6 @@ CcFastCopyWrite ( ASSERT(Success == TRUE); } -/* - * @implemented - */ -NTSTATUS -NTAPI -CcWaitForCurrentLazyWriterActivity ( - VOID) -{ - NTSTATUS Status; - - /* Lazy writer is done when its event is set */ - Status = KeWaitForSingleObject(&iLazyWriterNotify, - Executive, - KernelMode, - FALSE, - NULL); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - return STATUS_SUCCESS; -} - /* * @implemented */ diff --git a/ntoskrnl/cc/lazywrite.c b/ntoskrnl/cc/lazywrite.c index bda7ca27de..d38c6938b5 100644 --- a/ntoskrnl/cc/lazywrite.c +++ b/ntoskrnl/cc/lazywrite.c @@ -33,6 +33,7 @@ ULONG CcLazyWriteIos = 0; * - Lookaside list where to allocate work items * - Queue for regular work items * - Available worker threads + * - Queue for stuff to be queued after lazy writer is done * - Marker for throttling queues * - Number of ongoing workers * - Three seconds delay for lazy writer @@ -44,6 +45,7 @@ LAZY_WRITER LazyWriter; NPAGED_LOOKASIDE_LIST CcTwilightLookasideList; LIST_ENTRY CcRegularWorkQueue; LIST_ENTRY CcIdleWorkerThreadList; +LIST_ENTRY CcPostTickWorkQueue; BOOLEAN CcQueueThrottle = FALSE; ULONG CcNumberActiveWorkerThreads = 0; LARGE_INTEGER CcFirstDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)-1*3000*1000*10); @@ -51,10 +53,6 @@ LARGE_INTEGER CcIdleDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)-1*1000*1000*10 LARGE_INTEGER CcNoDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0); ULONG CcNumberWorkerThreads; -/* Internal vars (ROS): - */ -KEVENT iLazyWriterNotify; - /* FUNCTIONS *****************************************************************/ VOID @@ -127,10 +125,25 @@ CcLazyWriteScan(VOID) { ULONG Target; ULONG Count; + KIRQL OldIrql; PLIST_ENTRY ListEntry; + LIST_ENTRY ToPost; + PWORK_QUEUE_ENTRY WorkItem; - /* We're not sleeping anymore */ - KeClearEvent(&iLazyWriterNotify); + /* Do we have entries to queue after we're done? */ + InitializeListHead(&ToPost); + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); + if (LazyWriter.OtherWork) + { + while (!IsListEmpty(&CcPostTickWorkQueue)) + { + ListEntry = RemoveHeadList(&CcPostTickWorkQueue); + WorkItem = CONTAINING_RECORD(ListEntry, WORK_QUEUE_ENTRY, WorkQueueLinks); + InsertTailList(&ToPost, &WorkItem->WorkQueueLinks); + } + LazyWriter.OtherWork = FALSE; + } + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); /* Our target is one-eighth of the dirty pages */ Target = CcTotalDirtyPages / 8; @@ -146,9 +159,6 @@ CcLazyWriteScan(VOID) DPRINT1("Lazy writer done (%d)\n", Count); } - /* Inform people waiting on us that we're done */ - KeSetEvent(&iLazyWriterNotify, IO_DISK_INCREMENT, FALSE); - /* Likely not optimal, but let's handle one deferred write now! */ ListEntry = ExInterlockedRemoveHeadList(&CcDeferredWrites, &CcDeferredWriteSpinLock); if (ListEntry != NULL) @@ -178,6 +188,13 @@ CcLazyWriteScan(VOID) } } + while (!IsListEmpty(&ToPost)) + { + ListEntry = RemoveHeadList(&ToPost); + WorkItem = CONTAINING_RECORD(ListEntry, WORK_QUEUE_ENTRY, WorkQueueLinks); + CcPostWorkQueue(WorkItem, &CcRegularWorkQueue); + } + /* We're no longer active */ LazyWriter.ScanActive = FALSE; } @@ -281,3 +298,47 @@ CcWorkerThread( --CcNumberActiveWorkerThreads; KeReleaseQueuedSpinLock(LockQueueWorkQueueLock, OldIrql); } + +/* + * @implemented + */ +NTSTATUS +NTAPI +CcWaitForCurrentLazyWriterActivity ( + VOID) +{ + KIRQL OldIrql; + KEVENT WaitEvent; + PWORK_QUEUE_ENTRY WorkItem; + + /* Allocate a work item */ + WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList); + if (WorkItem == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* We want lazy writer to set our event */ + WorkItem->Function = SetDone; + KeInitializeEvent(&WaitEvent, NotificationEvent, FALSE); + WorkItem->Parameters.Event.Event = &WaitEvent; + + /* Use the post tick queue */ + OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); + InsertTailList(&CcPostTickWorkQueue, &WorkItem->WorkQueueLinks); + + /* Inform the lazy writer it will have to handle the post tick queue */ + LazyWriter.OtherWork = TRUE; + /* And if it's not running, queue a lazy writer run + * And start it NOW, we want the response now + */ + if (!LazyWriter.ScanActive) + { + CcScheduleLazyWriteScan(TRUE); + } + + KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); + + /* And now, wait until lazy writer replies */ + return KeWaitForSingleObject(&WaitEvent, Executive, KernelMode, FALSE, NULL); +} diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h index 18d34ef550..820cf7a2cb 100644 --- a/ntoskrnl/include/internal/cc.h +++ b/ntoskrnl/include/internal/cc.h @@ -48,8 +48,8 @@ extern KSPIN_LOCK CcDeferredWriteSpinLock; extern ULONG CcNumberWorkerThreads; extern LIST_ENTRY CcIdleWorkerThreadList; extern LIST_ENTRY CcRegularWorkQueue; +extern LIST_ENTRY CcPostTickWorkQueue; extern NPAGED_LOOKASIDE_LIST CcTwilightLookasideList; -extern KEVENT iLazyWriterNotify; typedef struct _PF_SCENARIO_ID {
6 years, 10 months
1
0
0
0
04/09: [NTOSKRNL] Drop the always running thread for lazy writer. Instead move to a threading model like the Windows one. We'll queue several work items to be executed in a system thread (Cc worker) when there are VACB that have been marked as dirty. Furthermore, some delay will be observed before action to avoid killing the system with IOs. This new threading model opens way for read ahead and write behind implementation.
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7e550edb2638b7f597856…
commit 7e550edb2638b7f59785659559d4431c85d3ceda Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Wed Feb 7 18:10:59 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Wed Feb 7 21:37:17 2018 +0100 [NTOSKRNL] Drop the always running thread for lazy writer. Instead move to a threading model like the Windows one. We'll queue several work items to be executed in a system thread (Cc worker) when there are VACB that have been marked as dirty. Furthermore, some delay will be observed before action to avoid killing the system with IOs. This new threading model opens way for read ahead and write behind implementation. Also, moved the initialization of the lazy writer to CcInitializeCacheManager() it has nothing to do with views and shouldn't be initialized there. Also, moved the lazy writer implementation to its own file. Modified CcDeferWrite() and CcRosMarkDirtyVacb() to take into account the new threading model. Introduced new functions: - CcPostWorkQueue(): post an item to be handled by Cc worker and spawn a worker if required - CcScanDpc(): called after some time (not to have lazy writer always running) to queue a lazy scan - CcLazyWriteScan(): the lazy writer we used to have - CcScheduleLazyWriteScan(): function to call when you want to start a lazy writer run. It will make a DPC after some time and queue execution - CcWorkerThread(): the worker thread that will handle lazy write, read ahead, and so on --- ntoskrnl/cache/newcc.h | 2 +- ntoskrnl/cc/cacheman.c | 72 ++++++++++- ntoskrnl/cc/copy.c | 6 + ntoskrnl/cc/lazywrite.c | 283 +++++++++++++++++++++++++++++++++++++++++ ntoskrnl/cc/view.c | 173 +------------------------ ntoskrnl/include/internal/cc.h | 61 ++++++++- ntoskrnl/ntos.cmake | 1 + 7 files changed, 426 insertions(+), 172 deletions(-) diff --git a/ntoskrnl/cache/newcc.h b/ntoskrnl/cache/newcc.h index 63f4841229..adbf1c5d92 100644 --- a/ntoskrnl/cache/newcc.h +++ b/ntoskrnl/cache/newcc.h @@ -53,7 +53,7 @@ CcMdlWriteComplete2(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain); -BOOLEAN +VOID NTAPI CcInitView(VOID); diff --git a/ntoskrnl/cc/cacheman.c b/ntoskrnl/cc/cacheman.c index 8303dd9dd8..1718ddebca 100644 --- a/ntoskrnl/cc/cacheman.c +++ b/ntoskrnl/cc/cacheman.c @@ -16,6 +16,9 @@ BOOLEAN CcPfEnablePrefetcher; PFSN_PREFETCHER_GLOBALS CcPfGlobals; +MM_SYSTEMSIZE CcCapturedSystemSize; + +static ULONG BugCheckFileId = 0x4 << 16; /* FUNCTIONS *****************************************************************/ @@ -42,15 +45,78 @@ NTAPI INIT_FUNCTION CcInitializeCacheManager(VOID) { - return CcInitView(); + ULONG Thread; + + CcInitView(); + + /* Initialize lazy-writer lists */ + InitializeListHead(&CcIdleWorkerThreadList); + InitializeListHead(&CcRegularWorkQueue); + + /* Define lazy writer threshold and the amount of workers, + * depending on the system type + */ + CcCapturedSystemSize = MmQuerySystemSize(); + switch (CcCapturedSystemSize) + { + case MmSmallSystem: + CcNumberWorkerThreads = ExCriticalWorkerThreads - 1; + CcDirtyPageThreshold = MmNumberOfPhysicalPages / 8; + break; + + case MmMediumSystem: + CcNumberWorkerThreads = ExCriticalWorkerThreads - 1; + CcDirtyPageThreshold = MmNumberOfPhysicalPages / 4; + break; + + case MmLargeSystem: + CcNumberWorkerThreads = ExCriticalWorkerThreads - 2; + CcDirtyPageThreshold = MmNumberOfPhysicalPages / 8 + MmNumberOfPhysicalPages / 4; + break; + + default: + CcNumberWorkerThreads = 1; + CcDirtyPageThreshold = MmNumberOfPhysicalPages / 8; + break; + } + + /* Allocate a work item for all our threads */ + for (Thread = 0; Thread < CcNumberWorkerThreads; ++Thread) + { + PWORK_QUEUE_ITEM Item; + + Item = ExAllocatePoolWithTag(NonPagedPool, sizeof(WORK_QUEUE_ITEM), 'qWcC'); + if (Item == NULL) + { + CcBugCheck(0, 0, 0); + } + + /* By default, it's obviously idle */ + ExInitializeWorkItem(Item, CcWorkerThread, Item); + InsertTailList(&CcIdleWorkerThreadList, &Item->List); + } + + /* Initialize our lazy writer */ + RtlZeroMemory(&LazyWriter, sizeof(LazyWriter)); + InitializeListHead(&LazyWriter.WorkQueue); + /* Delay activation of the lazy writer */ + KeInitializeDpc(&LazyWriter.ScanDpc, CcScanDpc, NULL); + KeInitializeTimer(&LazyWriter.ScanTimer); + + /* Lookaside list for our work items */ + ExInitializeNPagedLookasideList(&CcTwilightLookasideList, NULL, NULL, 0, sizeof(WORK_QUEUE_ENTRY), 'KWcC', 0); + + /* HACK: for lazy writer watching */ + KeInitializeEvent(&iLazyWriterNotify, NotificationEvent, FALSE); + + return TRUE; } VOID NTAPI CcShutdownSystem(VOID) { - /* Inform the lazy writer it has to stop activity */ - CcShutdownLazyWriter(); + /* NOTHING TO DO */ } /* diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c index 3d60a1aded..194526c559 100644 --- a/ntoskrnl/cc/copy.c +++ b/ntoskrnl/cc/copy.c @@ -533,6 +533,12 @@ CcDeferWrite ( &Context->DeferredWriteLinks, &CcDeferredWriteSpinLock); } + + /* FIXME: lock master */ + if (!LazyWriter.ScanActive) + { + CcScheduleLazyWriteScan(FALSE); + } } /* diff --git a/ntoskrnl/cc/lazywrite.c b/ntoskrnl/cc/lazywrite.c new file mode 100644 index 0000000000..bda7ca27de --- /dev/null +++ b/ntoskrnl/cc/lazywrite.c @@ -0,0 +1,283 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cc/lazywrite.c + * PURPOSE: Cache manager + * + * PROGRAMMERS: Pierre Schweitzer (pierre(a)reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include <ntoskrnl.h> +#define NDEBUG +#include <debug.h> + +typedef enum _WORK_QUEUE_FUNCTIONS +{ + ReadAhead = 1, + WriteBehind = 2, + LazyWrite = 3, + SetDone = 4, +} WORK_QUEUE_FUNCTIONS, *PWORK_QUEUE_FUNCTIONS; + +/* Counters: + * - Amount of pages flushed by lazy writer + * - Number of times lazy writer ran + */ +ULONG CcLazyWritePages = 0; +ULONG CcLazyWriteIos = 0; + +/* Internal vars (MS): + * - Lazy writer status structure + * - Lookaside list where to allocate work items + * - Queue for regular work items + * - Available worker threads + * - Marker for throttling queues + * - Number of ongoing workers + * - Three seconds delay for lazy writer + * - One second delay for lazy writer + * - Zero delay for lazy writer + * - Number of worker threads + */ +LAZY_WRITER LazyWriter; +NPAGED_LOOKASIDE_LIST CcTwilightLookasideList; +LIST_ENTRY CcRegularWorkQueue; +LIST_ENTRY CcIdleWorkerThreadList; +BOOLEAN CcQueueThrottle = FALSE; +ULONG CcNumberActiveWorkerThreads = 0; +LARGE_INTEGER CcFirstDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)-1*3000*1000*10); +LARGE_INTEGER CcIdleDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)-1*1000*1000*10); +LARGE_INTEGER CcNoDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)0); +ULONG CcNumberWorkerThreads; + +/* Internal vars (ROS): + */ +KEVENT iLazyWriterNotify; + +/* FUNCTIONS *****************************************************************/ + +VOID +CcPostWorkQueue( + IN PWORK_QUEUE_ENTRY WorkItem, + IN PLIST_ENTRY WorkQueue) +{ + KIRQL OldIrql; + PWORK_QUEUE_ITEM ThreadToSpawn; + + /* First of all, insert the item in the queue */ + OldIrql = KeAcquireQueuedSpinLock(LockQueueWorkQueueLock); + InsertTailList(WorkQueue, &WorkItem->WorkQueueLinks); + + /* Now, define whether we have to spawn a new work thread + * We will spawn a new one if: + * - There's no throttle in action + * - There's still at least one idle thread + */ + ThreadToSpawn = NULL; + if (!CcQueueThrottle && !IsListEmpty(&CcIdleWorkerThreadList)) + { + PLIST_ENTRY ListEntry; + + /* Get the idle thread */ + ListEntry = RemoveHeadList(&CcIdleWorkerThreadList); + ThreadToSpawn = CONTAINING_RECORD(ListEntry, WORK_QUEUE_ITEM, List); + + /* We're going to have one more! */ + CcNumberActiveWorkerThreads += 1; + } + + KeReleaseQueuedSpinLock(LockQueueWorkQueueLock, OldIrql); + + /* If we have a thread to spawn, do it! */ + if (ThreadToSpawn != NULL) + { + /* We NULLify it to be consistent with initialization */ + ThreadToSpawn->List.Flink = NULL; + ExQueueWorkItem(ThreadToSpawn, CriticalWorkQueue); + } +} + +VOID +NTAPI +CcScanDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + PWORK_QUEUE_ENTRY WorkItem; + + /* Allocate a work item */ + WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList); + if (WorkItem == NULL) + { + LazyWriter.ScanActive = FALSE; + return; + } + + /* And post it, it will be for lazy write */ + WorkItem->Function = LazyWrite; + CcPostWorkQueue(WorkItem, &CcRegularWorkQueue); +} + +/* FIXME: handle master lock */ +VOID +CcLazyWriteScan(VOID) +{ + ULONG Target; + ULONG Count; + PLIST_ENTRY ListEntry; + + /* We're not sleeping anymore */ + KeClearEvent(&iLazyWriterNotify); + + /* Our target is one-eighth of the dirty pages */ + Target = CcTotalDirtyPages / 8; + if (Target != 0) + { + /* Flush! */ + DPRINT1("Lazy writer starting (%d)\n", Target); + CcRosFlushDirtyPages(Target, &Count, FALSE, TRUE); + + /* And update stats */ + CcLazyWritePages += Count; + ++CcLazyWriteIos; + DPRINT1("Lazy writer done (%d)\n", Count); + } + + /* Inform people waiting on us that we're done */ + KeSetEvent(&iLazyWriterNotify, IO_DISK_INCREMENT, FALSE); + + /* Likely not optimal, but let's handle one deferred write now! */ + ListEntry = ExInterlockedRemoveHeadList(&CcDeferredWrites, &CcDeferredWriteSpinLock); + if (ListEntry != NULL) + { + PDEFERRED_WRITE Context; + + /* Extract the context */ + Context = CONTAINING_RECORD(ListEntry, DEFERRED_WRITE, DeferredWriteLinks); + ASSERT(Context->NodeTypeCode == NODE_TYPE_DEFERRED_WRITE); + + /* Can we write now? */ + if (CcCanIWrite(Context->FileObject, Context->BytesToWrite, FALSE, TRUE)) + { + /* Yes! Do it, and destroy the associated context */ + Context->PostRoutine(Context->Context1, Context->Context2); + ExFreePoolWithTag(Context, 'CcDw'); + } + else + { + /* Otherwise, requeue it, but in tail, so that it doesn't block others + * This is clearly to improve, but given the poor algorithm used now + * It's better than nothing! + */ + ExInterlockedInsertTailList(&CcDeferredWrites, + &Context->DeferredWriteLinks, + &CcDeferredWriteSpinLock); + } + } + + /* We're no longer active */ + LazyWriter.ScanActive = FALSE; +} + +VOID CcScheduleLazyWriteScan( + IN BOOLEAN NoDelay) +{ + /* If no delay, immediately start lazy writer, + * no matter it was already started + */ + if (NoDelay) + { + LazyWriter.ScanActive = TRUE; + KeSetTimer(&LazyWriter.ScanTimer, CcNoDelay, &LazyWriter.ScanDpc); + } + /* Otherwise, if it's not running, just wait three seconds to start it */ + else if (!LazyWriter.ScanActive) + { + LazyWriter.ScanActive = TRUE; + KeSetTimer(&LazyWriter.ScanTimer, CcFirstDelay, &LazyWriter.ScanDpc); + } + /* Finally, already running, so queue for the next second */ + else + { + KeSetTimer(&LazyWriter.ScanTimer, CcIdleDelay, &LazyWriter.ScanDpc); + } +} + +VOID +NTAPI +CcWorkerThread( + IN PVOID Parameter) +{ + KIRQL OldIrql; + BOOLEAN DropThrottle; + PWORK_QUEUE_ITEM Item; + + /* Get back our thread item */ + Item = Parameter; + /* And by default, don't touch throttle */ + DropThrottle = FALSE; + + /* Loop till we have jobs */ + while (TRUE) + { + PWORK_QUEUE_ENTRY WorkItem; + + /* Lock queues */ + OldIrql = KeAcquireQueuedSpinLock(LockQueueWorkQueueLock); + + /* If we have to touch throttle, reset it now! */ + if (DropThrottle) + { + CcQueueThrottle = FALSE; + DropThrottle = FALSE; + } + + /* If no work to do, we're done */ + if (IsListEmpty(&CcRegularWorkQueue)) + { + break; + } + + /* Get our work item, if someone is waiting for us to finish + * and we're not the only thread in queue + * then, quit running to let the others do + * and throttle so that noone starts till current activity is over + */ + WorkItem = CONTAINING_RECORD(CcRegularWorkQueue.Flink, WORK_QUEUE_ENTRY, WorkQueueLinks); + if (WorkItem->Function == SetDone && CcNumberActiveWorkerThreads > 1) + { + CcQueueThrottle = TRUE; + break; + } + + /* Otherwise, remove current entry */ + RemoveEntryList(&WorkItem->WorkQueueLinks); + KeReleaseQueuedSpinLock(LockQueueWorkQueueLock, OldIrql); + + /* And handle it */ + switch (WorkItem->Function) + { + /* We only support lazy write now */ + case LazyWrite: + CcLazyWriteScan(); + break; + + case SetDone: + KeSetEvent(WorkItem->Parameters.Event.Event, IO_NO_INCREMENT, FALSE); + DropThrottle = TRUE; + break; + } + + /* And release the item */ + ExFreeToNPagedLookasideList(&CcTwilightLookasideList, WorkItem); + } + + /* Our thread is available again */ + InsertTailList(&CcIdleWorkerThreadList, &Item->List); + /* One less worker */ + --CcNumberActiveWorkerThreads; + KeReleaseQueuedSpinLock(LockQueueWorkQueueLock, OldIrql); +} diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index 99e7b1c612..e050a33c17 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -51,39 +51,22 @@ NPAGED_LOOKASIDE_LIST iBcbLookasideList; static NPAGED_LOOKASIDE_LIST SharedCacheMapLookasideList; static NPAGED_LOOKASIDE_LIST VacbLookasideList; -/* Counters: - * - Amount of pages flushed by lazy writer - * - Number of times lazy writer ran - */ -ULONG CcLazyWritePages = 0; -ULONG CcLazyWriteIos = 0; - /* Internal vars (MS): * - Threshold above which lazy writer will start action * - Amount of dirty pages * - List for deferred writes * - Spinlock when dealing with the deferred list * - List for "clean" shared cache maps - * - One second delay for lazy writer - * - System size when system started - * - Number of worker threads */ ULONG CcDirtyPageThreshold = 0; ULONG CcTotalDirtyPages = 0; LIST_ENTRY CcDeferredWrites; KSPIN_LOCK CcDeferredWriteSpinLock; LIST_ENTRY CcCleanSharedCacheMapList; -LARGE_INTEGER CcIdleDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)-1*1000*1000*10); -MM_SYSTEMSIZE CcCapturedSystemSize; -ULONG CcNumberWorkerThreads; /* Internal vars (ROS): - * - Event to notify lazy writer to shutdown - * - Event to inform watchers lazy writer is done for this loop * - Lock for the CcCleanSharedCacheMapList list */ -KEVENT iLazyWriterShutdown; -KEVENT iLazyWriterNotify; KSPIN_LOCK iSharedCacheMapLock; #if DBG @@ -304,81 +287,6 @@ CcRosFlushDirtyPages ( return STATUS_SUCCESS; } -/* FIXME: Someday this could somewhat implement write-behind/read-ahead */ -VOID -NTAPI -CciLazyWriter(PVOID Unused) -{ - while (TRUE) - { - NTSTATUS Status; - PLIST_ENTRY ListEntry; - ULONG Target, Count = 0; - - /* One per second or until we have to stop */ - Status = KeWaitForSingleObject(&iLazyWriterShutdown, - Executive, - KernelMode, - FALSE, - &CcIdleDelay); - - /* If we succeeed, we've to stop running! */ - if (Status == STATUS_SUCCESS) - { - break; - } - - /* We're not sleeping anymore */ - KeClearEvent(&iLazyWriterNotify); - - /* Our target is one-eighth of the dirty pages */ - Target = CcTotalDirtyPages / 8; - if (Target != 0) - { - /* Flush! */ - DPRINT("Lazy writer starting (%d)\n", Target); - CcRosFlushDirtyPages(Target, &Count, FALSE, TRUE); - - /* And update stats */ - CcLazyWritePages += Count; - ++CcLazyWriteIos; - DPRINT("Lazy writer done (%d)\n", Count); - } - - /* Inform people waiting on us that we're done */ - KeSetEvent(&iLazyWriterNotify, IO_DISK_INCREMENT, FALSE); - - /* Likely not optimal, but let's handle one deferred write now! */ - ListEntry = ExInterlockedRemoveHeadList(&CcDeferredWrites, &CcDeferredWriteSpinLock); - if (ListEntry != NULL) - { - PDEFERRED_WRITE Context; - - /* Extract the context */ - Context = CONTAINING_RECORD(ListEntry, DEFERRED_WRITE, DeferredWriteLinks); - ASSERT(Context->NodeTypeCode == NODE_TYPE_DEFERRED_WRITE); - - /* Can we write now? */ - if (CcCanIWrite(Context->FileObject, Context->BytesToWrite, FALSE, TRUE)) - { - /* Yes! Do it, and destroy the associated context */ - Context->PostRoutine(Context->Context1, Context->Context2); - ExFreePoolWithTag(Context, 'CcDw'); - } - else - { - /* Otherwise, requeue it, but in tail, so that it doesn't block others - * This is clearly to improve, but given the poor algorithm used now - * It's better than nothing! - */ - ExInterlockedInsertTailList(&CcDeferredWrites, - &Context->DeferredWriteLinks, - &CcDeferredWriteSpinLock); - } - } - } -} - NTSTATUS CcRosTrimCache ( ULONG Target, @@ -611,6 +519,12 @@ CcRosMarkDirtyVacb ( KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldIrql); KeReleaseGuardedMutex(&ViewLock); + + /* FIXME: lock master */ + if (!LazyWriter.ScanActive) + { + CcScheduleLazyWriteScan(FALSE); + } } VOID @@ -1394,25 +1308,11 @@ CcGetFileObjectFromSectionPtrs ( } VOID -NTAPI -CcShutdownLazyWriter ( - VOID) -{ - /* Simply set the event, lazy writer will stop when it's done */ - KeSetEvent(&iLazyWriterShutdown, IO_DISK_INCREMENT, FALSE); -} - -BOOLEAN INIT_FUNCTION NTAPI CcInitView ( VOID) { - HANDLE LazyWriter; - NTSTATUS Status; - KPRIORITY Priority; - OBJECT_ATTRIBUTES ObjectAttributes; - DPRINT("CcInitView()\n"); InitializeListHead(&DirtyVacbListHead); @@ -1446,68 +1346,7 @@ CcInitView ( MmInitializeMemoryConsumer(MC_CACHE, CcRosTrimCache); - /* Initialize lazy writer events */ - KeInitializeEvent(&iLazyWriterShutdown, SynchronizationEvent, FALSE); - KeInitializeEvent(&iLazyWriterNotify, NotificationEvent, FALSE); - - /* Define lazy writer threshold and the amount of workers, - * depending on the system type - */ - CcCapturedSystemSize = MmQuerySystemSize(); - switch (CcCapturedSystemSize) - { - case MmSmallSystem: - CcNumberWorkerThreads = ExCriticalWorkerThreads - 1; - CcDirtyPageThreshold = MmNumberOfPhysicalPages / 8; - break; - - case MmMediumSystem: - CcNumberWorkerThreads = ExCriticalWorkerThreads - 1; - CcDirtyPageThreshold = MmNumberOfPhysicalPages / 4; - break; - - case MmLargeSystem: - CcNumberWorkerThreads = ExCriticalWorkerThreads - 2; - CcDirtyPageThreshold = MmNumberOfPhysicalPages / 8 + MmNumberOfPhysicalPages / 4; - break; - - default: - CcNumberWorkerThreads = 1; - CcDirtyPageThreshold = MmNumberOfPhysicalPages / 8; - break; - } - - /* Start the lazy writer thread */ - InitializeObjectAttributes(&ObjectAttributes, - NULL, - OBJ_KERNEL_HANDLE, - NULL, - NULL); - Status = PsCreateSystemThread(&LazyWriter, - THREAD_ALL_ACCESS, - &ObjectAttributes, - NULL, - NULL, - CciLazyWriter, - NULL); - if (!NT_SUCCESS(Status)) - { - return FALSE; - } - - Priority = 27; - Status = NtSetInformationThread(LazyWriter, - ThreadPriority, - &Priority, - sizeof(Priority)); - ASSERT(NT_SUCCESS(Status)); - - /* Handle is not needed */ - ObCloseHandle(LazyWriter, KernelMode); - CcInitCacheZeroPage(); - - return TRUE; } #if DBG && defined(KDBG) diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h index 3787563941..18d34ef550 100644 --- a/ntoskrnl/include/internal/cc.h +++ b/ntoskrnl/include/internal/cc.h @@ -45,6 +45,11 @@ extern ULONG CcDirtyPageThreshold; extern ULONG CcTotalDirtyPages; extern LIST_ENTRY CcDeferredWrites; extern KSPIN_LOCK CcDeferredWriteSpinLock; +extern ULONG CcNumberWorkerThreads; +extern LIST_ENTRY CcIdleWorkerThreadList; +extern LIST_ENTRY CcRegularWorkQueue; +extern NPAGED_LOOKASIDE_LIST CcTwilightLookasideList; +extern KEVENT iLazyWriterNotify; typedef struct _PF_SCENARIO_ID { @@ -211,6 +216,43 @@ typedef struct _INTERNAL_BCB CSHORT RefCount; /* (At offset 0x34 on WinNT4) */ } INTERNAL_BCB, *PINTERNAL_BCB; +typedef struct _LAZY_WRITER +{ + LIST_ENTRY WorkQueue; + KDPC ScanDpc; + KTIMER ScanTimer; + BOOLEAN ScanActive; + BOOLEAN OtherWork; + BOOLEAN PendingTeardown; +} LAZY_WRITER, *PLAZY_WRITER; + +typedef struct _WORK_QUEUE_ENTRY +{ + LIST_ENTRY WorkQueueLinks; + union + { + struct + { + FILE_OBJECT *FileObject; + } Read; + struct + { + SHARED_CACHE_MAP *SharedCacheMap; + } Write; + struct + { + KEVENT *Event; + } Event; + struct + { + unsigned long Reason; + } Notification; + } Parameters; + unsigned char Function; +} WORK_QUEUE_ENTRY, *PWORK_QUEUE_ENTRY; + +extern LAZY_WRITER LazyWriter; + #define NODE_TYPE_DEFERRED_WRITE 0x02FC VOID @@ -249,7 +291,7 @@ CcRosGetVacb( PROS_VACB *Vacb ); -BOOLEAN +VOID NTAPI CcInitView(VOID); @@ -371,6 +413,21 @@ VOID NTAPI CcShutdownSystem(VOID); +VOID +NTAPI +CcWorkerThread(PVOID Parameter); + +VOID +NTAPI +CcScanDpc( + PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2); + +VOID +CcScheduleLazyWriteScan(BOOLEAN NoDelay); + FORCEINLINE NTSTATUS CcRosAcquireVacbLock( @@ -418,3 +475,5 @@ IsPointInRange( { return DoRangesIntersect(Offset1, Length1, Point, 1); } + +#define CcBugCheck(A, B, C) KeBugCheckEx(CACHE_MANAGER, BugCheckFileId | ((ULONG)(__LINE__)), A, B, C) diff --git a/ntoskrnl/ntos.cmake b/ntoskrnl/ntos.cmake index ceb287656a..94e0dc8055 100644 --- a/ntoskrnl/ntos.cmake +++ b/ntoskrnl/ntos.cmake @@ -33,6 +33,7 @@ else() ${REACTOS_SOURCE_DIR}/ntoskrnl/cc/cacheman.c ${REACTOS_SOURCE_DIR}/ntoskrnl/cc/copy.c ${REACTOS_SOURCE_DIR}/ntoskrnl/cc/fs.c + ${REACTOS_SOURCE_DIR}/ntoskrnl/cc/lazywrite.c ${REACTOS_SOURCE_DIR}/ntoskrnl/cc/mdl.c ${REACTOS_SOURCE_DIR}/ntoskrnl/cc/pin.c ${REACTOS_SOURCE_DIR}/ntoskrnl/cc/view.c)
6 years, 10 months
1
0
0
0
03/09: [NTOSKRNL] On Cc init, also define CcNumberWorkerThreads which will be used later on Also make a "default" case (really limited) in case SystemSize doesn't match.
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3b147adafb8eaf3568e0f…
commit 3b147adafb8eaf3568e0fbfbb69350d4947d0a00 Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Wed Feb 7 17:52:51 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Wed Feb 7 21:37:17 2018 +0100 [NTOSKRNL] On Cc init, also define CcNumberWorkerThreads which will be used later on Also make a "default" case (really limited) in case SystemSize doesn't match. --- ntoskrnl/cc/view.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c index 9344a97c8d..99e7b1c612 100644 --- a/ntoskrnl/cc/view.c +++ b/ntoskrnl/cc/view.c @@ -66,6 +66,7 @@ ULONG CcLazyWriteIos = 0; * - List for "clean" shared cache maps * - One second delay for lazy writer * - System size when system started + * - Number of worker threads */ ULONG CcDirtyPageThreshold = 0; ULONG CcTotalDirtyPages = 0; @@ -74,6 +75,7 @@ KSPIN_LOCK CcDeferredWriteSpinLock; LIST_ENTRY CcCleanSharedCacheMapList; LARGE_INTEGER CcIdleDelay = RTL_CONSTANT_LARGE_INTEGER((LONGLONG)-1*1000*1000*10); MM_SYSTEMSIZE CcCapturedSystemSize; +ULONG CcNumberWorkerThreads; /* Internal vars (ROS): * - Event to notify lazy writer to shutdown @@ -1448,21 +1450,31 @@ CcInitView ( KeInitializeEvent(&iLazyWriterShutdown, SynchronizationEvent, FALSE); KeInitializeEvent(&iLazyWriterNotify, NotificationEvent, FALSE); - /* Define lazy writer threshold, depending on system type */ + /* Define lazy writer threshold and the amount of workers, + * depending on the system type + */ CcCapturedSystemSize = MmQuerySystemSize(); switch (CcCapturedSystemSize) { case MmSmallSystem: + CcNumberWorkerThreads = ExCriticalWorkerThreads - 1; CcDirtyPageThreshold = MmNumberOfPhysicalPages / 8; break; case MmMediumSystem: + CcNumberWorkerThreads = ExCriticalWorkerThreads - 1; CcDirtyPageThreshold = MmNumberOfPhysicalPages / 4; break; case MmLargeSystem: + CcNumberWorkerThreads = ExCriticalWorkerThreads - 2; CcDirtyPageThreshold = MmNumberOfPhysicalPages / 8 + MmNumberOfPhysicalPages / 4; break; + + default: + CcNumberWorkerThreads = 1; + CcDirtyPageThreshold = MmNumberOfPhysicalPages / 8; + break; } /* Start the lazy writer thread */
6 years, 10 months
1
0
0
0
← Newer
1
...
15
16
17
18
19
20
21
...
24
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
Results per page:
10
25
50
100
200