Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/cc/cacheman.c * PURPOSE: Cache manager * * PROGRAMMERS: David Welch (welch@cwcom.net) * Pierre Schweitzer (pierre@reactos.org) */
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>#define NDEBUG#include <debug.h>
BOOLEAN CcPfEnablePrefetcher;PFSN_PREFETCHER_GLOBALS CcPfGlobals;MM_SYSTEMSIZE CcCapturedSystemSize;
static ULONG BugCheckFileId = 0x4 << 16;
/* FUNCTIONS *****************************************************************/
CODE_SEG("INIT")VOIDNTAPICcPfInitializePrefetcher(VOID){ /* Notify debugger */ DbgPrintEx(DPFLTR_PREFETCHER_ID, DPFLTR_TRACE_LEVEL, "CCPF: InitializePrefetecher()\n");
/* Setup the Prefetcher Data */ InitializeListHead(&CcPfGlobals.ActiveTraces); InitializeListHead(&CcPfGlobals.CompletedTraces); ExInitializeFastMutex(&CcPfGlobals.CompletedTracesLock);
/* FIXME: Setup the rest of the prefetecher */}
CODE_SEG("INIT")BOOLEANCcInitializeCacheManager(VOID){ ULONG Thread;
CcInitView();
/* Initialize lazy-writer lists */ InitializeListHead(&CcIdleWorkerThreadList); InitializeListHead(&CcExpressWorkQueue); InitializeListHead(&CcRegularWorkQueue); InitializeListHead(&CcPostTickWorkQueue);
/* 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);
return TRUE;}
VOIDNTAPICcShutdownSystem(VOID){ /* NOTHING TO DO */}
/* * @unimplemented */LARGE_INTEGERNTAPICcGetFlushedValidData ( IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN BOOLEAN BcbListHeld ){ LARGE_INTEGER i;
UNIMPLEMENTED;
i.QuadPart = 0; return i;}
/* * @unimplemented */PVOIDNTAPICcRemapBcb ( IN PVOID Bcb ){ UNIMPLEMENTED;
return 0;}
/* * @unimplemented */VOIDNTAPICcScheduleReadAhead ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length ){ KIRQL OldIrql; LARGE_INTEGER NewOffset; PROS_SHARED_CACHE_MAP SharedCacheMap; PPRIVATE_CACHE_MAP PrivateCacheMap;
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; PrivateCacheMap = FileObject->PrivateCacheMap;
/* If file isn't cached, or if read ahead is disabled, this is no op */ if (SharedCacheMap == NULL || PrivateCacheMap == NULL || BooleanFlagOn(SharedCacheMap->Flags, READAHEAD_DISABLED)) { return; }
/* Round read length with read ahead mask */ Length = ROUND_UP(Length, PrivateCacheMap->ReadAheadMask + 1); /* Compute the offset we'll reach */ NewOffset.QuadPart = FileOffset->QuadPart + Length;
/* Lock read ahead spin lock */ KeAcquireSpinLock(&PrivateCacheMap->ReadAheadSpinLock, &OldIrql); /* Easy case: the file is sequentially read */ if (BooleanFlagOn(FileObject->Flags, FO_SEQUENTIAL_ONLY)) { /* If we went backward, this is no go! */ if (NewOffset.QuadPart < PrivateCacheMap->ReadAheadOffset[1].QuadPart) { KeReleaseSpinLock(&PrivateCacheMap->ReadAheadSpinLock, OldIrql); return; }
/* FIXME: hackish, but will do the job for now */ PrivateCacheMap->ReadAheadOffset[1].QuadPart = NewOffset.QuadPart; PrivateCacheMap->ReadAheadLength[1] = Length; } /* Other cases: try to find some logic in that mess... */ else { /* Let's check if we always read the same way (like going down in the file) * and pretend it's enough for now */ if (PrivateCacheMap->FileOffset2.QuadPart >= PrivateCacheMap->FileOffset1.QuadPart && FileOffset->QuadPart >= PrivateCacheMap->FileOffset2.QuadPart) { /* FIXME: hackish, but will do the job for now */ PrivateCacheMap->ReadAheadOffset[1].QuadPart = NewOffset.QuadPart; PrivateCacheMap->ReadAheadLength[1] = Length; } else { /* FIXME: handle the other cases */ KeReleaseSpinLock(&PrivateCacheMap->ReadAheadSpinLock, OldIrql); UNIMPLEMENTED_ONCE; return; } }
/* If read ahead isn't active yet */ if (!PrivateCacheMap->Flags.ReadAheadActive) { PWORK_QUEUE_ENTRY WorkItem;
/* It's active now! * Be careful with the mask, you don't want to mess with node code */ InterlockedOr((volatile long *)&PrivateCacheMap->UlongFlags, PRIVATE_CACHE_MAP_READ_AHEAD_ACTIVE); KeReleaseSpinLock(&PrivateCacheMap->ReadAheadSpinLock, OldIrql);
/* Get a work item */ WorkItem = ExAllocateFromNPagedLookasideList(&CcTwilightLookasideList); if (WorkItem != NULL) { /* Reference our FO so that it doesn't go in between */ ObReferenceObject(FileObject);
/* We want to do read ahead! */ WorkItem->Function = ReadAhead; WorkItem->Parameters.Read.FileObject = FileObject;
/* Queue in the read ahead dedicated queue */ CcPostWorkQueue(WorkItem, &CcExpressWorkQueue);
return; }
/* Fail path: lock again, and revert read ahead active */ KeAcquireSpinLock(&PrivateCacheMap->ReadAheadSpinLock, &OldIrql); InterlockedAnd((volatile long *)&PrivateCacheMap->UlongFlags, ~PRIVATE_CACHE_MAP_READ_AHEAD_ACTIVE); }
/* Done (fail) */ KeReleaseSpinLock(&PrivateCacheMap->ReadAheadSpinLock, OldIrql);}
/* * @implemented */VOIDNTAPICcSetAdditionalCacheAttributes ( IN PFILE_OBJECT FileObject, IN BOOLEAN DisableReadAhead, IN BOOLEAN DisableWriteBehind ){ KIRQL OldIrql; PROS_SHARED_CACHE_MAP SharedCacheMap;
CCTRACE(CC_API_DEBUG, "FileObject=%p DisableReadAhead=%d DisableWriteBehind=%d\n", FileObject, DisableReadAhead, DisableWriteBehind);
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
if (DisableReadAhead) { SetFlag(SharedCacheMap->Flags, READAHEAD_DISABLED); } else { ClearFlag(SharedCacheMap->Flags, READAHEAD_DISABLED); }
if (DisableWriteBehind) { /* FIXME: also set flag 0x200 */ SetFlag(SharedCacheMap->Flags, WRITEBEHIND_DISABLED); } else { ClearFlag(SharedCacheMap->Flags, WRITEBEHIND_DISABLED); } KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);}
/* * @unimplemented */VOIDNTAPICcSetBcbOwnerPointer ( IN PVOID Bcb, IN PVOID Owner ){ PINTERNAL_BCB iBcb = CONTAINING_RECORD(Bcb, INTERNAL_BCB, PFCB);
CCTRACE(CC_API_DEBUG, "Bcb=%p Owner=%p\n", Bcb, Owner);
if (!ExIsResourceAcquiredExclusiveLite(&iBcb->Lock) && !ExIsResourceAcquiredSharedLite(&iBcb->Lock)) { DPRINT1("Current thread doesn't own resource!\n"); return; }
ExSetResourceOwnerPointer(&iBcb->Lock, Owner);}
/* * @implemented */VOIDNTAPICcSetDirtyPageThreshold ( IN PFILE_OBJECT FileObject, IN ULONG DirtyPageThreshold ){ PFSRTL_COMMON_FCB_HEADER Fcb; PROS_SHARED_CACHE_MAP SharedCacheMap;
CCTRACE(CC_API_DEBUG, "FileObject=%p DirtyPageThreshold=%lu\n", FileObject, DirtyPageThreshold);
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; if (SharedCacheMap != NULL) { SharedCacheMap->DirtyPageThreshold = DirtyPageThreshold; }
Fcb = FileObject->FsContext; if (!BooleanFlagOn(Fcb->Flags, FSRTL_FLAG_LIMIT_MODIFIED_PAGES)) { SetFlag(Fcb->Flags, FSRTL_FLAG_LIMIT_MODIFIED_PAGES); }}
/* * @implemented */VOIDNTAPICcSetReadAheadGranularity ( IN PFILE_OBJECT FileObject, IN ULONG Granularity ){ PPRIVATE_CACHE_MAP PrivateMap;
CCTRACE(CC_API_DEBUG, "FileObject=%p Granularity=%lu\n", FileObject, Granularity);
PrivateMap = FileObject->PrivateCacheMap; PrivateMap->ReadAheadMask = Granularity - 1;}