mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 17:44:45 +00:00
Used lookasidelists for some memory allocations.
Implemented a delayed remove/close function for file objects. This holds files for section views (exe's and dll's) longer within the cache. svn path=/trunk/; revision=3970
This commit is contained in:
parent
7a00c6be46
commit
e177cc849d
1 changed files with 314 additions and 39 deletions
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: view.c,v 1.54 2002/12/15 17:01:52 chorns Exp $
|
/* $Id: view.c,v 1.55 2003/01/11 15:24:38 hbirr Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/cc/view.c
|
* FILE: ntoskrnl/cc/view.c
|
||||||
|
@ -63,21 +63,50 @@
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* 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_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
|
||||||
#define ROUND_DOWN(N, S) (((N) % (S)) ? ROUND_UP(N, S) - S : N)
|
#define ROUND_DOWN(N, S) (((N) % (S)) ? ROUND_UP(N, S) - S : N)
|
||||||
|
|
||||||
#define TAG_CSEG TAG('C', 'S', 'E', 'G')
|
#define TAG_CSEG TAG('C', 'S', 'E', 'G')
|
||||||
#define TAG_BCB TAG('B', 'C', 'B', ' ')
|
#define TAG_BCB TAG('B', 'C', 'B', ' ')
|
||||||
|
#define TAG_IBCB TAG('i', 'B', 'C', 'B')
|
||||||
|
|
||||||
static LIST_ENTRY DirtySegmentListHead;
|
static LIST_ENTRY DirtySegmentListHead;
|
||||||
static LIST_ENTRY CacheSegmentListHead;
|
static LIST_ENTRY CacheSegmentListHead;
|
||||||
static LIST_ENTRY CacheSegmentLRUListHead;
|
static LIST_ENTRY CacheSegmentLRUListHead;
|
||||||
|
static LIST_ENTRY ClosedListHead;
|
||||||
|
|
||||||
static FAST_MUTEX ViewLock;
|
static FAST_MUTEX ViewLock;
|
||||||
|
|
||||||
|
#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);
|
void * alloca(size_t size);
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
|
CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
@ -101,6 +130,9 @@ CcRosFlushCacheSegment(PCACHE_SEGMENT CacheSegment)
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID CcRosRemoveUnusedFiles(VOID);
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CcRosFlushDirtyPages(ULONG Target, PULONG Count)
|
CcRosFlushDirtyPages(ULONG Target, PULONG Count)
|
||||||
{
|
{
|
||||||
|
@ -116,6 +148,10 @@ CcRosFlushDirtyPages(ULONG Target, PULONG Count)
|
||||||
|
|
||||||
ExAcquireFastMutex(&ViewLock);
|
ExAcquireFastMutex(&ViewLock);
|
||||||
current_entry = DirtySegmentListHead.Flink;
|
current_entry = DirtySegmentListHead.Flink;
|
||||||
|
if (current_entry == &DirtySegmentListHead)
|
||||||
|
{
|
||||||
|
DPRINT("No Dirty pages\n");
|
||||||
|
}
|
||||||
while (current_entry != &DirtySegmentListHead && Target > 0)
|
while (current_entry != &DirtySegmentListHead && Target > 0)
|
||||||
{
|
{
|
||||||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
||||||
|
@ -149,7 +185,8 @@ CcRosFlushDirtyPages(ULONG Target, PULONG Count)
|
||||||
current_entry = DirtySegmentListHead.Flink;
|
current_entry = DirtySegmentListHead.Flink;
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&ViewLock);
|
ExReleaseFastMutex(&ViewLock);
|
||||||
DPRINT("CcRosTrimCache() finished\n");
|
DPRINT("CcRosFlushDirtyPages() finished\n");
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +254,7 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
CcRosReleaseCacheSegment(PBCB Bcb,
|
CcRosReleaseCacheSegment(PBCB Bcb,
|
||||||
PCACHE_SEGMENT CacheSeg,
|
PCACHE_SEGMENT CacheSeg,
|
||||||
BOOLEAN Valid,
|
BOOLEAN Valid,
|
||||||
|
@ -264,7 +301,8 @@ CcRosReleaseCacheSegment(PBCB Bcb,
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
PCACHE_SEGMENT CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset)
|
PCACHE_SEGMENT
|
||||||
|
CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY current_entry;
|
PLIST_ENTRY current_entry;
|
||||||
PCACHE_SEGMENT current;
|
PCACHE_SEGMENT current;
|
||||||
|
@ -387,13 +425,15 @@ CcRosCreateCacheSegment(PBCB Bcb,
|
||||||
PLIST_ENTRY current_entry;
|
PLIST_ENTRY current_entry;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
|
#ifdef CACHE_BITMAP
|
||||||
|
ULONG StartingOffset;
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(Bcb);
|
assert(Bcb);
|
||||||
|
|
||||||
DPRINT("CcRosCreateCacheSegment()\n");
|
DPRINT("CcRosCreateCacheSegment()\n");
|
||||||
|
|
||||||
current = ExAllocatePoolWithTag(NonPagedPool, sizeof(CACHE_SEGMENT),
|
current = ExAllocateFromNPagedLookasideList(&CacheSegLookasideList);
|
||||||
TAG_CSEG);
|
|
||||||
current->Valid = FALSE;
|
current->Valid = FALSE;
|
||||||
current->Dirty = FALSE;
|
current->Dirty = FALSE;
|
||||||
current->FileOffset = ROUND_DOWN(FileOffset, Bcb->CacheSegmentSize);
|
current->FileOffset = ROUND_DOWN(FileOffset, Bcb->CacheSegmentSize);
|
||||||
|
@ -425,7 +465,7 @@ CcRosCreateCacheSegment(PBCB Bcb,
|
||||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||||
ExReleaseFastMutex(&(*CacheSeg)->Lock);
|
ExReleaseFastMutex(&(*CacheSeg)->Lock);
|
||||||
ExReleaseFastMutex(&ViewLock);
|
ExReleaseFastMutex(&ViewLock);
|
||||||
ExFreePool(*CacheSeg);
|
ExFreeToNPagedLookasideList(&CacheSegLookasideList, *CacheSeg);
|
||||||
*CacheSeg = current;
|
*CacheSeg = current;
|
||||||
if (Lock)
|
if (Lock)
|
||||||
{
|
{
|
||||||
|
@ -442,7 +482,26 @@ CcRosCreateCacheSegment(PBCB Bcb,
|
||||||
InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry);
|
InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry);
|
||||||
InsertTailList(&CacheSegmentLRUListHead, ¤t->CacheSegmentLRUListEntry);
|
InsertTailList(&CacheSegmentLRUListHead, ¤t->CacheSegmentLRUListEntry);
|
||||||
ExReleaseFastMutex(&ViewLock);
|
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());
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||||
current->BaseAddress = NULL;
|
current->BaseAddress = NULL;
|
||||||
Status = MmCreateMemoryArea(NULL,
|
Status = MmCreateMemoryArea(NULL,
|
||||||
|
@ -458,6 +517,7 @@ CcRosCreateCacheSegment(PBCB Bcb,
|
||||||
{
|
{
|
||||||
KeBugCheck(0);
|
KeBugCheck(0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++)
|
for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++)
|
||||||
{
|
{
|
||||||
PHYSICAL_ADDRESS Page;
|
PHYSICAL_ADDRESS Page;
|
||||||
|
@ -612,7 +672,8 @@ CcRosRequestCacheSegment(PBCB Bcb,
|
||||||
UptoDate,
|
UptoDate,
|
||||||
CacheSeg));
|
CacheSeg));
|
||||||
}
|
}
|
||||||
|
#ifdef CACHE_BITMAP
|
||||||
|
#else
|
||||||
STATIC VOID
|
STATIC VOID
|
||||||
CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||||
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, BOOLEAN Dirty)
|
PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, BOOLEAN Dirty)
|
||||||
|
@ -623,16 +684,45 @@ CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||||
MmReleasePageMemoryConsumer(MC_CACHE, PhysAddr);
|
MmReleasePageMemoryConsumer(MC_CACHE, PhysAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg)
|
CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Releases a cache segment associated with a BCB
|
* 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);
|
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());
|
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||||
MmFreeMemoryArea(MmGetKernelAddressSpace(),
|
MmFreeMemoryArea(MmGetKernelAddressSpace(),
|
||||||
CacheSeg->BaseAddress,
|
CacheSeg->BaseAddress,
|
||||||
|
@ -640,11 +730,12 @@ CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg)
|
||||||
CcFreeCachePage,
|
CcFreeCachePage,
|
||||||
NULL);
|
NULL);
|
||||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||||
ExFreePool(CacheSeg);
|
#endif
|
||||||
|
ExFreeToNPagedLookasideList(&CacheSegLookasideList, CacheSeg);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
CcRosFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg)
|
CcRosFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -720,8 +811,8 @@ CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
|
||||||
IoStatus->Status = Status;
|
IoStatus->Status = Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(¤t->Lock);
|
|
||||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||||
|
ExReleaseFastMutex(¤t->Lock);
|
||||||
current->ReferenceCount--;
|
current->ReferenceCount--;
|
||||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||||
}
|
}
|
||||||
|
@ -746,7 +837,7 @@ CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
|
CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Releases the BCB associated with a file object
|
* FUNCTION: Releases the BCB associated with a file object
|
||||||
|
@ -757,28 +848,30 @@ CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
LIST_ENTRY FreeList;
|
LIST_ENTRY FreeList;
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
|
|
||||||
assert(Bcb);
|
assert(Bcb);
|
||||||
|
|
||||||
DPRINT("CcRosDeleteFileCache(FileObject %x, Bcb %x)\n",
|
Bcb->RefCount++;
|
||||||
Bcb->FileObject, Bcb);
|
|
||||||
|
|
||||||
ExReleaseFastMutex(&ViewLock);
|
ExReleaseFastMutex(&ViewLock);
|
||||||
|
|
||||||
CcFlushCache(FileObject->SectionObjectPointers, NULL, 0, NULL);
|
CcFlushCache(FileObject->SectionObjectPointers, NULL, 0, NULL);
|
||||||
|
|
||||||
ExAcquireFastMutex(&ViewLock);
|
ExAcquireFastMutex(&ViewLock);
|
||||||
|
Bcb->RefCount--;
|
||||||
if (Bcb->RefCount == 0)
|
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.
|
* Release all cache segments.
|
||||||
*/
|
*/
|
||||||
InitializeListHead(&FreeList);
|
InitializeListHead(&FreeList);
|
||||||
|
|
||||||
FileObject->SectionObjectPointers->SharedCacheMap = NULL;
|
|
||||||
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
|
||||||
current_entry = Bcb->BcbSegmentListHead.Flink;
|
current_entry = Bcb->BcbSegmentListHead.Flink;
|
||||||
while (!IsListEmpty(&Bcb->BcbSegmentListHead))
|
while (!IsListEmpty(&Bcb->BcbSegmentListHead))
|
||||||
|
@ -790,20 +883,23 @@ CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
|
||||||
if (current->Dirty)
|
if (current->Dirty)
|
||||||
{
|
{
|
||||||
RemoveEntryList(¤t->DirtySegmentListEntry);
|
RemoveEntryList(¤t->DirtySegmentListEntry);
|
||||||
|
DPRINT1("Freeing dirty segment\n");
|
||||||
}
|
}
|
||||||
InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry);
|
InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry);
|
||||||
|
|
||||||
}
|
}
|
||||||
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
|
||||||
|
|
||||||
|
ExReleaseFastMutex(&ViewLock);
|
||||||
|
ObDereferenceObject (Bcb->FileObject);
|
||||||
|
|
||||||
while (!IsListEmpty(&FreeList))
|
while (!IsListEmpty(&FreeList))
|
||||||
{
|
{
|
||||||
current_entry = RemoveTailList(&FreeList);
|
current_entry = RemoveTailList(&FreeList);
|
||||||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
|
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
|
||||||
Status = CcRosInternalFreeCacheSegment(current);
|
Status = CcRosInternalFreeCacheSegment(current);
|
||||||
}
|
}
|
||||||
|
ExFreeToNPagedLookasideList(&BcbLookasideList, Bcb);
|
||||||
ObDereferenceObject (Bcb->FileObject);
|
ExAcquireFastMutex(&ViewLock);
|
||||||
ExFreePool(Bcb);
|
|
||||||
}
|
}
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -818,16 +914,46 @@ VOID CcRosReferenceCache(PFILE_OBJECT FileObject)
|
||||||
ExReleaseFastMutex(&ViewLock);
|
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)
|
VOID CcRosDereferenceCache(PFILE_OBJECT FileObject)
|
||||||
{
|
{
|
||||||
PBCB Bcb;
|
PBCB Bcb;
|
||||||
ExAcquireFastMutex(&ViewLock);
|
ExAcquireFastMutex(&ViewLock);
|
||||||
Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
|
Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap;
|
||||||
assert(Bcb);
|
assert(Bcb);
|
||||||
Bcb->RefCount--;
|
if (Bcb->RefCount > 0)
|
||||||
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);
|
ExReleaseFastMutex(&ViewLock);
|
||||||
}
|
}
|
||||||
|
@ -848,11 +974,22 @@ CcRosReleaseFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
|
||||||
if (FileObject->PrivateCacheMap != NULL)
|
if (FileObject->PrivateCacheMap != NULL)
|
||||||
{
|
{
|
||||||
FileObject->PrivateCacheMap = NULL;
|
FileObject->PrivateCacheMap = NULL;
|
||||||
Bcb->RefCount--;
|
if (Bcb->RefCount > 0)
|
||||||
}
|
{
|
||||||
if (Bcb->RefCount == 0)
|
Bcb->RefCount--;
|
||||||
{
|
if (Bcb->RefCount == 0)
|
||||||
CcRosDeleteFileCache(FileObject, Bcb);
|
{
|
||||||
|
if (Bcb->RemoveOnClose)
|
||||||
|
{
|
||||||
|
CcRosDeleteFileCache(FileObject, Bcb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Bcb->TimeStamp = CcTimeStamp;
|
||||||
|
InsertHeadList(&ClosedListHead, &Bcb->BcbRemoveListEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&ViewLock);
|
ExReleaseFastMutex(&ViewLock);
|
||||||
|
@ -874,12 +1011,13 @@ CcRosInitializeFileCache(PFILE_OBJECT FileObject,
|
||||||
|
|
||||||
if (*Bcb == NULL)
|
if (*Bcb == NULL)
|
||||||
{
|
{
|
||||||
(*Bcb) = ExAllocatePoolWithTag(NonPagedPool, sizeof(BCB), TAG_BCB);
|
(*Bcb) = ExAllocateFromNPagedLookasideList(&BcbLookasideList);
|
||||||
if ((*Bcb) == NULL)
|
if ((*Bcb) == NULL)
|
||||||
{
|
{
|
||||||
|
ExReleaseFastMutex(&ViewLock);
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return(STATUS_UNSUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
memset((*Bcb), 0, sizeof(BCB));
|
||||||
ObReferenceObjectByPointer(FileObject,
|
ObReferenceObjectByPointer(FileObject,
|
||||||
FILE_ALL_ACCESS,
|
FILE_ALL_ACCESS,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -902,6 +1040,11 @@ CcRosInitializeFileCache(PFILE_OBJECT FileObject,
|
||||||
FileObject->PrivateCacheMap = *Bcb;
|
FileObject->PrivateCacheMap = *Bcb;
|
||||||
(*Bcb)->RefCount++;
|
(*Bcb)->RefCount++;
|
||||||
}
|
}
|
||||||
|
if ((*Bcb)->BcbRemoveListEntry.Flink != NULL)
|
||||||
|
{
|
||||||
|
RemoveEntryList(&(*Bcb)->BcbRemoveListEntry);
|
||||||
|
(*Bcb)->BcbRemoveListEntry.Flink = NULL;
|
||||||
|
}
|
||||||
ExReleaseFastMutex(&ViewLock);
|
ExReleaseFastMutex(&ViewLock);
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
|
@ -920,16 +1063,148 @@ CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
VOID
|
||||||
CcInitView(VOID)
|
CcInitView(VOID)
|
||||||
{
|
{
|
||||||
|
#ifdef CACHE_BITMAP
|
||||||
|
PMEMORY_AREA marea;
|
||||||
|
PVOID Buffer;
|
||||||
|
#endif
|
||||||
|
NTSTATUS Status;
|
||||||
|
KPRIORITY Priority;
|
||||||
|
|
||||||
DPRINT("CcInitView()\n");
|
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(&CacheSegmentListHead);
|
||||||
InitializeListHead(&DirtySegmentListHead);
|
InitializeListHead(&DirtySegmentListHead);
|
||||||
InitializeListHead(&CacheSegmentLRUListHead);
|
InitializeListHead(&CacheSegmentLRUListHead);
|
||||||
|
InitializeListHead(&ClosedListHead);
|
||||||
ExInitializeFastMutex(&ViewLock);
|
ExInitializeFastMutex(&ViewLock);
|
||||||
|
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);
|
MmInitializeMemoryConsumer(MC_CACHE, CcRosTrimCache);
|
||||||
|
|
||||||
CcInitCacheZeroPage();
|
CcInitCacheZeroPage();
|
||||||
|
|
||||||
|
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 */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue