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