xref: /reactos/ntoskrnl/mm/ARM3/zeropage.c (revision 50cf16b3)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4  * FILE:            ntoskrnl/mm/ARM3/zeropage.c
5  * PURPOSE:         ARM Memory Manager Zero Page Thread Support
6  * PROGRAMMERS:     ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 #define MODULE_INVOLVED_IN_ARM3
16 #include <mm/ARM3/miarm.h>
17 
18 /* GLOBALS ********************************************************************/
19 
20 BOOLEAN MmZeroingPageThreadActive;
21 KEVENT MmZeroingPageEvent;
22 
23 /* PRIVATE FUNCTIONS **********************************************************/
24 
25 VOID
26 NTAPI
27 MiFindInitializationCode(OUT PVOID *StartVa,
28 OUT PVOID *EndVa);
29 
30 VOID
31 NTAPI
32 MiFreeInitializationCode(IN PVOID StartVa,
33 IN PVOID EndVa);
34 
35 VOID
36 NTAPI
37 MmZeroPageThread(VOID)
38 {
39     PKTHREAD Thread = KeGetCurrentThread();
40     PVOID StartAddress, EndAddress;
41     PVOID WaitObjects[2];
42     KIRQL OldIrql;
43     PVOID ZeroAddress;
44     PFN_NUMBER PageIndex, FreePage;
45     PMMPFN Pfn1;
46 
47     /* Get the discardable sections to free them */
48     MiFindInitializationCode(&StartAddress, &EndAddress);
49     if (StartAddress) MiFreeInitializationCode(StartAddress, EndAddress);
50     DPRINT("Free non-cache pages: %lx\n", MmAvailablePages + MiMemoryConsumers[MC_CACHE].PagesUsed);
51 
52     /* Set our priority to 0 */
53     Thread->BasePriority = 0;
54     KeSetPriorityThread(Thread, 0);
55 
56     /* Setup the wait objects */
57     WaitObjects[0] = &MmZeroingPageEvent;
58 //    WaitObjects[1] = &PoSystemIdleTimer; FIXME: Implement idle timer
59 
60     while (TRUE)
61     {
62         KeWaitForMultipleObjects(1, // 2
63                                  WaitObjects,
64                                  WaitAny,
65                                  WrFreePage,
66                                  KernelMode,
67                                  FALSE,
68                                  NULL,
69                                  NULL);
70         OldIrql = MiAcquirePfnLock();
71         MmZeroingPageThreadActive = TRUE;
72 
73         while (TRUE)
74         {
75             if (!MmFreePageListHead.Total)
76             {
77                 MmZeroingPageThreadActive = FALSE;
78                 MiReleasePfnLock(OldIrql);
79                 break;
80             }
81 
82             PageIndex = MmFreePageListHead.Flink;
83             ASSERT(PageIndex != LIST_HEAD);
84             Pfn1 = MiGetPfnEntry(PageIndex);
85             MI_SET_USAGE(MI_USAGE_ZERO_LOOP);
86             MI_SET_PROCESS2("Kernel 0 Loop");
87             FreePage = MiRemoveAnyPage(MI_GET_PAGE_COLOR(PageIndex));
88 
89             /* The first global free page should also be the first on its own list */
90             if (FreePage != PageIndex)
91             {
92                 KeBugCheckEx(PFN_LIST_CORRUPT,
93                              0x8F,
94                              FreePage,
95                              PageIndex,
96                              0);
97             }
98 
99             Pfn1->u1.Flink = LIST_HEAD;
100             MiReleasePfnLock(OldIrql);
101 
102             ZeroAddress = MiMapPagesInZeroSpace(Pfn1, 1);
103             ASSERT(ZeroAddress);
104             RtlZeroMemory(ZeroAddress, PAGE_SIZE);
105             MiUnmapPagesInZeroSpace(ZeroAddress, 1);
106 
107             OldIrql = MiAcquirePfnLock();
108 
109             MiInsertPageInList(&MmZeroedPageListHead, PageIndex);
110         }
111     }
112 }
113 
114 /* EOF */
115