mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 09:21:31 +00:00
NTOS:CC Free some VACBs when we're under memory pressure
This commit is contained in:
parent
470ad18825
commit
69daff72d2
|
@ -130,6 +130,16 @@ CcWriteBehind(VOID)
|
||||||
++CcLazyWriteIos;
|
++CcLazyWriteIos;
|
||||||
DPRINT("Lazy writer done (%d)\n", Count);
|
DPRINT("Lazy writer done (%d)\n", Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure we're not throttling writes after this */
|
||||||
|
while (MmAvailablePages < MmThrottleTop)
|
||||||
|
{
|
||||||
|
/* Break if we can't even find one to free */
|
||||||
|
if (!CcRosFreeOneUnusedVacb())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -595,34 +595,26 @@ CcRosUnmarkDirtyVacb (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
CcRosFreeUnusedVacb (
|
CcRosFreeOneUnusedVacb(
|
||||||
PULONG Count)
|
VOID)
|
||||||
{
|
{
|
||||||
ULONG cFreed;
|
|
||||||
BOOLEAN Freed;
|
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
PROS_VACB current;
|
|
||||||
LIST_ENTRY FreeList;
|
|
||||||
PLIST_ENTRY current_entry;
|
PLIST_ENTRY current_entry;
|
||||||
|
PROS_VACB to_free = NULL;
|
||||||
cFreed = 0;
|
|
||||||
Freed = FALSE;
|
|
||||||
InitializeListHead(&FreeList);
|
|
||||||
|
|
||||||
oldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
oldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
|
||||||
|
|
||||||
/* Browse all the available VACB */
|
/* Browse all the available VACB */
|
||||||
current_entry = VacbLruListHead.Flink;
|
current_entry = VacbLruListHead.Flink;
|
||||||
while (current_entry != &VacbLruListHead)
|
while ((current_entry != &VacbLruListHead) && (to_free == NULL))
|
||||||
{
|
{
|
||||||
ULONG Refs;
|
ULONG Refs;
|
||||||
|
PROS_VACB current;
|
||||||
|
|
||||||
current = CONTAINING_RECORD(current_entry,
|
current = CONTAINING_RECORD(current_entry,
|
||||||
ROS_VACB,
|
ROS_VACB,
|
||||||
VacbLruListEntry);
|
VacbLruListEntry);
|
||||||
current_entry = current_entry->Flink;
|
|
||||||
|
|
||||||
KeAcquireSpinLockAtDpcLevel(¤t->SharedCacheMap->CacheMapLock);
|
KeAcquireSpinLockAtDpcLevel(¤t->SharedCacheMap->CacheMapLock);
|
||||||
|
|
||||||
|
@ -634,47 +626,32 @@ CcRosFreeUnusedVacb (
|
||||||
ASSERT(!current->MappedCount);
|
ASSERT(!current->MappedCount);
|
||||||
ASSERT(Refs == 1);
|
ASSERT(Refs == 1);
|
||||||
|
|
||||||
/* Reset and move to free list */
|
/* Reset it, this is the one we want to free */
|
||||||
RemoveEntryList(¤t->CacheMapVacbListEntry);
|
RemoveEntryList(¤t->CacheMapVacbListEntry);
|
||||||
|
InitializeListHead(¤t->CacheMapVacbListEntry);
|
||||||
RemoveEntryList(¤t->VacbLruListEntry);
|
RemoveEntryList(¤t->VacbLruListEntry);
|
||||||
InitializeListHead(¤t->VacbLruListEntry);
|
InitializeListHead(¤t->VacbLruListEntry);
|
||||||
InsertHeadList(&FreeList, ¤t->CacheMapVacbListEntry);
|
|
||||||
|
to_free = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeReleaseSpinLockFromDpcLevel(¤t->SharedCacheMap->CacheMapLock);
|
KeReleaseSpinLockFromDpcLevel(¤t->SharedCacheMap->CacheMapLock);
|
||||||
|
|
||||||
|
current_entry = current_entry->Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeReleaseQueuedSpinLock(LockQueueMasterLock, oldIrql);
|
KeReleaseQueuedSpinLock(LockQueueMasterLock, oldIrql);
|
||||||
|
|
||||||
/* And now, free any of the found VACB, that'll free memory! */
|
/* And now, free the VACB that we found, if any. */
|
||||||
while (!IsListEmpty(&FreeList))
|
if (to_free == NULL)
|
||||||
{
|
{
|
||||||
ULONG Refs;
|
return FALSE;
|
||||||
|
|
||||||
current_entry = RemoveHeadList(&FreeList);
|
|
||||||
current = CONTAINING_RECORD(current_entry,
|
|
||||||
ROS_VACB,
|
|
||||||
CacheMapVacbListEntry);
|
|
||||||
InitializeListHead(¤t->CacheMapVacbListEntry);
|
|
||||||
Refs = CcRosVacbDecRefCount(current);
|
|
||||||
ASSERT(Refs == 0);
|
|
||||||
++cFreed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we freed at least one VACB, return success */
|
/* This must be its last ref */
|
||||||
if (cFreed != 0)
|
NT_VERIFY(CcRosVacbDecRefCount(to_free) == 0);
|
||||||
{
|
|
||||||
Freed = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If caller asked for free count, return it */
|
return TRUE;
|
||||||
if (Count != NULL)
|
|
||||||
{
|
|
||||||
*Count = cFreed;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Freed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -690,7 +667,6 @@ CcRosCreateVacb (
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
ULONG Refs;
|
ULONG Refs;
|
||||||
BOOLEAN Retried;
|
|
||||||
SIZE_T ViewSize = VACB_MAPPING_GRANULARITY;
|
SIZE_T ViewSize = VACB_MAPPING_GRANULARITY;
|
||||||
|
|
||||||
ASSERT(SharedCacheMap);
|
ASSERT(SharedCacheMap);
|
||||||
|
@ -711,28 +687,24 @@ CcRosCreateVacb (
|
||||||
|
|
||||||
CcRosVacbIncRefCount(current);
|
CcRosVacbIncRefCount(current);
|
||||||
|
|
||||||
Retried = FALSE;
|
while (TRUE)
|
||||||
Retry:
|
|
||||||
/* Map VACB in system space */
|
|
||||||
Status = MmMapViewInSystemSpaceEx(SharedCacheMap->Section, ¤t->BaseAddress, &ViewSize, ¤t->FileOffset, 0);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
ULONG Freed;
|
/* Map VACB in system space */
|
||||||
/* If no space left, try to prune unused VACB
|
Status = MmMapViewInSystemSpaceEx(SharedCacheMap->Section, ¤t->BaseAddress, &ViewSize, ¤t->FileOffset, 0);
|
||||||
* to recover space to map our VACB
|
if (NT_SUCCESS(Status))
|
||||||
* If it succeed, retry to map, otherwise
|
|
||||||
* just fail.
|
|
||||||
*/
|
|
||||||
if (!Retried && CcRosFreeUnusedVacb(&Freed))
|
|
||||||
{
|
{
|
||||||
DPRINT("Prunned %d VACB, trying again\n", Freed);
|
break;
|
||||||
Retried = TRUE;
|
|
||||||
goto Retry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExFreeToNPagedLookasideList(&VacbLookasideList, current);
|
/*
|
||||||
return Status;
|
* If no space left, try to prune one unused VACB to recover space to map our VACB.
|
||||||
|
* If it succeeds, retry to map, otherwise just fail.
|
||||||
|
*/
|
||||||
|
if (!CcRosFreeOneUnusedVacb())
|
||||||
|
{
|
||||||
|
ExFreeToNPagedLookasideList(&VacbLookasideList, current);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DBG
|
#if DBG
|
||||||
|
|
|
@ -509,3 +509,7 @@ CcRosVacbDecRefCount(
|
||||||
}
|
}
|
||||||
#define CcRosVacbGetRefCount(vacb) InterlockedCompareExchange((PLONG)&(vacb)->ReferenceCount, 0, 0)
|
#define CcRosVacbGetRefCount(vacb) InterlockedCompareExchange((PLONG)&(vacb)->ReferenceCount, 0, 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
CcRosFreeOneUnusedVacb(
|
||||||
|
VOID);
|
||||||
|
|
Loading…
Reference in a new issue