update for HEAD-2003091401
[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       /*
60        * FIXME: While the current page is write back it is possible
61        *        that the next page is freed and not longer a user page.
62        */
63       NextPage = MmGetLRUNextUserPage(Page);
64       if (MmIsDirtyPageRmap(Page))
65         {
66           Status = MmWritePagePhysicalAddress(Page);
67           if (NT_SUCCESS(Status))
68             {
69               Target--;
70             }
71         } 
72       Page = NextPage;
73     }
74   *Actual = Target;
75   return(STATUS_SUCCESS);
76 }
77
78 NTSTATUS STDCALL
79 MmMpwThreadMain(PVOID Ignored)
80 {
81   NTSTATUS Status;
82   ULONG PagesWritten;
83   LARGE_INTEGER Timeout;
84   
85   Timeout.QuadPart = -50000000;
86   
87   for(;;)
88     {
89       Status = KeWaitForSingleObject(&MpwThreadEvent,
90                                      0,
91                                      KernelMode,
92                                      FALSE,
93                                      &Timeout);
94       if (!NT_SUCCESS(Status))
95         {
96           DbgPrint("MpwThread: Wait failed\n");
97           KEBUGCHECK(0);
98           return(STATUS_UNSUCCESSFUL);
99         }
100       if (MpwThreadShouldTerminate)
101         {
102           DbgPrint("MpwThread: Terminating\n");
103           return(STATUS_SUCCESS);
104         }
105       
106       PagesWritten = 0;
107 #if 0
108       /* 
109        *  FIXME: MmWriteDirtyPages doesn't work correctly.
110        */
111       MmWriteDirtyPages(128, &PagesWritten);
112 #endif
113       CcRosFlushDirtyPages(128, &PagesWritten);
114     }
115 }
116
117 NTSTATUS MmInitMpwThread(VOID)
118 {
119   KPRIORITY Priority;
120   NTSTATUS Status;
121   
122   MpwThreadShouldTerminate = FALSE;
123   KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE);
124   
125   Status = PsCreateSystemThread(&MpwThreadHandle,
126                                 THREAD_ALL_ACCESS,
127                                 NULL,
128                                 NULL,
129                                 &MpwThreadId,
130                                 (PKSTART_ROUTINE) MmMpwThreadMain,
131                                 NULL);
132   if (!NT_SUCCESS(Status))
133     {
134       return(Status);
135      }
136   
137   Priority = 1;
138   NtSetInformationThread(MpwThreadHandle,
139                          ThreadPriority,
140                          &Priority,
141                          sizeof(Priority));
142   
143   return(STATUS_SUCCESS);
144 }