- Fix for Bug 703.

- ReactOS can now be installed on systems with as little as 24MB. Memory usage after boot is down by 20-30MB. Application installations will use/require/leak less memory.
- Patch by Alex Ionescu.
See issue #703 for more details.

svn path=/trunk/; revision=39663
This commit is contained in:
Aleksey Bragin 2009-02-18 16:56:42 +00:00
parent cac6a6eb40
commit a4718924aa
3 changed files with 101 additions and 180 deletions

View file

@ -70,11 +70,6 @@ NPAGED_LOOKASIDE_LIST iBcbLookasideList;
static NPAGED_LOOKASIDE_LIST BcbLookasideList; static NPAGED_LOOKASIDE_LIST BcbLookasideList;
static NPAGED_LOOKASIDE_LIST CacheSegLookasideList; static NPAGED_LOOKASIDE_LIST CacheSegLookasideList;
static ULONG CcTimeStamp;
static KEVENT LazyCloseThreadEvent;
static HANDLE LazyCloseThreadHandle;
static CLIENT_ID LazyCloseThreadId;
static volatile BOOLEAN LazyCloseThreadShouldTerminate;
#if defined(__GNUC__) #if defined(__GNUC__)
/* void * alloca(size_t size); */ /* void * alloca(size_t size); */
@ -308,85 +303,97 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
* actually freed is returned. * actually freed is returned.
*/ */
{ {
PLIST_ENTRY current_entry; PLIST_ENTRY current_entry;
PCACHE_SEGMENT current, last = NULL; PCACHE_SEGMENT current;
ULONG PagesPerSegment; ULONG PagesPerSegment;
ULONG PagesFreed; ULONG PagesFreed;
KIRQL oldIrql; KIRQL oldIrql;
LIST_ENTRY FreeList; LIST_ENTRY FreeList;
DPRINT("CcRosTrimCache(Target %d)\n", Target); DPRINT("CcRosTrimCache(Target %d)\n", Target);
*NrFreed = 0; *NrFreed = 0;
InitializeListHead(&FreeList); InitializeListHead(&FreeList);
KeAcquireGuardedMutex(&ViewLock); KeAcquireGuardedMutex(&ViewLock);
current_entry = CacheSegmentLRUListHead.Flink; current_entry = CacheSegmentLRUListHead.Flink;
while (current_entry != &CacheSegmentLRUListHead && Target > 0) while (current_entry != &CacheSegmentLRUListHead && Target > 0)
{ {
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, NTSTATUS Status;
CacheSegmentLRUListEntry);
current_entry = current_entry->Flink;
KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql); Status = STATUS_SUCCESS;
if (current->ReferenceCount == 0) current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
{ CacheSegmentLRUListEntry);
RemoveEntryList(&current->BcbSegmentListEntry); current_entry = current_entry->Flink;
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
RemoveEntryList(&current->CacheSegmentListEntry);
RemoveEntryList(&current->CacheSegmentLRUListEntry);
InsertHeadList(&FreeList, &current->BcbSegmentListEntry);
PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
PagesFreed = min(PagesPerSegment, Target);
Target -= PagesFreed;
(*NrFreed) += PagesFreed;
}
else
{
if (last != current && current->MappedCount > 0 && !current->Dirty && !current->PageOut)
{
ULONG i;
NTSTATUS Status;
CcRosCacheSegmentIncRefCount(current); KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
last = current;
current->PageOut = TRUE;
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
KeReleaseGuardedMutex(&ViewLock);
for (i = 0; i < current->Bcb->CacheSegmentSize / PAGE_SIZE; i++)
{
PFN_TYPE Page;
Page = (PFN_TYPE)(MmGetPhysicalAddress((char*)current->BaseAddress + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT);
Status = MmPageOutPhysicalAddress(Page);
if (!NT_SUCCESS(Status))
{
break;
}
}
KeAcquireGuardedMutex(&ViewLock);
KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
CcRosCacheSegmentDecRefCount(current);
current->PageOut = FALSE;
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
current_entry = &current->CacheSegmentLRUListEntry;
continue;
}
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
}
}
KeReleaseGuardedMutex(&ViewLock);
while (!IsListEmpty(&FreeList)) if (current->MappedCount > 0 && !current->Dirty && !current->PageOut)
{ {
current_entry = RemoveHeadList(&FreeList); ULONG i;
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
BcbSegmentListEntry);
CcRosInternalFreeCacheSegment(current);
}
DPRINT("CcRosTrimCache() finished\n"); CcRosCacheSegmentIncRefCount(current);
return(STATUS_SUCCESS); current->PageOut = TRUE;
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
KeReleaseGuardedMutex(&ViewLock);
for (i = 0; i < current->Bcb->CacheSegmentSize / PAGE_SIZE; i++)
{
PFN_TYPE Page;
Page = (PFN_TYPE)(MmGetPhysicalAddress((char*)current->BaseAddress + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT);
Status = MmPageOutPhysicalAddress(Page);
}
KeAcquireGuardedMutex(&ViewLock);
KeAcquireSpinLock(&current->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(&current->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(&current->Bcb->BcbLock, &oldIrql);
if (current->ReferenceCount == 0)
{
RemoveEntryList(&current->BcbSegmentListEntry);
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
RemoveEntryList(&current->CacheSegmentListEntry);
RemoveEntryList(&current->CacheSegmentLRUListEntry);
InsertHeadList(&FreeList, &current->BcbSegmentListEntry);
}
else
{
KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
}
}
KeReleaseGuardedMutex(&ViewLock);
while (!IsListEmpty(&FreeList))
{
current_entry = RemoveHeadList(&FreeList);
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
BcbSegmentListEntry);
CcRosInternalFreeCacheSegment(current);
}
return(STATUS_SUCCESS);
} }
NTSTATUS NTSTATUS
@ -1151,15 +1158,7 @@ CcRosDereferenceCache(PFILE_OBJECT FileObject)
if (Bcb->RefCount == 0) if (Bcb->RefCount == 0)
{ {
MmFreeSectionSegments(Bcb->FileObject); MmFreeSectionSegments(Bcb->FileObject);
if (Bcb->RemoveOnClose)
{
CcRosDeleteFileCache(FileObject, Bcb); CcRosDeleteFileCache(FileObject, Bcb);
}
else
{
Bcb->TimeStamp = CcTimeStamp;
InsertHeadList(&ClosedListHead, &Bcb->BcbRemoveListEntry);
}
} }
} }
KeReleaseGuardedMutex(&ViewLock); KeReleaseGuardedMutex(&ViewLock);
@ -1188,15 +1187,7 @@ CcRosReleaseFileCache(PFILE_OBJECT FileObject)
if (Bcb->RefCount == 0) if (Bcb->RefCount == 0)
{ {
MmFreeSectionSegments(Bcb->FileObject); MmFreeSectionSegments(Bcb->FileObject);
if (Bcb->RemoveOnClose)
{
CcRosDeleteFileCache(FileObject, Bcb); CcRosDeleteFileCache(FileObject, Bcb);
}
else
{
Bcb->TimeStamp = CcTimeStamp;
InsertHeadList(&ClosedListHead, &Bcb->BcbRemoveListEntry);
}
} }
} }
} }
@ -1315,60 +1306,6 @@ CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers
return NULL; return NULL;
} }
VOID NTAPI
CmLazyCloseThreadMain(PVOID Ignored)
{
LARGE_INTEGER Timeout;
PLIST_ENTRY current_entry;
PBCB current;
ULONG RemoveTimeStamp;
NTSTATUS Status;
KeQuerySystemTime (&Timeout);
while (1)
{
Timeout.QuadPart += (LONGLONG)100000000; // 10sec
Status = KeWaitForSingleObject(&LazyCloseThreadEvent,
0,
KernelMode,
FALSE,
&Timeout);
DPRINT("LazyCloseThreadMain %d\n", CcTimeStamp);
if (!NT_SUCCESS(Status))
{
DbgPrint("LazyCloseThread: Wait failed\n");
KeBugCheck(CACHE_MANAGER);
break;
}
if (LazyCloseThreadShouldTerminate)
{
DbgPrint("LazyCloseThread: Terminating\n");
break;
}
KeAcquireGuardedMutex(&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);
}
}
KeReleaseGuardedMutex(&ViewLock);
}
}
VOID VOID
INIT_FUNCTION INIT_FUNCTION
NTAPI NTAPI
@ -1379,8 +1316,6 @@ CcInitView(VOID)
PVOID Buffer; PVOID Buffer;
PHYSICAL_ADDRESS BoundaryAddressMultiple; PHYSICAL_ADDRESS BoundaryAddressMultiple;
#endif #endif
NTSTATUS Status;
KPRIORITY Priority;
DPRINT("CcInitView()\n"); DPRINT("CcInitView()\n");
#ifdef CACHE_BITMAP #ifdef CACHE_BITMAP
@ -1443,25 +1378,6 @@ CcInitView(VOID)
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 */

