update for HEAD-2003091401
[reactos.git] / ntoskrnl / mm / pager.c
1 /* $Id$
2  *
3  * COPYRIGHT:    See COPYING in the top level directory
4  * PROJECT:      ReactOS kernel
5  * FILE:         ntoskrnl/mm/pager.c
6  * PURPOSE:      Moves infrequently used data out of memory
7  * PROGRAMMER:   David Welch (welch@cwcom.net)
8  * UPDATE HISTORY: 
9  *               27/05/98: Created
10  */
11
12 /* INCLUDES ****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/ps.h>
16 #include <internal/ke.h>
17 #include <internal/mm.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 /* GLOBALS *******************************************************************/
23
24 static HANDLE PagerThreadHandle;
25 static CLIENT_ID PagerThreadId;
26 static KEVENT PagerThreadEvent;
27 static BOOLEAN PagerThreadShouldTerminate;
28 static ULONG PagerThreadWorkCount;
29
30 /* FUNCTIONS *****************************************************************/
31
32 BOOLEAN
33 MiIsPagerThread(VOID)
34 {
35   return(PsGetCurrentThreadId() == PagerThreadId.UniqueThread);
36 }
37
38 VOID
39 MiStartPagerThread(VOID)
40 {
41   ULONG WasWorking;
42
43   WasWorking = InterlockedIncrement(&PagerThreadWorkCount);
44   if (WasWorking == 1)
45     {
46       KeSetEvent(&PagerThreadEvent, IO_NO_INCREMENT, FALSE);
47     }
48 }
49
50 VOID
51 MiStopPagerThread(VOID)
52 {
53   (VOID)InterlockedDecrement(&PagerThreadWorkCount);
54 }
55
56 static NTSTATUS STDCALL
57 MmPagerThreadMain(PVOID Ignored)
58 {
59    NTSTATUS Status;
60
61    for(;;)
62      {
63        /* Wake for a low memory situation or a terminate request. */
64        Status = KeWaitForSingleObject(&PagerThreadEvent,
65                                       0,
66                                       KernelMode,
67                                       FALSE,
68                                       NULL);
69        if (!NT_SUCCESS(Status))
70          {
71            DbgPrint("PagerThread: Wait failed\n");
72            KEBUGCHECK(0);
73          }
74        if (PagerThreadShouldTerminate)
75          {
76            DbgPrint("PagerThread: Terminating\n");
77            return(STATUS_SUCCESS);
78          }
79        do
80          {
81            /* Try and make some memory available to the system. */
82            MmRebalanceMemoryConsumers();
83          } while(PagerThreadWorkCount > 0);
84      }
85 }
86
87 NTSTATUS MmInitPagerThread(VOID)
88 {
89    NTSTATUS Status;
90    
91    PagerThreadShouldTerminate = FALSE;
92    PagerThreadWorkCount = 0;
93    KeInitializeEvent(&PagerThreadEvent,
94                      SynchronizationEvent,
95                      FALSE);
96    
97    Status = PsCreateSystemThread(&PagerThreadHandle,
98                                  THREAD_ALL_ACCESS,
99                                  NULL,
100                                  NULL,
101                                  &PagerThreadId,
102                                  (PKSTART_ROUTINE) MmPagerThreadMain,
103                                  NULL);
104    if (!NT_SUCCESS(Status))
105      {
106         return(Status);
107      }
108    
109    return(STATUS_SUCCESS);
110 }