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