ReactOS 0.4.16-dev-311-g9382aa2
pool.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/pool.c
5 * PURPOSE: ARM Memory Manager Pool Allocator
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
36
37/* PRIVATE FUNCTIONS **********************************************************/
38
39VOID
42 IN ULONG PageCount)
43{
44 PMMPTE PointerPte, LastPte;
46
47 /* If pool is physical, can't protect PTEs */
49
50 /* Get PTE pointers and loop */
51 PointerPte = MiAddressToPte(VirtualAddress);
52 LastPte = PointerPte + PageCount;
53 do
54 {
55 /* Capture the PTE for safety */
56 TempPte = *PointerPte;
57
58 /* Mark it as an invalid PTE, set proto bit to recognize it as pool */
59 TempPte.u.Hard.Valid = 0;
60 TempPte.u.Soft.Prototype = 1;
61 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
62 } while (++PointerPte < LastPte);
63
64 /* Flush the TLB */
66}
67
71 IN ULONG PageCount)
72{
73 PMMPTE PointerPte;
75 PFN_NUMBER UnprotectedPages = 0;
76
77 /* If pool is physical, can't protect PTEs */
79
80 /* Get, and capture the PTE */
81 PointerPte = MiAddressToPte(VirtualAddress);
82 TempPte = *PointerPte;
83
84 /* Loop protected PTEs */
85 while ((TempPte.u.Hard.Valid == 0) && (TempPte.u.Soft.Prototype == 1))
86 {
87 /* Unprotect the PTE */
88 TempPte.u.Hard.Valid = 1;
89 TempPte.u.Soft.Prototype = 0;
90 MI_WRITE_VALID_PTE(PointerPte, TempPte);
91
92 /* One more page */
93 if (++UnprotectedPages == PageCount) break;
94
95 /* Capture next PTE */
96 TempPte = *(++PointerPte);
97 }
98
99 /* Return if any pages were unprotected */
100 return UnprotectedPages ? TRUE : FALSE;
101}
102
104VOID
106 OUT PVOID* PoolFlink,
107 OUT PVOID* PoolBlink)
108{
109 BOOLEAN Safe;
110 PVOID PoolVa;
111
112 /* Initialize variables */
113 *PoolFlink = *PoolBlink = NULL;
114
115 /* Check if the list has entries */
116 if (IsListEmpty(Links) == FALSE)
117 {
118 /* We are going to need to forward link to do an insert */
119 PoolVa = Links->Flink;
120
121 /* So make it safe to access */
122 Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
123 if (Safe) *PoolFlink = PoolVa;
124 }
125
126 /* Are we going to need a backward link too? */
127 if (Links != Links->Blink)
128 {
129 /* Get the head's backward link for the insert */
130 PoolVa = Links->Blink;
131
132 /* Make it safe to access */
133 Safe = MiUnProtectFreeNonPagedPool(PoolVa, 1);
134 if (Safe) *PoolBlink = PoolVa;
135 }
136}
137
139VOID
141 IN PVOID PoolBlink)
142{
143 /* Reprotect the pages, if they got unprotected earlier */
144 if (PoolFlink) MiProtectFreeNonPagedPool(PoolFlink, 1);
145 if (PoolBlink) MiProtectFreeNonPagedPool(PoolBlink, 1);
146}
147
148VOID
149NTAPI
152 IN BOOLEAN Critical)
153{
154 PVOID PoolFlink, PoolBlink;
155
156 /* Make the list accessible */
157 MiProtectedPoolUnProtectLinks(ListHead, &PoolFlink, &PoolBlink);
158
159 /* Now insert in the right position */
160 Critical ? InsertHeadList(ListHead, Entry) : InsertTailList(ListHead, Entry);
161
162 /* And reprotect the pages containing the free links */
163 MiProtectedPoolProtectLinks(PoolFlink, PoolBlink);
164}
165
166VOID
167NTAPI
169{
170 PVOID PoolFlink, PoolBlink;
171
172 /* Make the list accessible */
173 MiProtectedPoolUnProtectLinks(Entry, &PoolFlink, &PoolBlink);
174
175 /* Now remove */
177
178 /* And reprotect the pages containing the free links */
179 if (PoolFlink) MiProtectFreeNonPagedPool(PoolFlink, 1);
180 if (PoolBlink) MiProtectFreeNonPagedPool(PoolBlink, 1);
181}
182
183CODE_SEG("INIT")
184VOID
185NTAPI
187{
189
190 /* Default low threshold of 8MB or one third of nonpaged pool */
193
194 /* Default high threshold of 20MB or 50% */
198}
199
200CODE_SEG("INIT")
201VOID
202NTAPI
204{
206 PFN_NUMBER FreePoolInPages;
207
208 /* Lock paged pool */
210
211 /* Total size of the paged pool minus the allocated size, is free */
213
214 /* Check the initial state high state */
215 if (FreePoolInPages >= MiHighPagedPoolThreshold)
216 {
217 /* We have plenty of pool */
219 }
220 else
221 {
222 /* We don't */
224 }
225
226 /* Check the initial low state */
227 if (FreePoolInPages <= MiLowPagedPoolThreshold)
228 {
229 /* We're very low in free pool memory */
231 }
232 else
233 {
234 /* We're not */
236 }
237
238 /* Release the paged pool lock */
240
241 /* Now it's time for the nonpaged pool lock */
243
244 /* Free pages are the maximum minus what's been allocated */
246
247 /* Check if we have plenty */
248 if (FreePoolInPages >= MiHighNonPagedPoolThreshold)
249 {
250 /* We do, set the event */
252 }
253 else
254 {
255 /* We don't, clear the event */
257 }
258
259 /* Check if we have very little */
260 if (FreePoolInPages <= MiLowNonPagedPoolThreshold)
261 {
262 /* We do, set the event */
264 }
265 else
266 {
267 /* We don't, clear it */
269 }
270
271 /* We're done, release the nonpaged pool lock */
273}
274
275CODE_SEG("INIT")
276VOID
277NTAPI
279{
280 ULONG i;
281 PFN_COUNT PoolPages;
282 PMMFREE_POOL_ENTRY FreeEntry, FirstEntry;
283 PMMPTE PointerPte;
284 PAGED_CODE();
285
286 //
287 // Initialize the pool S-LISTs as well as their maximum count. In general,
288 // we'll allow 8 times the default on a 2GB system, and two times the default
289 // on a 1GB system.
290 //
293 if (MmNumberOfPhysicalPages >= ((2 * _1GB) /PAGE_SIZE))
294 {
297 }
299 {
302 }
303
304 //
305 // However if debugging options for the pool are enabled, turn off the S-LIST
306 // to reduce the risk of messing things up even more
307 //
309 {
312 }
313
314 //
315 // We keep 4 lists of free pages (4 lists help avoid contention)
316 //
317 for (i = 0; i < MI_MAX_FREE_PAGE_LISTS; i++)
318 {
319 //
320 // Initialize each of them
321 //
323 }
324
325 //
326 // Calculate how many pages the initial nonpaged pool has
327 //
329 MmNumberOfFreeNonPagedPool = PoolPages;
330
331 //
332 // Initialize the first free entry
333 //
334 FreeEntry = MmNonPagedPoolStart;
335 FirstEntry = FreeEntry;
336 FreeEntry->Size = PoolPages;
338 FreeEntry->Owner = FirstEntry;
339
340 //
341 // Insert it into the last list
342 //
344 &FreeEntry->List);
345
346 //
347 // Now create free entries for every single other page
348 //
349 while (PoolPages-- > 1)
350 {
351 //
352 // Link them all back to the original entry
353 //
354 FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)FreeEntry + PAGE_SIZE);
355 FreeEntry->Owner = FirstEntry;
357 }
358
359 //
360 // Validate and remember first allocated pool page
361 //
363 ASSERT(PointerPte->u.Hard.Valid == 1);
365
366 //
367 // Keep track of where initial nonpaged pool ends
368 //
371
372 //
373 // Validate and remember last allocated pool page
374 //
375 PointerPte = MiAddressToPte((PVOID)((ULONG_PTR)MmNonPagedPoolEnd0 - 1));
376 ASSERT(PointerPte->u.Hard.Valid == 1);
378
379 //
380 // Validate the first nonpaged pool expansion page (which is a guard page)
381 //
383 ASSERT(PointerPte->u.Hard.Valid == 0);
384
385 //
386 // Calculate the size of the expansion region alone
387 //
390
391 //
392 // Remove 2 pages, since there's a guard page on top and on the bottom
393 //
395
396 //
397 // Now initialize the nonpaged pool expansion PTE space. Remember there's a
398 // guard page on top so make sure to skip it. The bottom guard page will be
399 // guaranteed by the fact our size is off by one.
400 //
401 MiInitializeSystemPtes(PointerPte + 1,
404}
405
407NTAPI
409{
410 //
411 // Use a simple bounds check
412 //
413 if (PoolAddress >= MmPagedPoolStart && PoolAddress <= MmPagedPoolEnd)
414 return PagedPool;
415 else if (PoolAddress >= MmNonPagedPoolStart && PoolAddress <= MmNonPagedPoolEnd)
416 return NonPagedPool;
417 KeBugCheckEx(BAD_POOL_CALLER, 0x42, (ULONG_PTR)PoolAddress, 0, 0);
418}
419
420PVOID
421NTAPI
423 IN SIZE_T SizeInBytes)
424{
425 PFN_NUMBER PageFrameNumber;
426 PFN_COUNT SizeInPages, PageTableCount;
427 ULONG i;
429 PLIST_ENTRY NextEntry, NextHead, LastHead;
430 PMMPTE PointerPte, StartPte;
431 PMMPDE PointerPde;
432 ULONG EndAllocation;
435 PMMPFN Pfn1;
436 PVOID BaseVa, BaseVaStart;
437 PMMFREE_POOL_ENTRY FreeEntry;
438
439 //
440 // Figure out how big the allocation is in pages
441 //
442 SizeInPages = (PFN_COUNT)BYTES_TO_PAGES(SizeInBytes);
443
444 //
445 // Check for overflow
446 //
447 if (SizeInPages == 0)
448 {
449 //
450 // Fail
451 //
452 return NULL;
453 }
454
455 //
456 // Handle paged pool
457 //
459 {
460 //
461 // If only one page is being requested, try to grab it from the S-LIST
462 //
463 if ((SizeInPages == 1) && (ExQueryDepthSList(&MiPagedPoolSListHead)))
464 {
466 if (BaseVa) return BaseVa;
467 }
468
469 //
470 // Lock the paged pool mutex
471 //
473
474 //
475 // Find some empty allocation space
476 //
478 SizeInPages,
480 if (i == 0xFFFFFFFF)
481 {
482 //
483 // Get the page bit count
484 //
485 i = ((SizeInPages - 1) / PTE_PER_PAGE) + 1;
486 DPRINT("Paged pool expansion: %lu %x\n", i, SizeInPages);
487
488 //
489 // Check if there is enougn paged pool expansion space left
490 //
493 {
494 //
495 // Out of memory!
496 //
497 DPRINT1("FAILED to allocate %Iu bytes from paged pool\n", SizeInBytes);
499 return NULL;
500 }
501
502 //
503 // Check if we'll have to expand past the last PTE we have available
504 //
507 {
508 //
509 // We can only support this much then
510 //
512 PageTableCount = (PFN_COUNT)(PointerPde + 1 -
514 ASSERT(PageTableCount < i);
515 i = PageTableCount;
516 }
517 else
518 {
519 //
520 // Otherwise, there is plenty of space left for this expansion
521 //
522 PageTableCount = i;
523 }
524
525 //
526 // Get the template PDE we'll use to expand
527 //
529
530 //
531 // Get the first PTE in expansion space
532 //
534 BaseVa = MiPdeToPte(PointerPde);
535 BaseVaStart = BaseVa;
536
537 //
538 // Lock the PFN database and loop pages
539 //
540 OldIrql = MiAcquirePfnLock();
541 do
542 {
543 //
544 // It should not already be valid
545 //
546 ASSERT(PointerPde->u.Hard.Valid == 0);
547
548 /* Request a page */
550 MI_SET_PROCESS2("Kernel");
551 PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
552 TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
553#if (_MI_PAGING_LEVELS >= 3)
554 /* On PAE/x64 systems, there's no double-buffering */
555 /* Initialize the PFN entry for it */
556 MiInitializePfnForOtherProcess(PageFrameNumber,
557 (PMMPTE)PointerPde,
558 PFN_FROM_PTE(MiAddressToPte(PointerPde)));
559
560 /* Write the actual PDE now */
561 MI_WRITE_VALID_PDE(PointerPde, TempPde);
562#else
563 //
564 // Save it into our double-buffered system page directory
565 //
566 MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)] = TempPde;
567
568 /* Initialize the PFN */
569 MiInitializePfnForOtherProcess(PageFrameNumber,
570 (PMMPTE)PointerPde,
572#endif
573
574 //
575 // Move on to the next expansion address
576 //
577 PointerPde++;
578 BaseVa = (PVOID)((ULONG_PTR)BaseVa + PAGE_SIZE);
579 i--;
580 } while (i > 0);
581
582 //
583 // Release the PFN database lock
584 //
585 MiReleasePfnLock(OldIrql);
586
587 //
588 // These pages are now available, clear their availablity bits
589 //
594 EndAllocation,
595 PageTableCount * PTE_PER_PAGE);
596
597 //
598 // Update the next expansion location
599 //
601
602 //
603 // Zero out the newly available memory
604 //
605 RtlZeroMemory(BaseVaStart, PageTableCount * PAGE_SIZE);
606
607 //
608 // Now try consuming the pages again
609 //
611 SizeInPages,
612 0);
613 if (i == 0xFFFFFFFF)
614 {
615 //
616 // Out of memory!
617 //
618 DPRINT1("FAILED to allocate %Iu bytes from paged pool\n", SizeInBytes);
620 return NULL;
621 }
622 }
623
624 //
625 // Update the pool hint if the request was just one page
626 //
627 if (SizeInPages == 1) MmPagedPoolInfo.PagedPoolHint = i + 1;
628
629 //
630 // Update the end bitmap so we know the bounds of this allocation when
631 // the time comes to free it
632 //
633 EndAllocation = i + SizeInPages - 1;
635
636 //
637 // Now we can release the lock (it mainly protects the bitmap)
638 //
640
641 //
642 // Now figure out where this allocation starts
643 //
644 BaseVa = (PVOID)((ULONG_PTR)MmPagedPoolStart + (i << PAGE_SHIFT));
645
646 //
647 // Flush the TLB
648 //
650
651 /* Setup a demand-zero writable PTE */
653
654 //
655 // Find the first and last PTE, then loop them all
656 //
657 PointerPte = MiAddressToPte(BaseVa);
658 StartPte = PointerPte + SizeInPages;
659 do
660 {
661 //
662 // Write the demand zero PTE and keep going
663 //
664 MI_WRITE_INVALID_PTE(PointerPte, TempPte);
665 } while (++PointerPte < StartPte);
666
667 //
668 // Return the allocation address to the caller
669 //
670 return BaseVa;
671 }
672
673 //
674 // If only one page is being requested, try to grab it from the S-LIST
675 //
676 if ((SizeInPages == 1) && (ExQueryDepthSList(&MiNonPagedPoolSListHead)))
677 {
679 if (BaseVa) return BaseVa;
680 }
681
682 //
683 // Allocations of less than 4 pages go into their individual buckets
684 //
685 i = min(SizeInPages, MI_MAX_FREE_PAGE_LISTS) - 1;
686
687 //
688 // Loop through all the free page lists based on the page index
689 //
690 NextHead = &MmNonPagedPoolFreeListHead[i];
692
693 //
694 // Acquire the nonpaged pool lock
695 //
697 do
698 {
699 //
700 // Now loop through all the free page entries in this given list
701 //
702 NextEntry = NextHead->Flink;
703 while (NextEntry != NextHead)
704 {
705 /* Is freed non paged pool enabled */
707 {
708 /* We need to be able to touch this page, unprotect it */
709 MiUnProtectFreeNonPagedPool(NextEntry, 0);
710 }
711
712 //
713 // Grab the entry and see if it can handle our allocation
714 //
715 FreeEntry = CONTAINING_RECORD(NextEntry, MMFREE_POOL_ENTRY, List);
717 if (FreeEntry->Size >= SizeInPages)
718 {
719 //
720 // It does, so consume the pages from here
721 //
722 FreeEntry->Size -= SizeInPages;
723
724 //
725 // The allocation will begin in this free page area
726 //
727 BaseVa = (PVOID)((ULONG_PTR)FreeEntry +
728 (FreeEntry->Size << PAGE_SHIFT));
729
730 /* Remove the item from the list, depending if pool is protected */
733 else
734 RemoveEntryList(&FreeEntry->List);
735
736 //
737 // However, check if its' still got space left
738 //
739 if (FreeEntry->Size != 0)
740 {
741 /* Check which list to insert this entry into */
742 i = min(FreeEntry->Size, MI_MAX_FREE_PAGE_LISTS) - 1;
743
744 /* Insert the entry into the free list head, check for prot. pool */
747 else
749
750 /* Is freed non paged pool protected? */
752 {
753 /* Protect the freed pool! */
754 MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
755 }
756 }
757
758 //
759 // Grab the PTE for this allocation
760 //
761 PointerPte = MiAddressToPte(BaseVa);
762 ASSERT(PointerPte->u.Hard.Valid == 1);
763
764 //
765 // Grab the PFN NextEntry and index
766 //
767 Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
768
769 //
770 // Now mark it as the beginning of an allocation
771 //
772 ASSERT(Pfn1->u3.e1.StartOfAllocation == 0);
773 Pfn1->u3.e1.StartOfAllocation = 1;
774
775 /* Mark it as special pool if needed */
776 ASSERT(Pfn1->u4.VerifierAllocation == 0);
778 {
779 Pfn1->u4.VerifierAllocation = 1;
780 }
781
782 //
783 // Check if the allocation is larger than one page
784 //
785 if (SizeInPages != 1)
786 {
787 //
788 // Navigate to the last PFN entry and PTE
789 //
790 PointerPte += SizeInPages - 1;
791 ASSERT(PointerPte->u.Hard.Valid == 1);
792 Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
793 }
794
795 //
796 // Mark this PFN as the last (might be the same as the first)
797 //
798 ASSERT(Pfn1->u3.e1.EndOfAllocation == 0);
799 Pfn1->u3.e1.EndOfAllocation = 1;
800
801 //
802 // Release the nonpaged pool lock, and return the allocation
803 //
805 return BaseVa;
806 }
807
808 //
809 // Try the next free page entry
810 //
811 NextEntry = FreeEntry->List.Flink;
812
813 /* Is freed non paged pool protected? */
815 {
816 /* Protect the freed pool! */
817 MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
818 }
819 }
820 } while (++NextHead < LastHead);
821
822 //
823 // If we got here, we're out of space.
824 // Start by releasing the lock
825 //
827
828 //
829 // Allocate some system PTEs
830 //
831 StartPte = MiReserveSystemPtes(SizeInPages, NonPagedPoolExpansion);
832 PointerPte = StartPte;
833 if (StartPte == NULL)
834 {
835 //
836 // Ran out of memory
837 //
838 DPRINT("Out of NP Expansion Pool\n");
839 return NULL;
840 }
841
842 //
843 // Acquire the pool lock now
844 //
846
847 //
848 // Lock the PFN database too
849 //
850 MiAcquirePfnLockAtDpcLevel();
851
852 /* Check that we have enough available pages for this request */
853 if (MmAvailablePages < SizeInPages)
854 {
855 MiReleasePfnLockFromDpcLevel();
857
858 MiReleaseSystemPtes(StartPte, SizeInPages, NonPagedPoolExpansion);
859
860 DPRINT1("OUT OF AVAILABLE PAGES! Required %lu, Available %lu\n", SizeInPages, MmAvailablePages);
861
862 return NULL;
863 }
864
865 //
866 // Loop the pages
867 //
869 do
870 {
871 /* Allocate a page */
873 MI_SET_PROCESS2("Kernel");
874 PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
875
876 /* Get the PFN entry for it and fill it out */
877 Pfn1 = MiGetPfnEntry(PageFrameNumber);
878 Pfn1->u3.e2.ReferenceCount = 1;
879 Pfn1->u2.ShareCount = 1;
880 Pfn1->PteAddress = PointerPte;
882 Pfn1->u4.VerifierAllocation = 0;
883
884 /* Write the PTE for it */
885 TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
886 MI_WRITE_VALID_PTE(PointerPte++, TempPte);
887 } while (--SizeInPages > 0);
888
889 //
890 // This is the last page
891 //
892 Pfn1->u3.e1.EndOfAllocation = 1;
893
894 //
895 // Get the first page and mark it as such
896 //
897 Pfn1 = MiGetPfnEntry(StartPte->u.Hard.PageFrameNumber);
898 Pfn1->u3.e1.StartOfAllocation = 1;
899
900 /* Mark it as a verifier allocation if needed */
901 ASSERT(Pfn1->u4.VerifierAllocation == 0);
903
904 //
905 // Release the PFN and nonpaged pool lock
906 //
907 MiReleasePfnLockFromDpcLevel();
909
910 //
911 // Return the address
912 //
913 return MiPteToAddress(StartPte);
914}
915
916ULONG
917NTAPI
919{
920 PMMPTE PointerPte, StartPte;
921 PMMPFN Pfn1, StartPfn;
922 PFN_COUNT FreePages, NumberOfPages;
924 PMMFREE_POOL_ENTRY FreeEntry, NextEntry, LastEntry;
925 ULONG i, End;
927
928 //
929 // Handle paged pool
930 //
931 if ((StartingVa >= MmPagedPoolStart) && (StartingVa <= MmPagedPoolEnd))
932 {
933 //
934 // Calculate the offset from the beginning of paged pool, and convert it
935 // into pages
936 //
938 i = (ULONG)(Offset >> PAGE_SHIFT);
939 End = i;
940
941 //
942 // Now use the end bitmap to scan until we find a set bit, meaning that
943 // this allocation finishes here
944 //
946
947 //
948 // Now calculate the total number of pages this allocation spans. If it's
949 // only one page, add it to the S-LIST instead of freeing it
950 //
951 NumberOfPages = End - i + 1;
952 if ((NumberOfPages == 1) &&
954 {
956 return 1;
957 }
958
959 /* Delete the actual pages */
961 FreePages = MiDeleteSystemPageableVm(PointerPte, NumberOfPages, 0, NULL);
962 ASSERT(FreePages == NumberOfPages);
963
964 //
965 // Acquire the paged pool lock
966 //
968
969 //
970 // Clear the allocation and free bits
971 //
974
975 //
976 // Update the hint if we need to
977 //
979
980 //
981 // Release the lock protecting the bitmaps
982 //
984
985 //
986 // And finally return the number of pages freed
987 //
988 return NumberOfPages;
989 }
990
991 //
992 // Get the first PTE and its corresponding PFN entry. If this is also the
993 // last PTE, meaning that this allocation was only for one page, push it into
994 // the S-LIST instead of freeing it
995 //
996 StartPte = PointerPte = MiAddressToPte(StartingVa);
997 StartPfn = Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
998 if ((Pfn1->u3.e1.EndOfAllocation == 1) &&
1000 {
1002 return 1;
1003 }
1004
1005 //
1006 // Loop until we find the last PTE
1007 //
1008 while (Pfn1->u3.e1.EndOfAllocation == 0)
1009 {
1010 //
1011 // Keep going
1012 //
1013 PointerPte++;
1014 Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1015 }
1016
1017 //
1018 // Now we know how many pages we have
1019 //
1020 NumberOfPages = (PFN_COUNT)(PointerPte - StartPte + 1);
1021
1022 //
1023 // Acquire the nonpaged pool lock
1024 //
1026
1027 //
1028 // Mark the first and last PTEs as not part of an allocation anymore
1029 //
1030 StartPfn->u3.e1.StartOfAllocation = 0;
1031 Pfn1->u3.e1.EndOfAllocation = 0;
1032
1033 //
1034 // Assume we will free as many pages as the allocation was
1035 //
1036 FreePages = NumberOfPages;
1037
1038 //
1039 // Peek one page past the end of the allocation
1040 //
1041 PointerPte++;
1042
1043 //
1044 // Guard against going past initial nonpaged pool
1045 //
1047 {
1048 //
1049 // This page is on the outskirts of initial nonpaged pool, so ignore it
1050 //
1051 Pfn1 = NULL;
1052 }
1053 else
1054 {
1055 /* Sanity check */
1056 ASSERT((ULONG_PTR)StartingVa + NumberOfPages <= (ULONG_PTR)MmNonPagedPoolEnd);
1057
1058 /* Check if protected pool is enabled */
1060 {
1061 /* The freed block will be merged, it must be made accessible */
1063 }
1064
1065 //
1066 // Otherwise, our entire allocation must've fit within the initial non
1067 // paged pool, or the expansion nonpaged pool, so get the PFN entry of
1068 // the next allocation
1069 //
1070 if (PointerPte->u.Hard.Valid == 1)
1071 {
1072 //
1073 // It's either expansion or initial: get the PFN entry
1074 //
1075 Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1076 }
1077 else
1078 {
1079 //
1080 // This means we've reached the guard page that protects the end of
1081 // the expansion nonpaged pool
1082 //
1083 Pfn1 = NULL;
1084 }
1085
1086 }
1087
1088 //
1089 // Check if this allocation actually exists
1090 //
1091 if ((Pfn1) && (Pfn1->u3.e1.StartOfAllocation == 0))
1092 {
1093 //
1094 // It doesn't, so we should actually locate a free entry descriptor
1095 //
1096 FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)StartingVa +
1097 (NumberOfPages << PAGE_SHIFT));
1099 ASSERT(FreeEntry->Owner == FreeEntry);
1100
1101 /* Consume this entry's pages */
1102 FreePages += FreeEntry->Size;
1103
1104 /* Remove the item from the list, depending if pool is protected */
1107 else
1108 RemoveEntryList(&FreeEntry->List);
1109 }
1110
1111 //
1112 // Now get the official free entry we'll create for the caller's allocation
1113 //
1114 FreeEntry = StartingVa;
1115
1116 //
1117 // Check if the our allocation is the very first page
1118 //
1120 {
1121 //
1122 // Then we can't do anything or we'll risk underflowing
1123 //
1124 Pfn1 = NULL;
1125 }
1126 else
1127 {
1128 //
1129 // Otherwise, get the PTE for the page right before our allocation
1130 //
1131 PointerPte -= NumberOfPages + 1;
1132
1133 /* Check if protected pool is enabled */
1135 {
1136 /* The freed block will be merged, it must be made accessible */
1138 }
1139
1140 /* Check if this is valid pool, or a guard page */
1141 if (PointerPte->u.Hard.Valid == 1)
1142 {
1143 //
1144 // It's either expansion or initial nonpaged pool, get the PFN entry
1145 //
1146 Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
1147 }
1148 else
1149 {
1150 //
1151 // We must've reached the guard page, so don't risk touching it
1152 //
1153 Pfn1 = NULL;
1154 }
1155 }
1156
1157 //
1158 // Check if there is a valid PFN entry for the page before the allocation
1159 // and then check if this page was actually the end of an allocation.
1160 // If it wasn't, then we know for sure it's a free page
1161 //
1162 if ((Pfn1) && (Pfn1->u3.e1.EndOfAllocation == 0))
1163 {
1164 //
1165 // Get the free entry descriptor for that given page range
1166 //
1167 FreeEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)StartingVa - PAGE_SIZE);
1169 FreeEntry = FreeEntry->Owner;
1170
1171 /* Check if protected pool is enabled */
1173 {
1174 /* The freed block will be merged, it must be made accessible */
1175 MiUnProtectFreeNonPagedPool(FreeEntry, 0);
1176 }
1177
1178 //
1179 // Check if the entry is small enough (1-3 pages) to be indexed on a free list
1180 // If it is, we'll want to re-insert it, since we're about to
1181 // collapse our pages on top of it, which will change its count
1182 //
1183 if (FreeEntry->Size < MI_MAX_FREE_PAGE_LISTS)
1184 {
1185 /* Remove the item from the list, depending if pool is protected */
1188 else
1189 RemoveEntryList(&FreeEntry->List);
1190
1191 //
1192 // Update its size
1193 //
1194 FreeEntry->Size += FreePages;
1195
1196 //
1197 // And now find the new appropriate list to place it in
1198 //
1199 i = min(FreeEntry->Size, MI_MAX_FREE_PAGE_LISTS) - 1;
1200
1201 /* Insert the entry into the free list head, check for prot. pool */
1204 else
1206 }
1207 else
1208 {
1209 //
1210 // Otherwise, just combine our free pages into this entry
1211 //
1212 FreeEntry->Size += FreePages;
1213 }
1214 }
1215
1216 //
1217 // Check if we were unable to do any compaction, and we'll stick with this
1218 //
1219 if (FreeEntry == StartingVa)
1220 {
1221 //
1222 // Well, now we are a free entry. At worse we just have our newly freed
1223 // pages, at best we have our pages plus whatever entry came after us
1224 //
1225 FreeEntry->Size = FreePages;
1226
1227 //
1228 // Find the appropriate list we should be on
1229 //
1230 i = min(FreeEntry->Size, MI_MAX_FREE_PAGE_LISTS) - 1;
1231
1232 /* Insert the entry into the free list head, check for prot. pool */
1235 else
1237 }
1238
1239 //
1240 // Just a sanity check
1241 //
1242 ASSERT(FreePages != 0);
1243
1244 //
1245 // Get all the pages between our allocation and its end. These will all now
1246 // become free page chunks.
1247 //
1248 NextEntry = StartingVa;
1249 LastEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + (FreePages << PAGE_SHIFT));
1250 do
1251 {
1252 //
1253 // Link back to the parent free entry, and keep going
1254 //
1255 NextEntry->Owner = FreeEntry;
1256 NextEntry->Signature = MM_FREE_POOL_SIGNATURE;
1257 NextEntry = (PMMFREE_POOL_ENTRY)((ULONG_PTR)NextEntry + PAGE_SIZE);
1258 } while (NextEntry != LastEntry);
1259
1260 /* Is freed non paged pool protected? */
1262 {
1263 /* Protect the freed pool! */
1264 MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
1265 }
1266
1267 //
1268 // We're done, release the lock and let the caller know how much we freed
1269 //
1271 return NumberOfPages;
1272}
1273
1275NTAPI
1277{
1278 PMMPTE PointerPte, LastPte;
1279 PMMPDE PointerPde, LastPde;
1280 PFN_NUMBER PageFrameIndex, PdeCount;
1281 PPOOL_DESCRIPTOR PoolDescriptor;
1282 PMM_SESSION_SPACE SessionGlobal;
1283 PMM_PAGED_POOL_INFO PagedPoolInfo;
1285 ULONG Index, PoolSize, BitmapSize;
1286 PAGED_CODE();
1287
1288 /* Lock session pool */
1289 SessionGlobal = MmSessionSpace->GlobalVirtualAddress;
1291
1292 /* Setup a valid pool descriptor */
1293 PoolDescriptor = &MmSessionSpace->PagedPool;
1294 ExInitializePoolDescriptor(PoolDescriptor,
1296 0,
1297 0,
1298 &SessionGlobal->PagedPoolMutex);
1299
1300 /* Setup the pool addresses */
1303 DPRINT1("Session Pool Start: 0x%p End: 0x%p\n",
1305
1306 /* Reset all the counters */
1307 PagedPoolInfo = &MmSessionSpace->PagedPoolInfo;
1308 PagedPoolInfo->PagedPoolCommit = 0;
1309 PagedPoolInfo->PagedPoolHint = 0;
1310 PagedPoolInfo->AllocatedPagedPool = 0;
1311
1312 /* Compute PDE and PTE addresses */
1317
1318 /* Write them down */
1319 MmSessionSpace->PagedPoolBasePde = PointerPde;
1320 PagedPoolInfo->FirstPteForPagedPool = PointerPte;
1321 PagedPoolInfo->LastPteForPagedPool = LastPte;
1322 PagedPoolInfo->NextPdeForPagedPoolExpansion = PointerPde + 1;
1323
1324 /* Zero the PDEs */
1325 PdeCount = LastPde - PointerPde;
1326 RtlZeroMemory(PointerPde, (PdeCount + 1) * sizeof(MMPTE));
1327
1328 /* Initialize the PFN for the PDE */
1329 Status = MiInitializeAndChargePfn(&PageFrameIndex,
1330 PointerPde,
1332 TRUE);
1334
1335 /* Initialize the first page table */
1337 Index >>= 22;
1338#ifndef _M_AMD64 // FIXME
1340 MmSessionSpace->PageTables[Index] = *PointerPde;
1341#endif
1342
1343 /* Bump up counters */
1346
1347 /* Compute the size of the pool in pages, and of the bitmap for it */
1348 PoolSize = MmSessionPoolSize >> PAGE_SHIFT;
1349 BitmapSize = sizeof(RTL_BITMAP) + ((PoolSize + 31) / 32) * sizeof(ULONG);
1350
1351 /* Allocate and initialize the bitmap to track allocations */
1353 BitmapSize,
1354 TAG_MM);
1355 ASSERT(PagedPoolInfo->PagedPoolAllocationMap != NULL);
1357 (PULONG)(PagedPoolInfo->PagedPoolAllocationMap + 1),
1358 PoolSize);
1359
1360 /* Set all bits, but clear the first page table's worth */
1361 RtlSetAllBits(PagedPoolInfo->PagedPoolAllocationMap);
1363
1364 /* Allocate and initialize the bitmap to track free space */
1366 BitmapSize,
1367 TAG_MM);
1368 ASSERT(PagedPoolInfo->EndOfPagedPoolBitmap != NULL);
1370 (PULONG)(PagedPoolInfo->EndOfPagedPoolBitmap + 1),
1371 PoolSize);
1372
1373 /* Clear all the bits and return success */
1374 RtlClearAllBits(PagedPoolInfo->EndOfPagedPoolBitmap);
1375 return STATUS_SUCCESS;
1376}
1377
1405BOOLEAN
1406NTAPI
1407MmRaisePoolQuota(
1411{
1412 /*
1413 * We must be in dispatch level interrupt here
1414 * as we should be under a spin lock at this point.
1415 */
1417
1418 switch (PoolType)
1419 {
1420 case NonPagedPool:
1421 {
1422 /*
1423 * When concerning with a raise (charge) of quota
1424 * in a non paged pool scenario, make sure that
1425 * we've got at least 200 pages necessary to provide.
1426 */
1428 {
1429 DPRINT1("MmRaisePoolQuota(): Not enough pages available (current pages -- %lu)\n", MmAvailablePages);
1430 return FALSE;
1431 }
1432
1433 /*
1434 * Check if there's at least some space available
1435 * in the non paged pool area.
1436 */
1438 {
1439 /* There's too much allocated space, bail out */
1440 DPRINT1("MmRaisePoolQuota(): Failed to increase pool quota, not enough non paged pool space (current size -- %lu || allocated size -- %lu)\n",
1442 return FALSE;
1443 }
1444
1445 /* Do we have enough resident pages to increase our quota? */
1447 {
1448 DPRINT1("MmRaisePoolQuota(): Failed to increase pool quota, not enough resident pages available (current available pages -- %lu)\n",
1450 return FALSE;
1451 }
1452
1453 /*
1454 * Raise the non paged pool quota indicator and set
1455 * up new maximum limit of quota for the process.
1456 */
1459 DPRINT("MmRaisePoolQuota(): Non paged pool quota increased (before -- %lu || after -- %lu)\n", CurrentMaxQuota, NewMaxQuota);
1460 return TRUE;
1461 }
1462
1463 case PagedPool:
1464 {
1465 /*
1466 * Before raising the quota limit of a paged quota
1467 * pool, make sure we've got enough space that is available.
1468 * On Windows it seems it wants to check for at least 1 MB of space
1469 * needed so that it would be possible to raise the paged pool quota.
1470 */
1472 {
1473 /* We haven't gotten enough space, bail out */
1474 DPRINT1("MmRaisePoolQuota(): Failed to increase pool quota, not enough paged pool space (current size -- %lu || allocated size -- %lu)\n",
1476 return FALSE;
1477 }
1478
1479 /*
1480 * Raise the paged pool quota indicator and set
1481 * up new maximum limit of quota for the process.
1482 */
1485 DPRINT("MmRaisePoolQuota(): Paged pool quota increased (before -- %lu || after -- %lu)\n", CurrentMaxQuota, NewMaxQuota);
1486 return TRUE;
1487 }
1488
1489 /* Only NonPagedPool and PagedPool are used */
1491 }
1492}
1493
1516VOID
1517NTAPI
1518MmReturnPoolQuota(
1521{
1522 /*
1523 * We must be in dispatch level interrupt here
1524 * as we should be under a spin lock at this point.
1525 */
1527
1528 switch (PoolType)
1529 {
1530 case NonPagedPool:
1531 {
1532 /* This is a non paged pool type, decrease the non paged quota */
1535 DPRINT("MmReturnPoolQuota(): Non paged pool quota returned (current size -- %lu)\n", MmTotalNonPagedPoolQuota);
1536 break;
1537 }
1538
1539 case PagedPool:
1540 {
1541 /* This is a paged pool type, decrease the paged quota */
1544 DPRINT("MmReturnPoolQuota(): Paged pool quota returned (current size -- %lu)\n", MmTotalPagedPoolQuota);
1545 break;
1546 }
1547
1548 /* Only NonPagedPool and PagedPool are used */
1550 }
1551}
1552
1553/* PUBLIC FUNCTIONS ***********************************************************/
1554
1573PVOID
1574NTAPI
1575MmAllocateMappingAddress(
1578{
1579 PFN_NUMBER SizeInPages;
1580 PMMPTE PointerPte;
1581 MMPTE TempPte;
1582
1583 /* Fast exit if PoolTag is NULL */
1584 if (!PoolTag)
1585 return NULL;
1586
1587 /* How many PTEs does the caller want? */
1588 SizeInPages = BYTES_TO_PAGES(NumberOfBytes);
1589 if (SizeInPages == 0)
1590 {
1591 KeBugCheckEx(SYSTEM_PTE_MISUSE,
1592 PTE_MAPPING_NONE, /* Requested 0 mappings */
1593 SizeInPages,
1594 PoolTag,
1596 }
1597
1598 /* We need two extra PTEs to store size and pool tag in */
1599 SizeInPages += 2;
1600
1601 /* Reserve our PTEs */
1602 PointerPte = MiReserveSystemPtes(SizeInPages, SystemPteSpace);
1603 if (!PointerPte)
1604 {
1605 /* Failed to reserve PTEs */
1606 DPRINT1("Failed to reserve system PTEs\n");
1607 return NULL;
1608 }
1609
1610 ASSERT(SizeInPages <= MM_EMPTY_PTE_LIST);
1611 TempPte.u.Long = 0;
1612 TempPte.u.List.NextEntry = SizeInPages;
1613 MI_WRITE_INVALID_PTE(&PointerPte[0], TempPte);
1614 TempPte.u.Long = PoolTag;
1615 TempPte.u.Hard.Valid = 0;
1616 MI_WRITE_INVALID_PTE(&PointerPte[1], TempPte);
1617 return MiPteToAddress(PointerPte + 2);
1618}
1619
1638VOID
1639NTAPI
1640MmFreeMappingAddress(
1643{
1644 PMMPTE PointerPte;
1645 MMPTE TempPte;
1646 PFN_NUMBER SizeInPages;
1647 PFN_NUMBER i;
1648
1649 /* Get the first PTE we reserved */
1650 PointerPte = MiAddressToPte(BaseAddress) - 2;
1651
1652 /* Verify that the pool tag matches */
1653 TempPte.u.Long = PoolTag;
1654 TempPte.u.Hard.Valid = 0;
1655 if (PointerPte[1].u.Long != TempPte.u.Long)
1656 {
1657 KeBugCheckEx(SYSTEM_PTE_MISUSE,
1658 PTE_MAPPING_NOT_OWNED, /* Trying to free an address it does not own */
1660 PoolTag,
1661 PointerPte[1].u.Long);
1662 }
1663
1664 /* We must have a size */
1665 SizeInPages = PointerPte[0].u.List.NextEntry;
1666 if (SizeInPages < 3)
1667 {
1668 KeBugCheckEx(SYSTEM_PTE_MISUSE,
1669 PTE_MAPPING_EMPTY, /* Mapping apparently empty */
1671 PoolTag,
1673 }
1674
1675 /* Enumerate all PTEs and make sure they are empty */
1676 for (i = 2; i < SizeInPages; i++)
1677 {
1678 if (PointerPte[i].u.Long != 0)
1679 {
1680 KeBugCheckEx(SYSTEM_PTE_MISUSE,
1681 PTE_MAPPING_RESERVED, /* Mapping address still reserved */
1682 (ULONG_PTR)PointerPte,
1683 PoolTag,
1684 SizeInPages - 2);
1685 }
1686 }
1687
1688 /* Release the PTEs */
1689 MiReleaseSystemPtes(PointerPte, SizeInPages, SystemPteSpace);
1690}
1691
1692/* EOF */
#define PAGED_CODE()
#define CODE_SEG(...)
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
unsigned char BOOLEAN
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define MM_READWRITE
Definition: bootanim.c:19
#define _Requires_lock_held_(lock)
#define RtlClearBits
Definition: dbgbitmap.h:331
#define RtlInitializeBitMap
Definition: dbgbitmap.h:326
#define RtlClearAllBits
Definition: dbgbitmap.h:329
#define RtlClearBit
Definition: dbgbitmap.h:330
#define RtlFindClearBitsAndSet
Definition: dbgbitmap.h:333
#define RtlTestBit
Definition: dbgbitmap.h:347
#define RtlSetAllBits
Definition: dbgbitmap.h:346
#define RTL_BITMAP
Definition: dbgbitmap.h:323
#define RtlSetBit
Definition: dbgbitmap.h:344
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
#define ULONG_PTR
Definition: config.h:101
#define __drv_freesMem(kind)
Definition: driverspecs.h:272
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
VOID NTAPI ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor, IN POOL_TYPE PoolType, IN ULONG PoolIndex, IN ULONG Threshold, IN PVOID PoolLock)
Definition: expool.c:969
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define InterlockedIncrementSizeT(a)
Definition: interlocked.h:220
#define _ReturnAddress()
Definition: intrin_arm.h:35
@ SystemPteSpace
Definition: miarm.h:417
@ NonPagedPoolExpansion
Definition: miarm.h:418
VOID NTAPI MiInitializeSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE PoolType)
Definition: syspte.c:388
FORCEINLINE BOOLEAN MI_IS_PHYSICAL_ADDRESS(IN PVOID Address)
Definition: miarm.h:959
PVOID MmPagedPoolStart
Definition: miarm.h:588
#define PTE_MAPPING_EMPTY
Definition: miarm.h:164
#define PTE_MAPPING_NOT_OWNED
Definition: miarm.h:163
#define _1GB
Definition: miarm.h:20
PVOID MmNonPagedPoolEnd
Definition: mminit.c:99
PFN_NUMBER MiLowPagedPoolThreshold
Definition: mminit.c:302
PMM_SESSION_SPACE MmSessionSpace
Definition: session.c:21
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:246
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
VOID NTAPI MiReleaseSystemPtes(IN PMMPTE StartingPte, IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:264
#define PTE_MAPPING_NONE
Definition: miarm.h:162
#define MI_MAKE_SOFTWARE_PTE(p, x)
Definition: miarm.h:203
PFN_NUMBER MmMaximumNonPagedPoolInPages
Definition: mminit.c:30
NTSTATUS NTAPI MiInitializeAndChargePfn(OUT PPFN_NUMBER PageFrameIndex, IN PMMPDE PointerPde, IN PFN_NUMBER ContainingPageFrame, IN BOOLEAN SessionAllocation)
Definition: pfnlist.c:1101
PFN_NUMBER MiHighPagedPoolThreshold
Definition: mminit.c:303
VOID NTAPI MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex, IN PVOID PteAddress, IN PFN_NUMBER PteFrame)
Definition: pfnlist.c:1301
FORCEINLINE VOID MI_WRITE_VALID_PDE(IN PMMPDE PointerPde, IN MMPDE TempPde)
Definition: miarm.h:1031
PKEVENT MiLowNonPagedPoolEvent
Definition: mminit.c:296
#define _1MB
Definition: miarm.h:19
FORCEINLINE VOID MI_WRITE_INVALID_PTE(IN PMMPTE PointerPte, IN MMPTE InvalidPte)
Definition: miarm.h:1006
PMMPTE NTAPI MiReserveSystemPtes(IN ULONG NumberOfPtes, IN MMSYSTEM_PTE_POOL_TYPE SystemPtePoolType)
Definition: syspte.c:246
#define PTE_MAPPING_RESERVED
Definition: miarm.h:165
#define SYSTEM_PD_SIZE
Definition: miarm.h:32
PFN_NUMBER MiLowNonPagedPoolThreshold
Definition: mminit.c:304
PFN_NUMBER MiHighNonPagedPoolThreshold
Definition: mminit.c:305
PKEVENT MiHighPagedPoolEvent
Definition: mminit.c:295
FORCEINLINE VOID MI_WRITE_VALID_PTE(IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: miarm.h:973
PFN_COUNT NTAPI MiDeleteSystemPageableVm(IN PMMPTE PointerPte, IN PFN_NUMBER PageCount, IN ULONG Flags, OUT PPFN_NUMBER ValidPages)
Definition: virtual.c:275
PKEVENT MiLowPagedPoolEvent
Definition: mminit.c:294
PFN_NUMBER MmSizeOfPagedPoolInPages
Definition: mminit.c:111
PKEVENT MiHighNonPagedPoolEvent
Definition: mminit.c:297
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define MiAddressToPde(x)
Definition: mmx86.c:20
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
@ ActiveAndValid
Definition: mmtypes.h:159
#define _Ret_maybenull_
Definition: no_sal2.h:328
#define _Post_invalid_
Definition: no_sal2.h:524
#define _Must_inspect_result_
Definition: no_sal2.h:62
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define DEFAULT_UNREACHABLE
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define MM_EMPTY_PTE_LIST
Definition: mm.h:87
#define MI_MAX_FREE_PAGE_LISTS
Definition: mm.h:80
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define MiPteToPde(_Pte)
Definition: mm.h:121
#define PTE_PER_PAGE
Definition: mm.h:20
#define MiPteToAddress(_Pte)
Definition: mm.h:116
#define PDE_PER_PAGE
Definition: mm.h:21
#define MiPdeToPte(_Pde)
Definition: mm.h:120
struct _MMFREE_POOL_ENTRY * PMMFREE_POOL_ENTRY
#define VERIFIER_POOL_MASK
Definition: mm.h:123
PFN_NUMBER MmResidentAvailablePages
Definition: freelist.c:27
_In_ SIZE_T _Out_ PSIZE_T NewMaxQuota
Definition: mm.h:667
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1047
#define MI_SET_PROCESS2(x)
Definition: mm.h:319
@ MI_USAGE_PAGED_POOL
Definition: mm.h:325
#define MI_QUOTA_NON_PAGED_NEEDED_PAGES
Definition: mm.h:62
#define MI_CHARGE_PAGED_POOL_QUOTA
Definition: mm.h:64
_In_ SIZE_T CurrentMaxQuota
Definition: mm.h:665
PFN_COUNT MmNumberOfPhysicalPages
Definition: init.c:48
FORCEINLINE PFN_NUMBER MiGetPfnEntryIndex(IN PMMPFN Pfn1)
Definition: mm.h:1067
#define MI_NON_PAGED_QUOTA_MIN_RESIDENT_PAGES
Definition: mm.h:63
#define MI_SET_USAGE(x)
Definition: mm.h:317
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
#define MI_CHARGE_NON_PAGED_POOL_QUOTA
Definition: mm.h:65
#define MM_FREE_POOL_SIGNATURE
Definition: mm.h:481
_In_ SIZE_T QuotaToReturn
Definition: mm.h:675
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:652
PMMPDE MmSystemPagePtes
Definition: init.c:41
ULONG MmMaximumNonPagedPoolInBytes
Definition: init.c:22
ULONG MmSizeOfNonPagedPoolInBytes
Definition: init.c:21
PVOID MiSessionPoolStart
Definition: init.c:32
ULONG MmSessionPoolSize
Definition: init.c:36
PVOID MmNonPagedPoolExpansionStart
Definition: init.c:25
PVOID MmSessionBase
Definition: init.c:33
PVOID MmNonPagedPoolStart
Definition: init.c:24
PVOID MiSessionPoolEnd
Definition: init.c:31
PFN_NUMBER MmSystemPageDirectory[PPE_PER_PAGE]
Definition: init.c:40
PVOID MmPagedPoolEnd
Definition: init.c:26
ULONG MiNonPagedPoolSListMaximum
Definition: pool.c:33
PFN_NUMBER MiStartOfInitialPoolFrame
Definition: pool.c:23
PFN_COUNT MmNumberOfFreeNonPagedPool
Definition: pool.c:21
SIZE_T MmTotalPagedPoolQuota
Definition: pool.c:28
PFN_COUNT MiExpansionPoolPagesInitialCharge
Definition: pool.c:21
VOID NTAPI MiProtectedPoolRemoveEntryList(IN PLIST_ENTRY Entry)
Definition: pool.c:168
VOID NTAPI MiInitializePoolEvents(VOID)
Definition: pool.c:203
ULONG MiPagedPoolSListMaximum
Definition: pool.c:35
SIZE_T MmTotalNonPagedPoolQuota
Definition: pool.c:27
VOID NTAPI MiInitializeNonPagedPool(VOID)
Definition: pool.c:278
BOOLEAN MmProtectFreedNonPagedPool
Definition: pool.c:31
KGUARDED_MUTEX MmPagedPoolMutex
Definition: pool.c:24
PVOID NTAPI MiAllocatePoolPages(IN POOL_TYPE PoolType, IN SIZE_T SizeInBytes)
Definition: pool.c:422
FORCEINLINE VOID MiProtectedPoolUnProtectLinks(IN PLIST_ENTRY Links, OUT PVOID *PoolFlink, OUT PVOID *PoolBlink)
Definition: pool.c:105
MM_PAGED_POOL_INFO MmPagedPoolInfo
Definition: pool.c:25
VOID NTAPI MiInitializeNonPagedPoolThresholds(VOID)
Definition: pool.c:186
SLIST_HEADER MiNonPagedPoolSListHead
Definition: pool.c:32
VOID NTAPI MiProtectFreeNonPagedPool(IN PVOID VirtualAddress, IN ULONG PageCount)
Definition: pool.c:41
PFN_NUMBER MiEndOfInitialPoolFrame
Definition: pool.c:23
LIST_ENTRY MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS]
Definition: pool.c:20
FORCEINLINE VOID MiProtectedPoolProtectLinks(IN PVOID PoolFlink, IN PVOID PoolBlink)
Definition: pool.c:140
SIZE_T MmAllocatedNonPagedPool
Definition: pool.c:26
ULONG MmSpecialPoolTag
Definition: pool.c:29
POOL_TYPE NTAPI MmDeterminePoolType(IN PVOID PoolAddress)
Definition: pool.c:408
SLIST_HEADER MiPagedPoolSListHead
Definition: pool.c:34
NTSTATUS NTAPI MiInitializeSessionPool(VOID)
Definition: pool.c:1276
PVOID MmNonPagedPoolEnd0
Definition: pool.c:22
ULONG MmConsumedPoolPercentage
Definition: pool.c:30
BOOLEAN NTAPI MiUnProtectFreeNonPagedPool(IN PVOID VirtualAddress, IN ULONG PageCount)
Definition: pool.c:70
ULONG NTAPI MiFreePoolPages(IN PVOID StartingVa)
Definition: pool.c:918
VOID NTAPI MiProtectedPoolInsertList(IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry, IN BOOLEAN Critical)
Definition: pool.c:150
MMPTE ValidKernelPte
Definition: init.c:29
MMPTE ValidKernelPde
Definition: init.c:28
static KSPIN_LOCK PspQuotaLock
Definition: quota.c:18
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
ULONG PFN_NUMBER
Definition: ke.h:9
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
base of all file and directory entries
Definition: entries.h:83
ULONG PageFrameNumber
Definition: mmtypes.h:74
ULONG PageFrameNumber
Definition: mmtypes.h:109
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: mm.h:473
ULONG Signature
Definition: mm.h:476
struct _MMFREE_POOL_ENTRY * Owner
Definition: mm.h:477
PFN_COUNT Size
Definition: mm.h:475
LIST_ENTRY List
Definition: mm.h:474
USHORT PageLocation
Definition: mm.h:365
Definition: mm.h:374
PMMPTE PteAddress
Definition: mm.h:386
union _MMPFN::@1803 u2
struct _MMPFN::@1804::@1810 e2
union _MMPFN::@1807 u4
MMPFNENTRY e1
Definition: mm.h:397
ULONG_PTR VerifierAllocation
Definition: mm.h:420
ULONG_PTR ShareCount
Definition: mm.h:390
union _MMPFN::@1804 u3
ULONG64 Valid
Definition: mmtypes.h:150
ULONG64 PageFrameNumber
Definition: mmtypes.h:171
ULONG64 NextEntry
Definition: mmtypes.h:145
MMPTE_LIST List
Definition: mmtypes.h:222
union _MMPTE::@2338 u
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG_PTR Long
Definition: mmtypes.h:215
PMMPTE LastPteForPagedPool
Definition: mm.h:489
SIZE_T AllocatedPagedPool
Definition: mm.h:493
PRTL_BITMAP EndOfPagedPoolBitmap
Definition: mm.h:487
PRTL_BITMAP PagedPoolAllocationMap
Definition: mm.h:486
PMMPDE NextPdeForPagedPoolExpansion
Definition: mm.h:490
PMMPTE FirstPteForPagedPool
Definition: mm.h:488
ULONG PagedPoolHint
Definition: mm.h:491
SIZE_T PagedPoolCommit
Definition: mm.h:492
PFN_NUMBER SessionPageDirectoryIndex
Definition: miarm.h:494
PMMPDE PageTables
Definition: miarm.h:521
KGUARDED_MUTEX PagedPoolMutex
Definition: miarm.h:512
PVOID PagedPoolStart
Definition: miarm.h:497
MM_PAGED_POOL_INFO PagedPoolInfo
Definition: miarm.h:513
struct _MM_SESSION_SPACE * GlobalVirtualAddress
Definition: miarm.h:484
PVOID PagedPoolEnd
Definition: miarm.h:498
SIZE_T CommittedPages
Definition: miarm.h:496
SIZE_T NonPageablePages
Definition: miarm.h:495
POOL_DESCRIPTOR PagedPool
Definition: miarm.h:517
PMMPDE PagedPoolBasePde
Definition: miarm.h:499
#define TAG_MM
Definition: tag.h:113
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
uint32_t * PULONG
Definition: typedefs.h:59
INT POOL_TYPE
Definition: typedefs.h:78
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ _Strict_type_match_ POOL_TYPE PoolType
Definition: wdfdevice.h:3815
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ _Strict_type_match_ POOL_TYPE _In_opt_ ULONG PoolTag
Definition: wdfmemory.h:164
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define FORCEINLINE
Definition: wdftypes.h:67
FORCEINLINE USHORT ExQueryDepthSList(_In_ PSLIST_HEADER SListHead)
Definition: exfuncs.h:153
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:1036
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ PagedPoolSession
Definition: ketypes.h:893
@ LockQueueMmNonPagedPoolLock
Definition: ketypes.h:673
#define BYTES_TO_PAGES(Size)
ULONG PFN_COUNT
Definition: mmtypes.h:102
#define InterlockedPushEntrySList(SListHead, SListEntry)
Definition: rtlfuncs.h:3406
#define InterlockedPopEntrySList(SListHead)
Definition: rtlfuncs.h:3409
FORCEINLINE VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3368