[REACTOS]
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / zeropage.c
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 "../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 DPRINT1("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 = KeAcquireQueuedSpinLock(LockQueuePfnLock);
71 while (TRUE)
72 {
73 if (!MmFreePageListHead.Total)
74 {
75 MmZeroingPageThreadActive = FALSE;
76 KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
77 break;
78 }
79
80 PageIndex = MmFreePageListHead.Flink;
81 ASSERT(PageIndex != LIST_HEAD);
82 Pfn1 = MiGetPfnEntry(PageIndex);
83 MI_SET_USAGE(MI_USAGE_ZERO_LOOP);
84 MI_SET_PROCESS2("Kernel 0 Loop");
85 FreePage = MiRemoveAnyPage(MI_GET_PAGE_COLOR(PageIndex));
86
87 /* The first global free page should also be the first on its own list */
88 if (FreePage != PageIndex)
89 {
90 KeBugCheckEx(PFN_LIST_CORRUPT,
91 0x8F,
92 FreePage,
93 PageIndex,
94 0);
95 }
96
97 Pfn1->u1.Flink = LIST_HEAD;
98 KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
99
100 ZeroAddress = MiMapPagesInZeroSpace(Pfn1, 1);
101 ASSERT(ZeroAddress);
102 RtlZeroMemory(ZeroAddress, PAGE_SIZE);
103 MiUnmapPagesInZeroSpace(ZeroAddress, 1);
104
105 OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
106
107 MiInsertPageInList(&MmZeroedPageListHead, PageIndex);
108 }
109 }
110 }
111
112 /* EOF */