View file

@ -684,7 +684,7 @@ KdbInitialize(PKD_DISPATCH_TABLE DispatchTable,
ULONG BootPhase) ULONG BootPhase)
{ {
PCHAR p1, p2; PCHAR p1, p2;
SHORT Found; SHORT Found = FALSE;
CHAR YesNo; CHAR YesNo;
LIST_ENTRY *ModuleEntry; LIST_ENTRY *ModuleEntry;
PLDR_DATA_TABLE_ENTRY DataTableEntry; PLDR_DATA_TABLE_ENTRY DataTableEntry;
@ -708,12 +708,6 @@ KdbInitialize(PKD_DISPATCH_TABLE DispatchTable,
InitializeListHead(&SymbolFileListHead); InitializeListHead(&SymbolFileListHead);
KeInitializeSpinLock(&SymbolFileListLock); KeInitializeSpinLock(&SymbolFileListLock);
#ifdef DBG
LoadSymbols = TRUE;
#else
LoadSymbols = FALSE;
#endif
/* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS, /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
* /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */ * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
ASSERT(KeLoaderBlock); ASSERT(KeLoaderBlock);

View file

@ -68,7 +68,18 @@ MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
/* Set up targets. */ /* Set up targets. */
MiMinimumAvailablePages = 64; MiMinimumAvailablePages = 64;
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 2; if ((NrAvailablePages + NrSystemPages) >= 8192)
{
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 4 * 3;
}
else if ((NrAvailablePages + NrSystemPages) >= 4096)
{
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 3 * 2;
}
else
{
MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 8;
}
MiMemoryConsumers[MC_USER].PagesTarget = MiMemoryConsumers[MC_USER].PagesTarget =
NrAvailablePages - MiMinimumAvailablePages; NrAvailablePages - MiMinimumAvailablePages;
MiMemoryConsumers[MC_PPOOL].PagesTarget = NrAvailablePages / 2; MiMemoryConsumers[MC_PPOOL].PagesTarget = NrAvailablePages / 2;