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 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