reactos/reactos/ntoskrnl/mm/mpw.c
Aleksey Bragin fad1031b37 - Implement MiShutdownMemoryManager (stops MPW thread and writes all dirty pages to disk).
- Move MiShutdownMemoryManager invocation to where it should really happen (before filesystems shutdown).
- As a result, MPW doesn't have a chance to flush pages when filesystems are already down. However, 1st assertion as mentioned in bug 2872 still happens. 2nd one is gone.
See issue #2872 for more details.

svn path=/trunk/; revision=32547
2008-03-03 18:03:04 +00:00

148 lines
3.7 KiB
C

/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/mpw.c
* PURPOSE: Writes data that has been modified in memory but not on
* the disk
*
* PROGRAMMERS: David Welch (welch@cwcom.net)
*/
/* INCLUDES ****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
HANDLE MpwThreadHandle;
static CLIENT_ID MpwThreadId;
KEVENT MpwThreadEvent;
BOOLEAN MpwThreadShouldTerminate;
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
MmWriteDirtyPages(ULONG Target, PULONG Actual)
{
PFN_TYPE Page;
PFN_TYPE NextPage;
NTSTATUS Status;
Page = MmGetLRUFirstUserPage();
while (Page != 0 && Target > 0)
{
/*
* FIXME: While the current page is write back it is possible
* that the next page is freed and not longer a user page.
*/
NextPage = MmGetLRUNextUserPage(Page);
if (MmIsDirtyPageRmap(Page))
{
Status = MmWritePagePhysicalAddress(Page);
if (NT_SUCCESS(Status))
{
Target--;
}
}
Page = NextPage;
}
*Actual = Target;
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
MmMpwThreadMain(PVOID Ignored)
{
NTSTATUS Status;
ULONG PagesWritten;
LARGE_INTEGER Timeout;
Timeout.QuadPart = -50000000;
for(;;)
{
Status = KeWaitForSingleObject(&MpwThreadEvent,
0,
KernelMode,
FALSE,
&Timeout);
if (!NT_SUCCESS(Status))
{
DbgPrint("MpwThread: Wait failed\n");
KEBUGCHECK(0);
return(STATUS_UNSUCCESSFUL);
}
if (MpwThreadShouldTerminate)
{
DbgPrint("MpwThread: Terminating\n");
return(STATUS_SUCCESS);
}
PagesWritten = 0;
#if 0
/*
* FIXME: MmWriteDirtyPages doesn't work correctly.
*/
MmWriteDirtyPages(128, &PagesWritten);
#endif
CcRosFlushDirtyPages(128, &PagesWritten);
}
}
NTSTATUS
NTAPI
MmInitMpwThread(VOID)
{
KPRIORITY Priority;
NTSTATUS Status;
MpwThreadShouldTerminate = FALSE;
KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
Status = PsCreateSystemThread(&MpwThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&MpwThreadId,
(PKSTART_ROUTINE) MmMpwThreadMain,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Priority = 1;
NtSetInformationThread(MpwThreadHandle,
ThreadPriority,
&Priority,
sizeof(Priority));
return(STATUS_SUCCESS);
}
NTSTATUS
NTAPI
MmInitBsmThread(VOID)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE ThreadHandle;
/* Create the thread */
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
Status = PsCreateSystemThread(&ThreadHandle,
THREAD_ALL_ACCESS,
&ObjectAttributes,
NULL,
NULL,
KeBalanceSetManager,
NULL);
/* Close the handle and return status */
ZwClose(ThreadHandle);
return Status;
}