/* GLOBALS *******************************************************************/
+/*
+ * If CACHE_BITMAP is defined, the cache manager uses one large memory region
+ * within the kernel address space and allocate/deallocate space from this block
+ * over a bitmap. If CACHE_BITMAP is used, the size of the mdl mapping region
+ * must be reduced (ntoskrnl\mm\mdl.c, MI_MDLMAPPING_REGION_SIZE).
+ */
+//#define CACHE_BITMAP
+
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
#define ROUND_DOWN(N, S) (((N) % (S)) ? ROUND_UP(N, S) - S : N)
#define TAG_CSEG TAG('C', 'S', 'E', 'G')
#define TAG_BCB TAG('B', 'C', 'B', ' ')
+#define TAG_IBCB TAG('i', 'B', 'C', 'B')
static LIST_ENTRY DirtySegmentListHead;
static LIST_ENTRY CacheSegmentListHead;
static LIST_ENTRY CacheSegmentLRUListHead;
+static LIST_ENTRY ClosedListHead;
+static ULONG DirtyPageCount=0;
static FAST_MUTEX ViewLock;
+#ifndef LIBCAPTIVE
+#ifdef CACHE_BITMAP
+#define CI_CACHESEG_MAPPING_REGION_SIZE (128*1024*1024)
+
+static PVOID CiCacheSegMappingRegionBase = NULL;
+static RTL_BITMAP CiCacheSegMappingRegionAllocMap;
+static ULONG CiCacheSegMappingRegionHint;
+static KSPIN_LOCK CiCacheSegMappingRegionLock;
+#endif
+
+NPAGED_LOOKASIDE_LIST iBcbLookasideList;
+static NPAGED_LOOKASIDE_LIST BcbLookasideList;
+static NPAGED_LOOKASIDE_LIST CacheSegLookasideList;
+
+static ULONG CcTimeStamp;
+static KEVENT LazyCloseThreadEvent;
+static HANDLE LazyCloseThreadHandle;
+static CLIENT_ID LazyCloseThreadId;
+static volatile BOOLEAN LazyCloseThreadShouldTerminate;
+
void * alloca(size_t size);
-NTSTATUS STDCALL
+NTSTATUS
CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
+#endif /* LIBCAPTIVE */
/* FUNCTIONS *****************************************************************/
+#ifndef LIBCAPTIVE
+
NTSTATUS STATIC
CcRosFlushCacheSegment(PCACHE_SEGMENT CacheSegment)
{
KeAcquireSpinLock(&CacheSegment->Bcb->BcbLock, &oldIrql);
CacheSegment->Dirty = FALSE;
RemoveEntryList(&CacheSegment->DirtySegmentListEntry);
+ DirtyPageCount -= CacheSegment->Bcb->CacheSegmentSize / PAGE_SIZE;
CacheSegment->ReferenceCount--;
KeReleaseSpinLock(&CacheSegment->Bcb->BcbLock, oldIrql);
ExReleaseFastMutex(&ViewLock);
return(Status);
}
+VOID CcRosRemoveUnusedFiles(VOID);
+
+
NTSTATUS
CcRosFlushDirtyPages(ULONG Target, PULONG Count)
{
ULONG PagesPerSegment;
BOOLEAN Locked;
NTSTATUS Status;
+ static ULONG WriteCount[4] = {0, 0, 0, 0};
+ ULONG NewTarget;
DPRINT("CcRosFlushDirtyPages(Target %d)\n", Target);
(*Count) = 0;
ExAcquireFastMutex(&ViewLock);
+
+ WriteCount[0] = WriteCount[1];
+ WriteCount[1] = WriteCount[2];
+ WriteCount[2] = WriteCount[3];
+ WriteCount[3] = 0;
+
+ NewTarget = WriteCount[0] + WriteCount[1] + WriteCount[2];
+
+ if (NewTarget < DirtyPageCount)
+ {
+ NewTarget = (DirtyPageCount - NewTarget + 3) / 4;
+ WriteCount[0] += NewTarget;
+ WriteCount[1] += NewTarget;
+ WriteCount[2] += NewTarget;
+ WriteCount[3] += NewTarget;
+ }
+
+ NewTarget = WriteCount[0];
+
+ Target = max(NewTarget, Target);
+
current_entry = DirtySegmentListHead.Flink;
+ if (current_entry == &DirtySegmentListHead)
+ {
+ DPRINT("No Dirty pages\n");
+ }
while (current_entry != &DirtySegmentListHead && Target > 0)
{
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
ExAcquireFastMutex(&ViewLock);
current_entry = DirtySegmentListHead.Flink;
}
+ if (*Count < NewTarget)
+ {
+ WriteCount[1] += (NewTarget - *Count);
+ }
ExReleaseFastMutex(&ViewLock);
- DPRINT("CcRosTrimCache() finished\n");
+ DPRINT("CcRosFlushDirtyPages() finished\n");
+
return(STATUS_SUCCESS);
}
return(STATUS_SUCCESS);
}
-NTSTATUS STDCALL
+#endif /* LIBCAPTIVE */
+
+NTSTATUS
CcRosReleaseCacheSegment(PBCB Bcb,
PCACHE_SEGMENT CacheSeg,
BOOLEAN Valid,
BOOLEAN WasDirty = CacheSeg->Dirty;
KIRQL oldIrql;
+ assert(Bcb);
+
DPRINT("CcReleaseCacheSegment(Bcb %x, CacheSeg %x, Valid %d)\n",
Bcb, CacheSeg, Valid);
if (!WasDirty && CacheSeg->Dirty)
{
InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
+ DirtyPageCount += Bcb->CacheSegmentSize / PAGE_SIZE;
}
RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry);
InsertTailList(&CacheSegmentLRUListHead, &CacheSeg->CacheSegmentLRUListEntry);
return(STATUS_SUCCESS);
}
-PCACHE_SEGMENT CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset)
+PCACHE_SEGMENT
+CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset)
{
PLIST_ENTRY current_entry;
PCACHE_SEGMENT current;
KIRQL oldIrql;
+ assert(Bcb);
+
DPRINT("CcRosLookupCacheSegment(Bcb %x, FileOffset %d)\n", Bcb, FileOffset);
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
return(NULL);
}
+#ifndef LIBCAPTIVE
+
NTSTATUS
CcRosMarkDirtyCacheSegment(PBCB Bcb, ULONG FileOffset)
{
PCACHE_SEGMENT CacheSeg;
KIRQL oldIrql;
+ assert(Bcb);
+
DPRINT("CcRosMarkDirtyCacheSegment(Bcb %x, FileOffset %d)\n", Bcb, FileOffset);
CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset);
{
ExAcquireFastMutex(&ViewLock);
InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
+ DirtyPageCount += Bcb->CacheSegmentSize / PAGE_SIZE;
ExReleaseFastMutex(&ViewLock);
}
else
BOOLEAN WasDirty;
KIRQL oldIrql;
+ assert(Bcb);
+
DPRINT("CcRosUnmapCacheSegment(Bcb %x, FileOffset %d, NowDirty %d)\n",
Bcb, FileOffset, NowDirty);
{
ExAcquireFastMutex(&ViewLock);
InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
+ DirtyPageCount += Bcb->CacheSegmentSize / PAGE_SIZE;
ExReleaseFastMutex(&ViewLock);
}
return(STATUS_SUCCESS);
}
+#endif /* LIBCAPTIVE */
+
NTSTATUS STATIC
CcRosCreateCacheSegment(PBCB Bcb,
ULONG FileOffset,
PCACHE_SEGMENT* CacheSeg,
BOOLEAN Lock)
{
+#ifndef LIBCAPTIVE
ULONG i;
+#endif /* LIBCAPTIVE */
PCACHE_SEGMENT current;
PLIST_ENTRY current_entry;
NTSTATUS Status;
KIRQL oldIrql;
+#ifdef CACHE_BITMAP
+ ULONG StartingOffset;
+#endif
+
+ assert(Bcb);
DPRINT("CcRosCreateCacheSegment()\n");
- current = ExAllocatePoolWithTag(NonPagedPool, sizeof(CACHE_SEGMENT),
- TAG_CSEG);
+ current = ExAllocateFromNPagedLookasideList(&CacheSegLookasideList);
current->Valid = FALSE;
current->Dirty = FALSE;
current->FileOffset = ROUND_DOWN(FileOffset, Bcb->CacheSegmentSize);
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
ExReleaseFastMutex(&(*CacheSeg)->Lock);
ExReleaseFastMutex(&ViewLock);
- ExFreePool(*CacheSeg);
+ ExFreeToNPagedLookasideList(&CacheSegLookasideList, *CacheSeg);
*CacheSeg = current;
if (Lock)
{
InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry);
InsertTailList(&CacheSegmentLRUListHead, ¤t->CacheSegmentLRUListEntry);
ExReleaseFastMutex(&ViewLock);
+#ifdef CACHE_BITMAP
+ KeAcquireSpinLock(&CiCacheSegMappingRegionLock, &oldIrql);
+
+ StartingOffset = RtlFindClearBitsAndSet(&CiCacheSegMappingRegionAllocMap, Bcb->CacheSegmentSize / PAGE_SIZE, CiCacheSegMappingRegionHint);
+
+ if (StartingOffset == 0xffffffff)
+ {
+ DPRINT1("Out of CacheSeg mapping space\n");
+ KeBugCheck(0);
+ }
+
+ current->BaseAddress = CiCacheSegMappingRegionBase + StartingOffset * PAGE_SIZE;
+
+ if (CiCacheSegMappingRegionHint == StartingOffset)
+ {
+ CiCacheSegMappingRegionHint += Bcb->CacheSegmentSize / PAGE_SIZE;
+ }
+ KeReleaseSpinLock(&CiCacheSegMappingRegionLock, oldIrql);
+#else
MmLockAddressSpace(MmGetKernelAddressSpace());
current->BaseAddress = NULL;
Status = MmCreateMemoryArea(NULL,
{
KeBugCheck(0);
}
+#endif
+#ifndef LIBCAPTIVE
for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++)
{
PHYSICAL_ADDRESS Page;
KeBugCheck(0);
}
}
+#else /* !LIBCAPTIVE */
+ /* libcaptive MmCreateMemoryArea() returns already allocated memory */
+#endif /* !LIBCAPTIVE */
if (!Lock)
{
ExReleaseFastMutex(¤t->Lock);
return(STATUS_SUCCESS);
}
+#ifndef LIBCAPTIVE
+
NTSTATUS
CcRosGetCacheSegmentChain(PBCB Bcb,
ULONG FileOffset,
PCACHE_SEGMENT* CacheSegList;
PCACHE_SEGMENT Previous = NULL;
+ assert(Bcb);
+
DPRINT("CcRosGetCacheSegmentChain()\n");
Length = ROUND_UP(Length, Bcb->CacheSegmentSize);
return(STATUS_SUCCESS);
}
+#endif /* LIBCAPTIVE */
+
NTSTATUS
CcRosGetCacheSegment(PBCB Bcb,
ULONG FileOffset,
PCACHE_SEGMENT current;
NTSTATUS Status;
+ assert(Bcb);
+
DPRINT("CcRosGetCacheSegment()\n");
/*
{
ULONG BaseOffset;
+ assert(Bcb);
+
if ((FileOffset % Bcb->CacheSegmentSize) != 0)
{
CPRINT("Bad fileoffset %x should be multiple of %x",
CacheSeg));
}
+#ifndef LIBCAPTIVE
+
+#ifdef CACHE_BITMAP
+#else
STATIC VOID
CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, BOOLEAN Dirty)
MmReleasePageMemoryConsumer(MC_CACHE, PhysAddr);
}
}
-
-NTSTATUS STDCALL
+#endif
+NTSTATUS
CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg)
/*
* FUNCTION: Releases a cache segment associated with a BCB
*/
{
-
+#ifdef CACHE_BITMAP
+ ULONG i;
+ ULONG RegionSize;
+ ULONG Base;
+ PHYSICAL_ADDRESS PhysicalAddr;
+ KIRQL oldIrql;
+#endif
DPRINT("Freeing cache segment %x\n", CacheSeg);
+#ifdef CACHE_BITMAP
+ RegionSize = CacheSeg->Bcb->CacheSegmentSize / PAGE_SIZE;
+
+ /* Unmap all the pages. */
+ for (i = 0; i < RegionSize; i++)
+ {
+ MmDeleteVirtualMapping(NULL,
+ CacheSeg->BaseAddress + (i * PAGE_SIZE),
+ FALSE,
+ NULL,
+ &PhysicalAddr);
+ MmReleasePageMemoryConsumer(MC_CACHE, PhysicalAddr);
+ }
+ KeAcquireSpinLock(&CiCacheSegMappingRegionLock, &oldIrql);
+ /* Deallocate all the pages used. */
+ Base = (ULONG)(CacheSeg->BaseAddress - CiCacheSegMappingRegionBase) / PAGE_SIZE;
+
+ RtlClearBits(&CiCacheSegMappingRegionAllocMap, Base, RegionSize);
+
+ CiCacheSegMappingRegionHint = min (CiCacheSegMappingRegionHint, Base);
+
+ KeReleaseSpinLock(&CiCacheSegMappingRegionLock, oldIrql);
+#else
MmLockAddressSpace(MmGetKernelAddressSpace());
MmFreeMemoryArea(MmGetKernelAddressSpace(),
CacheSeg->BaseAddress,
CcFreeCachePage,
NULL);
MmUnlockAddressSpace(MmGetKernelAddressSpace());
- ExFreePool(CacheSeg);
+#endif
+ ExFreeToNPagedLookasideList(&CacheSegLookasideList, CacheSeg);
return(STATUS_SUCCESS);
}
-NTSTATUS STDCALL
+NTSTATUS
CcRosFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg)
{
NTSTATUS Status;
KIRQL oldIrql;
+ assert(Bcb);
+
DPRINT("CcRosFreeCacheSegment(Bcb %x, CacheSeg %x)\n",
Bcb, CacheSeg);
if (CacheSeg->Dirty)
{
RemoveEntryList(&CacheSeg->DirtySegmentListEntry);
+ DirtyPageCount -= Bcb->CacheSegmentSize / PAGE_SIZE;
+
}
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
ExReleaseFastMutex(&ViewLock);
if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
{
Bcb = (PBCB)SectionObjectPointers->SharedCacheMap;
+ assert(Bcb);
if (FileOffset)
{
Offset = *FileOffset;
IoStatus->Status = Status;
}
}
- ExReleaseFastMutex(¤t->Lock);
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
+ ExReleaseFastMutex(¤t->Lock);
current->ReferenceCount--;
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
}
}
}
-NTSTATUS STDCALL
+NTSTATUS
CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
/*
* FUNCTION: Releases the BCB associated with a file object
NTSTATUS Status;
LIST_ENTRY FreeList;
KIRQL oldIrql;
-
- DPRINT("CcRosDeleteFileCache(FileObject %x, Bcb %x)\n",
- Bcb->FileObject, Bcb);
+ assert(Bcb);
+
+ Bcb->RefCount++;
ExReleaseFastMutex(&ViewLock);
CcFlushCache(FileObject->SectionObjectPointers, NULL, 0, NULL);
ExAcquireFastMutex(&ViewLock);
-
+ Bcb->RefCount--;
if (Bcb->RefCount == 0)
{
- MmFreeSectionSegments(Bcb->FileObject);
+ if (Bcb->BcbRemoveListEntry.Flink != NULL)
+ {
+ RemoveEntryList(&Bcb->BcbRemoveListEntry);
+ Bcb->BcbRemoveListEntry.Flink = NULL;
+ }
+
+ FileObject->SectionObjectPointers->SharedCacheMap = NULL;
/*
* Release all cache segments.
*/
InitializeListHead(&FreeList);
-
- FileObject->SectionObjectPointers->SharedCacheMap = NULL;
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
current_entry = Bcb->BcbSegmentListHead.Flink;
while (!IsListEmpty(&Bcb->BcbSegmentListHead))
if (current->Dirty)
{
RemoveEntryList(¤t->DirtySegmentListEntry);
+ DirtyPageCount -= Bcb->CacheSegmentSize / PAGE_SIZE;
+ DPRINT1("Freeing dirty segment\n");
}
InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry);
-
}
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
+
+ ExReleaseFastMutex(&ViewLock);
+ ObDereferenceObject (Bcb->FileObject);
+
while (!IsListEmpty(&FreeList))
{
current_entry = RemoveTailList(&FreeList);
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
Status = CcRosInternalFreeCacheSegment(current);
}
-
- ObDereferenceObject (Bcb->FileObject);
- ExFreePool(Bcb);
+ ExFreeToNPagedLookasideList(&BcbLookasideList, Bcb);
+ ExAcquireFastMutex(&ViewLock);
}
return(STATUS_SUCCESS);
}
PBCB Bcb;
ExAcquireFastMutex(&ViewLock);
Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
+ assert(Bcb);
Bcb->RefCount++;
ExReleaseFastMutex(&ViewLock);
}
+VOID CcRosSetRemoveOnClose(PSECTION_OBJECT_POINTERS SectionObjectPointer)
+{
+ PBCB Bcb;
+// DPRINT1("CcRosSetRemoveOnClose()\n");
+ ExAcquireFastMutex(&ViewLock);
+ Bcb = (PBCB)SectionObjectPointer->SharedCacheMap;
+ if (Bcb)
+ {
+ Bcb->RemoveOnClose = TRUE;
+ if (Bcb->RefCount == 0)
+ {
+ CcRosDeleteFileCache(Bcb->FileObject, Bcb);
+ }
+ }
+ ExReleaseFastMutex(&ViewLock);
+}
+
+
VOID CcRosDereferenceCache(PFILE_OBJECT FileObject)
{
PBCB Bcb;
ExAcquireFastMutex(&ViewLock);
Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
- Bcb->RefCount--;
- if (Bcb->RefCount == 0)
+ assert(Bcb);
+ if (Bcb->RefCount > 0)
{
- CcRosDeleteFileCache(FileObject, Bcb);
+ Bcb->RefCount--;
+ if (Bcb->RefCount == 0)
+ {
+ MmFreeSectionSegments(Bcb->FileObject);
+ if (Bcb->RemoveOnClose)
+ {
+ CcRosDeleteFileCache(FileObject, Bcb);
+ }
+ else
+ {
+ Bcb->TimeStamp = CcTimeStamp;
+ InsertHeadList(&ClosedListHead, &Bcb->BcbRemoveListEntry);
+ }
+ }
}
ExReleaseFastMutex(&ViewLock);
}
* has been closed.
*/
{
+ assert(Bcb);
+
ExAcquireFastMutex(&ViewLock);
if (FileObject->SectionObjectPointers->SharedCacheMap != NULL)
if (FileObject->PrivateCacheMap != NULL)
{
FileObject->PrivateCacheMap = NULL;
- Bcb->RefCount--;
- }
- if (Bcb->RefCount == 0)
- {
- CcRosDeleteFileCache(FileObject, Bcb);
+ if (Bcb->RefCount > 0)
+ {
+ Bcb->RefCount--;
+ if (Bcb->RefCount == 0)
+ {
+ if (Bcb->RemoveOnClose)
+ {
+ CcRosDeleteFileCache(FileObject, Bcb);
+ }
+ else
+ {
+ Bcb->TimeStamp = CcTimeStamp;
+ InsertHeadList(&ClosedListHead, &Bcb->BcbRemoveListEntry);
+ }
+ }
+ }
}
}
ExReleaseFastMutex(&ViewLock);
if (*Bcb == NULL)
{
- (*Bcb) = ExAllocatePoolWithTag(NonPagedPool, sizeof(BCB), TAG_BCB);
+ (*Bcb) = ExAllocateFromNPagedLookasideList(&BcbLookasideList);
if ((*Bcb) == NULL)
{
+ ExReleaseFastMutex(&ViewLock);
return(STATUS_UNSUCCESSFUL);
}
-
+ memset((*Bcb), 0, sizeof(BCB));
ObReferenceObjectByPointer(FileObject,
FILE_ALL_ACCESS,
NULL,
FileObject->PrivateCacheMap = *Bcb;
(*Bcb)->RefCount++;
}
+ if ((*Bcb)->BcbRemoveListEntry.Flink != NULL)
+ {
+ RemoveEntryList(&(*Bcb)->BcbRemoveListEntry);
+ (*Bcb)->BcbRemoveListEntry.Flink = NULL;
+ }
ExReleaseFastMutex(&ViewLock);
return(STATUS_SUCCESS);
if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
{
Bcb = (PBCB)SectionObjectPointers->SharedCacheMap;
+ assert(Bcb);
return Bcb->FileObject;
}
return NULL;
}
+#endif /* LIBCAPTIVE */
+
+VOID STDCALL
+CmLazyCloseThreadMain(PVOID Ignored)
+{
+ LARGE_INTEGER Timeout;
+ PLIST_ENTRY current_entry;
+ PBCB current;
+ ULONG RemoveTimeStamp;
+ NTSTATUS Status;
+
+ KeQuerySystemTime (&Timeout);
+
+ while (1)
+ {
+ Timeout.QuadPart += 100000000LL; // 10sec
+ Status = KeWaitForSingleObject(&LazyCloseThreadEvent,
+ 0,
+ KernelMode,
+ FALSE,
+ &Timeout);
+
+ DPRINT("LazyCloseThreadMain %d\n", CcTimeStamp);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("LazyCloseThread: Wait failed\n");
+ KeBugCheck(0);
+ break;
+ }
+ if (LazyCloseThreadShouldTerminate)
+ {
+ DbgPrint("LazyCloseThread: Terminating\n");
+ break;
+ }
+
+ ExAcquireFastMutex(&ViewLock);
+ CcTimeStamp++;
+ if (CcTimeStamp >= 30)
+ {
+ RemoveTimeStamp = CcTimeStamp - 30; /* 5min = 10sec * 30 */
+ while (!IsListEmpty(&ClosedListHead))
+ {
+ current_entry = ClosedListHead.Blink;
+ current = CONTAINING_RECORD(current_entry, BCB, BcbRemoveListEntry);
+ if (current->TimeStamp >= RemoveTimeStamp)
+ {
+ break;
+ }
+ CcRosDeleteFileCache(current->FileObject, current);
+ }
+ }
+ ExReleaseFastMutex(&ViewLock);
+ }
+}
+
VOID
CcInitView(VOID)
{
+#ifdef CACHE_BITMAP
+ PMEMORY_AREA marea;
+ PVOID Buffer;
+#endif
+ NTSTATUS Status;
+ KPRIORITY Priority;
+
DPRINT("CcInitView()\n");
+#ifdef CACHE_BITMAP
+ CiCacheSegMappingRegionHint = 0;
+ CiCacheSegMappingRegionBase = NULL;
+
+ MmLockAddressSpace(MmGetKernelAddressSpace());
+
+ Status = MmCreateMemoryArea(NULL,
+ MmGetKernelAddressSpace(),
+ MEMORY_AREA_CACHE_SEGMENT,
+ &CiCacheSegMappingRegionBase,
+ CI_CACHESEG_MAPPING_REGION_SIZE,
+ 0,
+ &marea,
+ FALSE);
+ MmUnlockAddressSpace(MmGetKernelAddressSpace());
+ if (!NT_SUCCESS(Status))
+ {
+ KeBugCheck(0);
+ }
+
+ Buffer = ExAllocatePool(NonPagedPool, CI_CACHESEG_MAPPING_REGION_SIZE / (PAGE_SIZE * 8));
+
+ RtlInitializeBitMap(&CiCacheSegMappingRegionAllocMap, Buffer, CI_CACHESEG_MAPPING_REGION_SIZE / PAGE_SIZE);
+ RtlClearAllBits(&CiCacheSegMappingRegionAllocMap);
+
+ KeInitializeSpinLock(&CiCacheSegMappingRegionLock);
+#endif
InitializeListHead(&CacheSegmentListHead);
InitializeListHead(&DirtySegmentListHead);
InitializeListHead(&CacheSegmentLRUListHead);
+ InitializeListHead(&ClosedListHead);
ExInitializeFastMutex(&ViewLock);
+#ifndef LIBCAPTIVE
+ ExInitializeNPagedLookasideList (&iBcbLookasideList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(INTERNAL_BCB),
+ TAG_IBCB,
+ 20);
+ ExInitializeNPagedLookasideList (&BcbLookasideList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(BCB),
+ TAG_BCB,
+ 20);
+ ExInitializeNPagedLookasideList (&CacheSegLookasideList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(CACHE_SEGMENT),
+ TAG_CSEG,
+ 20);
+
MmInitializeMemoryConsumer(MC_CACHE, CcRosTrimCache);
+
CcInitCacheZeroPage();
+#endif /* LIBCAPTIVE */
+
+ CcTimeStamp = 0;
+ LazyCloseThreadShouldTerminate = FALSE;
+ KeInitializeEvent (&LazyCloseThreadEvent, SynchronizationEvent, FALSE);
+ Status = PsCreateSystemThread(&LazyCloseThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ NULL,
+ &LazyCloseThreadId,
+ (PKSTART_ROUTINE)CmLazyCloseThreadMain,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ Priority = LOW_REALTIME_PRIORITY;
+ NtSetInformationThread(LazyCloseThreadHandle,
+ ThreadPriority,
+ &Priority,
+ sizeof(Priority));
+ }
+
}
/* EOF */