- 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 CacheSegLookasideList;
static ULONG CcTimeStamp;
static KEVENT LazyCloseThreadEvent;
static HANDLE LazyCloseThreadHandle;
static CLIENT_ID LazyCloseThreadId;
static volatile BOOLEAN LazyCloseThreadShouldTerminate;
#if defined(__GNUC__)
/* void * alloca(size_t size); */
@ -308,85 +303,97 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
* actually freed is returned.
*/
{
PLIST_ENTRY current_entry;
PCACHE_SEGMENT current, last = NULL;
ULONG PagesPerSegment;
ULONG PagesFreed;
KIRQL oldIrql;
LIST_ENTRY FreeList;
PLIST_ENTRY current_entry;
PCACHE_SEGMENT current;
ULONG PagesPerSegment;
ULONG PagesFreed;
KIRQL oldIrql;
LIST_ENTRY FreeList;
DPRINT("CcRosTrimCache(Target %d)\n", Target);
*NrFreed = 0;
InitializeListHead(&FreeList);
DPRINT("CcRosTrimCache(Target %d)\n", Target);
*NrFreed = 0;
InitializeListHead(&FreeList);
KeAcquireGuardedMutex(&ViewLock);
current_entry = CacheSegmentLRUListHead.Flink;
while (current_entry != &CacheSegmentLRUListHead && Target > 0)
KeAcquireGuardedMutex(&ViewLock);
current_entry = CacheSegmentLRUListHead.Flink;
while (current_entry != &CacheSegmentLRUListHead && Target > 0)
{
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
CacheSegmentLRUListEntry);
current_entry = current_entry->Flink;
NTSTATUS Status;
Status = STATUS_SUCCESS;
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
CacheSegmentLRUListEntry);
current_entry = current_entry->Flink;
KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
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);
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);
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))
{
current_entry = RemoveHeadList(&FreeList);
current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
BcbSegmentListEntry);
CcRosInternalFreeCacheSegment(current);
}
DPRINT("CcRosTrimCache() finished\n");
return(STATUS_SUCCESS);
if (current->MappedCount > 0 && !current->Dirty && !current->PageOut)
{
ULONG i;
CcRosCacheSegmentIncRefCount(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);
}
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
@ -1151,15 +1158,7 @@ CcRosDereferenceCache(PFILE_OBJECT FileObject)
if (Bcb->RefCount == 0)
{
MmFreeSectionSegments(Bcb->FileObject);
if (Bcb->RemoveOnClose)
{
CcRosDeleteFileCache(FileObject, Bcb);
}
else
{
Bcb->TimeStamp = CcTimeStamp;
InsertHeadList(&ClosedListHead, &Bcb->BcbRemoveListEntry);
}
}
}
KeReleaseGuardedMutex(&ViewLock);
@ -1188,15 +1187,7 @@ CcRosReleaseFileCache(PFILE_OBJECT FileObject)
if (Bcb->RefCount == 0)
{
MmFreeSectionSegments(Bcb->FileObject);
if (Bcb->RemoveOnClose)
{
CcRosDeleteFileCache(FileObject, Bcb);
}
else
{
Bcb->TimeStamp = CcTimeStamp;
InsertHeadList(&ClosedListHead, &Bcb->BcbRemoveListEntry);
}
}
}
}
@ -1315,60 +1306,6 @@ CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers
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
INIT_FUNCTION
NTAPI
@ -1379,8 +1316,6 @@ CcInitView(VOID)
PVOID Buffer;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
#endif
NTSTATUS Status;
KPRIORITY Priority;
DPRINT("CcInitView()\n");
#ifdef CACHE_BITMAP
@ -1443,25 +1378,6 @@ CcInitView(VOID)
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 */

View file

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

View file

@ -68,7 +68,18 @@ MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
/* Set up targets. */
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 =
NrAvailablePages - MiMinimumAvailablePages;
MiMemoryConsumers[MC_PPOOL].PagesTarget = NrAvailablePages / 2;