mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
[NTOSKRNL]
- Optimize CcRosTrimCache by eliminating an extra loop of all segments - Allow swapping of dirty segments by flushing them first svn path=/trunk/; revision=54549
This commit is contained in:
parent
246357c187
commit
f9794fddef
1 changed files with 57 additions and 54 deletions
|
@ -302,79 +302,80 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
|
||||||
ULONG PagesFreed;
|
ULONG PagesFreed;
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
LIST_ENTRY FreeList;
|
LIST_ENTRY FreeList;
|
||||||
|
PFN_NUMBER Page;
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
DPRINT("CcRosTrimCache(Target %d)\n", Target);
|
DPRINT("CcRosTrimCache(Target %d)\n", Target);
|
||||||
|
|
||||||
*NrFreed = 0;
|
|
||||||
|
|
||||||
InitializeListHead(&FreeList);
|
InitializeListHead(&FreeList);
|
||||||
|
|
||||||
KeAcquireGuardedMutex(&ViewLock);
|
/* Flush dirty pages to disk */
|
||||||
current_entry = CacheSegmentLRUListHead.Flink;
|
CcRosFlushDirtyPages(Target, NrFreed);
|
||||||
while (current_entry != &CacheSegmentLRUListHead && Target > 0)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
ULONG i;
|
|
||||||
|
|
||||||
CcRosCacheSegmentIncRefCount(current);
|
|
||||||
current->PageOut = TRUE;
|
|
||||||
KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql);
|
|
||||||
KeReleaseGuardedMutex(&ViewLock);
|
|
||||||
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);
|
|
||||||
MmPageOutPhysicalAddress(Page);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if ((*NrFreed) != 0) DPRINT1("Flushed %d dirty cache pages to disk\n", (*NrFreed));
|
||||||
|
|
||||||
|
*NrFreed = 0;
|
||||||
|
|
||||||
|
KeAcquireGuardedMutex(&ViewLock);
|
||||||
|
|
||||||
current_entry = CacheSegmentLRUListHead.Flink;
|
current_entry = CacheSegmentLRUListHead.Flink;
|
||||||
while (current_entry != &CacheSegmentLRUListHead)
|
while (current_entry != &CacheSegmentLRUListHead)
|
||||||
{
|
{
|
||||||
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
|
||||||
CacheSegmentLRUListEntry);
|
CacheSegmentLRUListEntry);
|
||||||
current->PageOut = FALSE;
|
|
||||||
current_entry = current_entry->Flink;
|
current_entry = current_entry->Flink;
|
||||||
|
|
||||||
KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql);
|
KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql);
|
||||||
|
|
||||||
|
/* Reference the cache segment */
|
||||||
|
CcRosCacheSegmentIncRefCount(current);
|
||||||
|
|
||||||
|
/* Check if it's mapped and not dirty */
|
||||||
|
if (current->MappedCount > 0 && !current->Dirty)
|
||||||
|
{
|
||||||
|
/* 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++)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dereference the cache segment */
|
||||||
|
CcRosCacheSegmentDecRefCount(current);
|
||||||
|
|
||||||
|
/* Check if we can free this entry now */
|
||||||
if (current->ReferenceCount == 0)
|
if (current->ReferenceCount == 0)
|
||||||
{
|
{
|
||||||
|
ASSERT(!current->Dirty);
|
||||||
|
ASSERT(!current->MappedCount);
|
||||||
|
|
||||||
RemoveEntryList(¤t->BcbSegmentListEntry);
|
RemoveEntryList(¤t->BcbSegmentListEntry);
|
||||||
KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql);
|
|
||||||
RemoveEntryList(¤t->CacheSegmentListEntry);
|
RemoveEntryList(¤t->CacheSegmentListEntry);
|
||||||
RemoveEntryList(¤t->CacheSegmentLRUListEntry);
|
RemoveEntryList(¤t->CacheSegmentLRUListEntry);
|
||||||
InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry);
|
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);
|
KeReleaseGuardedMutex(&ViewLock);
|
||||||
|
|
||||||
while (!IsListEmpty(&FreeList))
|
while (!IsListEmpty(&FreeList))
|
||||||
{
|
{
|
||||||
current_entry = RemoveHeadList(&FreeList);
|
current_entry = RemoveHeadList(&FreeList);
|
||||||
|
@ -382,7 +383,9 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
|
||||||
BcbSegmentListEntry);
|
BcbSegmentListEntry);
|
||||||
CcRosInternalFreeCacheSegment(current);
|
CcRosInternalFreeCacheSegment(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINT1("Evicted %d cache pages\n", (*NrFreed));
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue