xref: /reactos/ntoskrnl/mm/ARM3/zeropage.c (revision 98e62b9b)
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 KEVENT MmZeroingPageEvent;
21 
22 /* PRIVATE FUNCTIONS **********************************************************/
23 
24 VOID
25 NTAPI
26 MiFindInitializationCode(OUT PVOID *StartVa,
27 OUT PVOID *EndVa);
28 
29 VOID
30 NTAPI
31 MiFreeInitializationCode(IN PVOID StartVa,
32 IN PVOID EndVa);
33 
34 VOID
35 NTAPI
MmZeroPageThread(VOID)36 MmZeroPageThread(VOID)
37 {
38     PKTHREAD Thread = KeGetCurrentThread();
39     PVOID StartAddress, EndAddress;
40     PVOID WaitObjects[2];
41 
42     /* Get the discardable sections to free them */
43     MiFindInitializationCode(&StartAddress, &EndAddress);
44     if (StartAddress) MiFreeInitializationCode(StartAddress, EndAddress);
45     DPRINT("Free pages: %lx\n", MmAvailablePages);
46 
47     /* Set our priority to 0 */
48     Thread->BasePriority = 0;
49     KeSetPriorityThread(Thread, 0);
50 
51     /* Setup the wait objects */
52     WaitObjects[0] = &MmZeroingPageEvent;
53 //    WaitObjects[1] = &PoSystemIdleTimer; FIXME: Implement idle timer
54 
55     while (TRUE)
56     {
57         KIRQL OldIrql;
58 
59         KeWaitForMultipleObjects(1, // 2
60                                  WaitObjects,
61                                  WaitAny,
62                                  WrFreePage,
63                                  KernelMode,
64                                  FALSE,
65                                  NULL,
66                                  NULL);
67         OldIrql = MiAcquirePfnLock();
68 
69         while (TRUE)
70         {
71             ULONG PageCount = 0;
72             PMMPFN Pfn1 = (PMMPFN)LIST_HEAD;
73             PVOID ZeroAddress;
74             PFN_NUMBER PageIndex, FreePage;
75 
76             while (PageCount < MI_ZERO_PTES)
77             {
78                 PMMPFN Pfn2;
79 
80                 if (!MmFreePageListHead.Total)
81                     break;
82 
83                 PageIndex = MmFreePageListHead.Flink;
84                 ASSERT(PageIndex != LIST_HEAD);
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                 Pfn2 = MiGetPfnEntry(PageIndex);
100                 Pfn2->u1.Flink = (PFN_NUMBER)Pfn1;
101                 Pfn1 = Pfn2;
102                 PageCount++;
103             }
104             MiReleasePfnLock(OldIrql);
105 
106             if (PageCount == 0)
107             {
108                 KeClearEvent(&MmZeroingPageEvent);
109                 break;
110             }
111 
112             ZeroAddress = MiMapPagesInZeroSpace(Pfn1, PageCount);
113             ASSERT(ZeroAddress);
114             KeZeroPages(ZeroAddress, PageCount * PAGE_SIZE);
115             MiUnmapPagesInZeroSpace(ZeroAddress, PageCount);
116 
117             OldIrql = MiAcquirePfnLock();
118 
119             while (Pfn1 != (PMMPFN)LIST_HEAD)
120             {
121                 PageIndex = MiGetPfnEntryIndex(Pfn1);
122                 Pfn1 = (PMMPFN)Pfn1->u1.Flink;
123                 MiInsertPageInList(&MmZeroedPageListHead, PageIndex);
124             }
125         }
126     }
127 }
128 
129 /* EOF */
130