X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fcc%2Fview.c;h=b8ce087c1b912de5f03ac2a45c8542e99efedf42;hp=e881188071fb8a5f217218a958f4eded42673ebe;hb=f9794fddef6b8aeacc1157a8ab3527a063c6b31d;hpb=246357c187f7e090a95ff20c177e766dea543a43 diff --git a/reactos/ntoskrnl/cc/view.c b/reactos/ntoskrnl/cc/view.c index e881188071f..b8ce087c1b9 100644 --- a/reactos/ntoskrnl/cc/view.c +++ b/reactos/ntoskrnl/cc/view.c @@ -302,79 +302,80 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed) 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); - } - - 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); + + /* Dereference the cache segment */ + CcRosCacheSegmentDecRefCount(current); + + /* Check if we can free this entry now */ 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 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed) BcbSegmentListEntry); CcRosInternalFreeCacheSegment(current); } - + + DPRINT1("Evicted %d cache pages\n", (*NrFreed)); + return(STATUS_SUCCESS); }