Author: cgutman Date: Wed Nov 30 17:10:43 2011 New Revision: 54549
URL: http://svn.reactos.org/svn/reactos?rev=54549&view=rev Log: [NTOSKRNL] - Optimize CcRosTrimCache by eliminating an extra loop of all segments - Allow swapping of dirty segments by flushing them first
Modified: trunk/reactos/ntoskrnl/cc/view.c
Modified: trunk/reactos/ntoskrnl/cc/view.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cc/view.c?rev=5454... ============================================================================== --- trunk/reactos/ntoskrnl/cc/view.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/cc/view.c [iso-8859-1] Wed Nov 30 17:10:43 2011 @@ -302,79 +302,80 @@ ULONG PagesFreed; KIRQL oldIrql; LIST_ENTRY FreeList; - + PFN_NUMBER Page; + ULONG i; + DPRINT("CcRosTrimCache(Target %d)\n", Target); - + + InitializeListHead(&FreeList); + + /* Flush dirty pages to disk */ + CcRosFlushDirtyPages(Target, NrFreed); + + if ((*NrFreed) != 0) DPRINT1("Flushed %d dirty cache pages to disk\n", (*NrFreed)); + *NrFreed = 0; - - InitializeListHead(&FreeList);
KeAcquireGuardedMutex(&ViewLock); + current_entry = CacheSegmentLRUListHead.Flink; - while (current_entry != &CacheSegmentLRUListHead && Target > 0) + while (current_entry != &CacheSegmentLRUListHead) { current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, CacheSegmentLRUListEntry); current_entry = current_entry->Flink; - + KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql);
- if (current->MappedCount > 0 && !current->Dirty && !current->PageOut) + /* Reference the cache segment */ + CcRosCacheSegmentIncRefCount(current); + + /* Check if it's mapped and not dirty */ + if (current->MappedCount > 0 && !current->Dirty) { - ULONG i; - - CcRosCacheSegmentIncRefCount(current); - current->PageOut = TRUE; + /* We have to break these locks because Cc sucks */ KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql); KeReleaseGuardedMutex(&ViewLock); + + /* Page out the segment */ for (i = 0; i < current->Bcb->CacheSegmentSize / PAGE_SIZE; i++) { - PFN_NUMBER Page; - Page = (PFN_NUMBER)(MmGetPhysicalAddress((char*)current->BaseAddress + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT); + Page = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)current->BaseAddress + (i * PAGE_SIZE)).QuadPart >> PAGE_SHIFT); + MmPageOutPhysicalAddress(Page); } + + /* Reacquire the locks */ KeAcquireGuardedMutex(&ViewLock); KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql); - CcRosCacheSegmentDecRefCount(current); } - + + /* Dereference the cache segment */ + CcRosCacheSegmentDecRefCount(current); + + /* Check if we can free this entry now */ if (current->ReferenceCount == 0) { - PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE; - // PagesFreed = PagesPerSegment; - PagesFreed = min(PagesPerSegment, Target); - Target -= PagesFreed; - (*NrFreed) += PagesFreed; - } - - KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql); - } - - current_entry = CacheSegmentLRUListHead.Flink; - while (current_entry != &CacheSegmentLRUListHead) - { - current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, - CacheSegmentLRUListEntry); - current->PageOut = FALSE; - current_entry = current_entry->Flink; - - KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql); - if (current->ReferenceCount == 0) - { + ASSERT(!current->Dirty); + ASSERT(!current->MappedCount); + RemoveEntryList(¤t->BcbSegmentListEntry); - KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql); RemoveEntryList(¤t->CacheSegmentListEntry); RemoveEntryList(¤t->CacheSegmentLRUListEntry); InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry); + + /* Calculate how many pages we freed for Mm */ + PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE; + PagesFreed = min(PagesPerSegment, Target); + Target -= PagesFreed; + (*NrFreed) += PagesFreed; } - else - { - KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql); - } - } - + + KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql); + } + KeReleaseGuardedMutex(&ViewLock); - + while (!IsListEmpty(&FreeList)) { current_entry = RemoveHeadList(&FreeList); @@ -382,7 +383,9 @@ BcbSegmentListEntry); CcRosInternalFreeCacheSegment(current); } - + + DPRINT1("Evicted %d cache pages\n", (*NrFreed)); + return(STATUS_SUCCESS); }