:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / ntoskrnl / mm / mpw.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  *
21  * PROJECT:      ReactOS kernel
22  * FILE:         ntoskrnl/mm/mpw.c
23  * PURPOSE:      Writes data that has been modified in memory but not on
24  *               the disk
25  * PROGRAMMER:   David Welch (welch@cwcom.net)
26  * UPDATE HISTORY: 
27  *               27/05/98: Created
28  */
29
30 /* INCLUDES ****************************************************************/
31
32 #include <ddk/ntddk.h>
33 #include <internal/ps.h>
34 #include <internal/mm.h>
35 #include <internal/cc.h>
36
37 #define NDEBUG
38 #include <internal/debug.h>
39
40 /* GLOBALS *******************************************************************/
41
42 static HANDLE MpwThreadHandle;
43 static CLIENT_ID MpwThreadId;
44 static KEVENT MpwThreadEvent;
45 static volatile BOOLEAN MpwThreadShouldTerminate;
46
47 /* FUNCTIONS *****************************************************************/
48
49 NTSTATUS STDCALL
50 MmWriteDirtyPages(ULONG Target, PULONG Actual)
51 {
52   PHYSICAL_ADDRESS Page;
53   PHYSICAL_ADDRESS NextPage;
54   NTSTATUS Status;
55
56   Page = MmGetLRUFirstUserPage();
57   while (Page.QuadPart != 0LL && Target > 0)
58     {
59       NextPage = MmGetLRUNextUserPage(Page);
60       if (MmIsDirtyPageRmap(Page))
61         {
62           Status = MmWritePagePhysicalAddress(Page);
63           if (NT_SUCCESS(Status))
64             {
65               Target--;
66             }
67         } 
68       Page = NextPage;
69     }
70   *Actual = Target;
71   return(STATUS_SUCCESS);
72 }
73
74 NTSTATUS STDCALL
75 MmMpwThreadMain(PVOID Ignored)
76 {
77   NTSTATUS Status;
78   ULONG PagesWritten;
79   LARGE_INTEGER Timeout;
80   
81   Timeout.QuadPart = -50000000;
82   
83   for(;;)
84     {
85       Status = KeWaitForSingleObject(&MpwThreadEvent,
86                                      0,
87                                      KernelMode,
88                                      FALSE,
89                                      &Timeout);
90       if (!NT_SUCCESS(Status))
91         {
92           DbgPrint("MpwThread: Wait failed\n");
93           KeBugCheck(0);
94           return(STATUS_UNSUCCESSFUL);
95         }
96       if (MpwThreadShouldTerminate)
97         {
98           DbgPrint("MpwThread: Terminating\n");
99           return(STATUS_SUCCESS);
100         }
101       
102       PagesWritten = 0;
103       MmWriteDirtyPages(128, &PagesWritten);
104       CcRosFlushDirtyPages(128, &PagesWritten);
105     }
106 }
107
108 NTSTATUS MmInitMpwThread(VOID)
109 {
110   KPRIORITY Priority;
111   NTSTATUS Status;
112   
113   MpwThreadShouldTerminate = FALSE;
114   KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
115   
116   Status = PsCreateSystemThread(&MpwThreadHandle,
117                                 THREAD_ALL_ACCESS,
118                                 NULL,
119                                 NULL,
120                                 &MpwThreadId,
121                                 MmMpwThreadMain,
122                                 NULL);
123   if (!NT_SUCCESS(Status))
124     {
125       return(Status);
126      }
127   
128   Priority = 1;
129   NtSetInformationThread(MpwThreadHandle,
130                          ThreadPriority,
131                          &Priority,
132                          sizeof(Priority));
133   
134   return(STATUS_SUCCESS);
135 }