00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "mi.h"
00023
00024 #define MM_LOW_LIMIT 2
00025 #define MM_HIGH_LIMIT 19
00026
00027 KEVENT MmAvailablePagesEventHigh;
00028
00029 ULONG
MmTransitionPrivatePages;
00030 ULONG
MmTransitionSharedPages;
00031
00032 #define MI_TALLY_TRANSITION_PAGE_ADDITION(Pfn) \
00033
if (Pfn->u3.e1.PrototypePte) { \
00034
MmTransitionSharedPages += 1; \
00035
} \
00036
else { \
00037
MmTransitionPrivatePages += 1; \
00038
} \
00039
ASSERT (MmTransitionPrivatePages + MmTransitionSharedPages == MmStandbyPageListHead.Total + MmModifiedPageListHead.Total + MmModifiedNoWritePageListHead.Total);
00040
00041 #define MI_TALLY_TRANSITION_PAGE_REMOVAL(Pfn) \
00042
if (Pfn->u3.e1.PrototypePte) { \
00043
MmTransitionSharedPages -= 1; \
00044
} \
00045
else { \
00046
MmTransitionPrivatePages -= 1; \
00047
} \
00048
ASSERT (MmTransitionPrivatePages + MmTransitionSharedPages == MmStandbyPageListHead.Total + MmModifiedPageListHead.Total + MmModifiedNoWritePageListHead.Total);
00049
00050
VOID
00051
MiRemovePageByColor (
00052 IN PFN_NUMBER Page,
00053 IN ULONG PageColor
00054 );
00055
00056
00057
VOID
00058
FASTCALL
00059 MiInsertPageInList (
00060 IN
PMMPFNLIST ListHead,
00061 IN PFN_NUMBER PageFrameIndex
00062 )
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 {
00091 PFN_NUMBER last;
00092
PMMPFN Pfn1;
00093
PMMPFN Pfn2;
00094 ULONG Color;
00095
00096
MM_PFN_LOCK_ASSERT();
00097
ASSERT ((PageFrameIndex != 0) &&
00098 (PageFrameIndex <=
MmHighestPhysicalPage) &&
00099 (PageFrameIndex >=
MmLowestPhysicalPage));
00100
00101
00102
00103
00104
00105 Pfn1 =
MI_PFN_ELEMENT(PageFrameIndex);
00106
00107
ASSERT (Pfn1->
u3.e1.LockCharged == 0);
00108
00109
PERFINFO_INSERTINLIST(PageFrameIndex, ListHead);
00110
00111
#if DBG
00112
if (MmDebug &
MM_DBG_PAGE_REF_COUNT) {
00113
00114
PMMPTE PointerPte;
00115 KIRQL OldIrql = 99;
00116
00117
if ((ListHead->ListName ==
StandbyPageList) ||
00118 (ListHead->ListName ==
ModifiedPageList)) {
00119
00120
if ((Pfn1->
u3.e1.PrototypePte == 1) &&
00121 (
MmIsAddressValid (Pfn1->
PteAddress))) {
00122 PointerPte = Pfn1->
PteAddress;
00123 }
else {
00124
00125
00126
00127
00128
00129
00130 PointerPte =
MiMapPageInHyperSpace (Pfn1->
PteFrame, &OldIrql);
00131 PointerPte = (
PMMPTE)((PCHAR)PointerPte +
00132
MiGetByteOffset(Pfn1->
PteAddress));
00133 }
00134
00135
ASSERT ((
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerPte) == PageFrameIndex) ||
00136 (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte) == PageFrameIndex));
00137
ASSERT (PointerPte->u.Soft.Transition == 1);
00138
ASSERT (PointerPte->u.Soft.Prototype == 0);
00139
if (OldIrql != 99) {
00140
MiUnmapPageInHyperSpace (OldIrql)
00141 }
00142 }
00143 }
00144
#endif
00145
00146
#if PFN_CONSISTENCY
00147
if (ListHead == &
MmFreePageListHead) {
00148
if (Pfn1->
u2.ShareCount != 0) {
00149
KeBugCheckEx (PFN_LIST_CORRUPT,
00150 0x91,
00151 PageFrameIndex,
00152 Pfn1->
u2.ShareCount,
00153 Pfn1->
u3.e2.ReferenceCount);
00154 }
00155 }
00156
else if (ListHead == &
MmZeroedPageListHead) {
00157
if (Pfn1->
u2.ShareCount != 0) {
00158
KeBugCheckEx (PFN_LIST_CORRUPT,
00159 0x92,
00160 PageFrameIndex,
00161 Pfn1->
u2.ShareCount,
00162 Pfn1->
u3.e2.ReferenceCount);
00163 }
00164 }
00165
#endif
00166
00167
#if DBG
00168
if ((ListHead->ListName ==
StandbyPageList) ||
00169 (ListHead->ListName ==
ModifiedPageList)) {
00170
if ((Pfn1->
OriginalPte.
u.Soft.Prototype == 0) &&
00171 (Pfn1->
OriginalPte.
u.Soft.Transition == 1)) {
00172
KeBugCheckEx (MEMORY_MANAGEMENT, 0x8888, 0,0,0);
00173 }
00174 }
00175
#endif
00176
00177
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
00178
00179 ListHead->Total += 1;
00180
00181
00182
00183
00184
00185
00186
00187
if (ListHead == &
MmModifiedPageListHead) {
00188
00189
#if PFN_CONSISTENCY
00190
if (Pfn1->
u2.ShareCount != 0) {
00191
KeBugCheckEx (PFN_LIST_CORRUPT,
00192 0x90,
00193 PageFrameIndex,
00194 Pfn1->
u2.ShareCount,
00195 Pfn1->
u3.e2.ReferenceCount);
00196 }
00197
#endif
00198
00199
if (Pfn1->
OriginalPte.
u.Soft.Prototype == 0) {
00200
00201
00202
00203
00204
00205
00206
00207 ListHead = &
MmModifiedPageListByColor [Pfn1->
u3.e1.PageColor];
00208 ListHead->
Total += 1;
00209
MmTotalPagesForPagingFile += 1;
00210 }
00211
else {
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
if (ListHead->Total -
MmTotalPagesForPagingFile == 1) {
00226
00227
00228
00229
00230
00231
if (
MiTimerPending ==
FALSE) {
00232
MiTimerPending =
TRUE;
00233
00234 (
VOID)
KeSetTimerEx( &
MiModifiedPageWriterTimer,
MiModifiedPageLife, 0, &
MiModifiedPageWriterTimerDpc );
00235 }
00236 }
00237 }
00238 }
00239
else if ((Pfn1->
u3.e1.RemovalRequested == 1) &&
00240 (ListHead->ListName <=
StandbyPageList)) {
00241
00242 ListHead->Total -= 1;
00243
00244
if (ListHead->ListName ==
StandbyPageList) {
00245 Pfn1->
u3.e1.PageLocation =
StandbyPageList;
00246
MiRestoreTransitionPte (PageFrameIndex);
00247 }
00248
00249 ListHead =
MmPageLocationList[
BadPageList];
00250 ListHead->
Total += 1;
00251 }
00252
00253
00254 last = ListHead->Blink;
00255
if (last ==
MM_EMPTY_LIST) {
00256
00257
00258
00259
00260
00261 ListHead->Flink = PageFrameIndex;
00262 }
else {
00263 Pfn2 =
MI_PFN_ELEMENT (last);
00264 Pfn2->
u1.Flink = PageFrameIndex;
00265 }
00266
00267 ListHead->Blink = PageFrameIndex;
00268 Pfn1->
u1.Flink =
MM_EMPTY_LIST;
00269 Pfn1->
u2.Blink = last;
00270 Pfn1->
u3.e1.PageLocation = ListHead->ListName;
00271
00272
00273
00274
00275
00276
00277
00278
00279
if (ListHead->ListName <=
StandbyPageList) {
00280
MmAvailablePages += 1;
00281
00282
00283
00284
00285
00286
00287
if (
MmAvailablePages ==
MM_LOW_LIMIT) {
00288
KeSetEvent (&
MmAvailablePagesEvent, 0,
FALSE);
00289 }
else if (
MmAvailablePages ==
MM_HIGH_LIMIT) {
00290
KeSetEvent (&
MmAvailablePagesEventHigh, 0,
FALSE);
00291 }
00292
00293
if (ListHead->ListName <=
FreePageList) {
00294
00295
ASSERT (Pfn1->
u3.e1.InPageError == 0);
00296
00297
00298
00299
00300
00301
00302 Color =
MI_GET_SECONDARY_COLOR (PageFrameIndex, Pfn1);
00303
ASSERT (Pfn1->
u3.e1.PageColor ==
MI_GET_COLOR_FROM_SECONDARY(Color));
00304
00305
if (
MmFreePagesByColor[ListHead->ListName][Color].
Flink ==
00306
MM_EMPTY_LIST) {
00307
00308
00309
00310
00311
00312
00313
MmFreePagesByColor[ListHead->ListName][Color].
Flink =
00314 PageFrameIndex;
00315
MmFreePagesByColor[ListHead->ListName][Color].
Blink =
00316 (PVOID)Pfn1;
00317 }
else {
00318 Pfn2 = (
PMMPFN)
MmFreePagesByColor[ListHead->ListName][Color].
Blink;
00319 Pfn2->
OriginalPte.
u.Long = PageFrameIndex;
00320
MmFreePagesByColor[ListHead->ListName][Color].
Blink = (PVOID)Pfn1;
00321 }
00322 Pfn1->
OriginalPte.
u.Long =
MM_EMPTY_LIST;
00323
00324
if (ListHead->ListName ==
ZeroedPageList) {
00325
MI_BARRIER_STAMP_ZEROED_PAGE (&Pfn1->
PteFrame);
00326 }
00327 }
00328
else {
00329
00330
00331
00332
00333
00334
MI_TALLY_TRANSITION_PAGE_ADDITION (Pfn1);
00335 }
00336
00337
if ((ListHead->ListName ==
FreePageList) &&
00338 (
MmFreePageListHead.
Total >=
MmMinimumFreePagesToZero) &&
00339 (
MmZeroingPageThreadActive ==
FALSE)) {
00340
00341
00342
00343
00344
00345
00346
MmZeroingPageThreadActive =
TRUE;
00347
KeSetEvent (&
MmZeroingPageEvent, 0,
FALSE);
00348 }
00349
return;
00350 }
00351
00352
00353
00354
00355
00356
if (ListHead->ListName ==
ModifiedPageList) {
00357
00358
00359
00360
00361
00362
MI_TALLY_TRANSITION_PAGE_ADDITION (Pfn1);
00363
00364
if (Pfn1->
OriginalPte.
u.Soft.Prototype == 0) {
00365
ASSERT (Pfn1->
OriginalPte.
u.Soft.PageFileHigh == 0);
00366 }
00367
00368
PsGetCurrentProcess()->ModifiedPageCount += 1;
00369
if (
MmModifiedPageListHead.
Total >=
MmModifiedPageMaximum ) {
00370
00371
00372
00373
00374
00375
KeSetEvent (&
MmModifiedPageWriterEvent, 0,
FALSE);
00376 }
00377 }
00378
else if (ListHead->ListName ==
ModifiedNoWritePageList) {
00379
MI_TALLY_TRANSITION_PAGE_ADDITION (Pfn1);
00380 }
00381
00382
return;
00383 }
00384
00385
00386
VOID
00387
FASTCALL
00388 MiInsertStandbyListAtFront (
00389 IN PFN_NUMBER PageFrameIndex
00390 )
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 {
00414 PFN_NUMBER first;
00415 IN
PMMPFNLIST ListHead;
00416
PMMPFN Pfn1;
00417
PMMPFN Pfn2;
00418
00419
MM_PFN_LOCK_ASSERT();
00420
ASSERT ((PageFrameIndex != 0) && (PageFrameIndex <=
MmHighestPhysicalPage) &&
00421 (PageFrameIndex >=
MmLowestPhysicalPage));
00422
00423
00424
00425
00426
00427
00428 Pfn1 =
MI_PFN_ELEMENT(PageFrameIndex);
00429
00430
PERFINFO_INSERT_FRONT_STANDBY(PageFrameIndex);
00431
00432
#if DBG
00433
if (MmDebug &
MM_DBG_PAGE_REF_COUNT) {
00434
00435
PMMPTE PointerPte;
00436 KIRQL OldIrql = 99;
00437
00438
if ((Pfn1->
u3.e1.PrototypePte == 1) &&
00439 (
MmIsAddressValid (Pfn1->
PteAddress))) {
00440 PointerPte = Pfn1->
PteAddress;
00441 }
else {
00442
00443
00444
00445
00446
00447
00448 PointerPte =
MiMapPageInHyperSpace (Pfn1->
PteFrame, &OldIrql);
00449 PointerPte = (
PMMPTE)((PCHAR)PointerPte +
00450
MiGetByteOffset(Pfn1->
PteAddress));
00451 }
00452
00453
ASSERT ((
MI_GET_PAGE_FRAME_FROM_TRANSITION_PTE (PointerPte) == PageFrameIndex) ||
00454 (
MI_GET_PAGE_FRAME_FROM_PTE (PointerPte) == PageFrameIndex));
00455
ASSERT (PointerPte->u.Soft.Transition == 1);
00456
ASSERT (PointerPte->u.Soft.Prototype == 0);
00457
if (OldIrql != 99) {
00458
MiUnmapPageInHyperSpace (OldIrql)
00459 }
00460 }
00461
00462
if ((Pfn1->
OriginalPte.
u.Soft.Prototype == 0) &&
00463 (Pfn1->
OriginalPte.
u.Soft.Transition == 1)) {
00464
KeBugCheckEx (MEMORY_MANAGEMENT, 0x8889, 0,0,0);
00465 }
00466
#endif
00467
00468
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
00469
ASSERT (Pfn1->
u3.e1.PrototypePte == 1);
00470
MmTransitionSharedPages += 1;
00471
00472
MmStandbyPageListHead.
Total += 1;
00473
00474
ASSERT (
MmTransitionPrivatePages +
MmTransitionSharedPages ==
MmStandbyPageListHead.
Total +
MmModifiedPageListHead.
Total +
MmModifiedNoWritePageListHead.
Total);
00475
00476 ListHead = &
MmStandbyPageListHead;
00477
00478 first = ListHead->
Flink;
00479
if (first ==
MM_EMPTY_LIST) {
00480
00481
00482
00483
00484
00485 ListHead->Blink = PageFrameIndex;
00486 }
else {
00487 Pfn2 =
MI_PFN_ELEMENT (first);
00488 Pfn2->
u2.Blink = PageFrameIndex;
00489 }
00490
00491 ListHead->Flink = PageFrameIndex;
00492 Pfn1->
u2.Blink =
MM_EMPTY_LIST;
00493 Pfn1->
u1.Flink = first;
00494 Pfn1->
u3.e1.PageLocation =
StandbyPageList;
00495
00496
00497
00498
00499
00500
00501
00502
00503
MmAvailablePages += 1;
00504
00505
00506
00507
00508
00509
00510
if (
MmAvailablePages ==
MM_LOW_LIMIT) {
00511
KeSetEvent (&
MmAvailablePagesEvent, 0,
FALSE);
00512 }
else if (
MmAvailablePages ==
MM_HIGH_LIMIT) {
00513
KeSetEvent (&
MmAvailablePagesEventHigh, 0,
FALSE);
00514 }
00515
00516
return;
00517 }
00518
00519 PFN_NUMBER
00520
FASTCALL
00521 MiRemovePageFromList (
00522 IN
PMMPFNLIST ListHead
00523 )
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 {
00551 PFN_NUMBER PageFrameIndex;
00552
PMMPFN Pfn1;
00553
PMMPFN Pfn2;
00554 ULONG Color;
00555
00556
MM_PFN_LOCK_ASSERT();
00557
00558
00559
00560
00561
00562
if (ListHead->Total == 0) {
00563
00564 KdPrint((
"MM:Attempting to remove page from empty list\n"));
00565
KeBugCheckEx (PFN_LIST_CORRUPT, 1, (ULONG_PTR)ListHead,
MmAvailablePages, 0);
00566
return 0;
00567 }
00568
00569
ASSERT (ListHead->ListName !=
ModifiedPageList);
00570
00571
00572
00573
00574
00575
00576 ListHead->Total -= 1;
00577 PageFrameIndex = ListHead->Flink;
00578 Pfn1 =
MI_PFN_ELEMENT (PageFrameIndex);
00579
00580
PERFINFO_REMOVEPAGE(PageFrameIndex, PERFINFO_LOG_TYPE_REMOVEPAGEFROMLIST);
00581
00582 ListHead->Flink = Pfn1->
u1.Flink;
00583
00584
00585
00586
00587
00588 Pfn1->
u1.Flink = 0;
00589 Pfn1->
u2.Blink = 0;
00590
00591
00592
00593
00594
00595
00596
if (ListHead->Flink ==
MM_EMPTY_LIST) {
00597 ListHead->Blink =
MM_EMPTY_LIST;
00598 }
else {
00599
00600
00601
00602
00603
00604
00605 Pfn2 =
MI_PFN_ELEMENT (ListHead->Flink);
00606 Pfn2->
u2.Blink =
MM_EMPTY_LIST;
00607 }
00608
00609
00610
00611
00612
00613
if (ListHead->ListName <=
StandbyPageList) {
00614
MmAvailablePages -= 1;
00615
00616
if (ListHead->ListName ==
StandbyPageList) {
00617
00618
00619
00620
00621
00622
00623
MI_TALLY_TRANSITION_PAGE_REMOVAL (Pfn1);
00624
MiRestoreTransitionPte (PageFrameIndex);
00625 }
00626
00627
if (
MmAvailablePages <
MmMinimumFreePages) {
00628
00629
00630
00631
00632
00633
MiObtainFreePages();
00634 }
00635 }
00636
00637
ASSERT ((PageFrameIndex != 0) &&
00638 (PageFrameIndex <=
MmHighestPhysicalPage) &&
00639 (PageFrameIndex >=
MmLowestPhysicalPage));
00640
00641
00642
00643
00644
00645 Color = Pfn1->
u3.e1.PageColor;
00646
ASSERT (Pfn1->
u3.e1.RemovalRequested == 0);
00647 Pfn1->
u3.e2.ShortFlags = 0;
00648 Pfn1->
u3.e1.PageColor = Color;
00649 Color =
MI_GET_SECONDARY_COLOR (PageFrameIndex, Pfn1);
00650
00651
if (ListHead->ListName <=
FreePageList) {
00652
00653
00654
00655
00656
00657
ASSERT (
MmFreePagesByColor[ListHead->ListName][Color].
Flink == PageFrameIndex);
00658
MmFreePagesByColor[ListHead->ListName][Color].
Flink =
00659 (PFN_NUMBER) Pfn1->
OriginalPte.
u.Long;
00660 }
00661
00662
return PageFrameIndex;
00663 }
00664
00665
VOID
00666
FASTCALL
00667 MiUnlinkPageFromList (
00668 IN
PMMPFN Pfn
00669 )
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 {
00695
PMMPFNLIST ListHead;
00696 PFN_NUMBER Previous;
00697 PFN_NUMBER Next;
00698
PMMPFN Pfn2;
00699
00700
MM_PFN_LOCK_ASSERT();
00701
00702
PERFINFO_UNLINKPAGE((ULONG_PTR)(Pfn -
MmPfnDatabase), Pfn->u3.e1.PageLocation);
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
if (Pfn->u3.e2.ReferenceCount > 0) {
00714
00715
00716
00717
00718
00719
00720
if (Pfn->u2.ShareCount == 0) {
00721
#if DBG
00722
if (MmDebug &
MM_DBG_PAGE_IN_LIST) {
00723
DbgPrint(
"unlinking page not in list...\n");
00724
MiFormatPfn(Pfn);
00725 }
00726
#endif
00727
return;
00728 }
00729 KdPrint((
"MM:attempt to remove page from wrong page list\n"));
00730
KeBugCheckEx (PFN_LIST_CORRUPT,
00731 2,
00732 Pfn -
MmPfnDatabase,
00733
MmHighestPhysicalPage,
00734 Pfn->u3.e2.ReferenceCount);
00735
return;
00736 }
00737
00738 ListHead =
MmPageLocationList[Pfn->u3.e1.PageLocation];
00739
00740
00741
00742
00743
00744
00745
ASSERT (ListHead->
ListName >=
StandbyPageList);
00746
00747
00748
00749
00750
00751
00752
00753
if ((ListHead == &
MmModifiedPageListHead) &&
00754 (Pfn->OriginalPte.u.Soft.Prototype == 0)) {
00755
00756
00757
00758
00759
00760
00761
00762 ListHead->
Total -= 1;
00763
MmTotalPagesForPagingFile -= 1;
00764 ListHead = &
MmModifiedPageListByColor [Pfn->u3.e1.PageColor];
00765 }
00766
00767
ASSERT (Pfn->u3.e1.WriteInProgress == 0);
00768
ASSERT (Pfn->u3.e1.ReadInProgress == 0);
00769
ASSERT (ListHead->
Total != 0);
00770
00771 Next = Pfn->u1.Flink;
00772 Pfn->u1.Flink = 0;
00773 Previous = Pfn->u2.Blink;
00774 Pfn->u2.Blink = 0;
00775
00776
if (Next ==
MM_EMPTY_LIST) {
00777 ListHead->
Blink = Previous;
00778 }
else {
00779 Pfn2 =
MI_PFN_ELEMENT(Next);
00780 Pfn2->
u2.Blink = Previous;
00781 }
00782
00783
if (Previous ==
MM_EMPTY_LIST) {
00784 ListHead->
Flink = Next;
00785 }
else {
00786 Pfn2 =
MI_PFN_ELEMENT(Previous);
00787 Pfn2->
u1.Flink = Next;
00788 }
00789
00790 ListHead->
Total -= 1;
00791
00792
00793
00794
00795
00796
if (ListHead->
ListName <=
StandbyPageList) {
00797
MmAvailablePages -= 1;
00798
00799
if (ListHead->
ListName ==
StandbyPageList) {
00800
MI_TALLY_TRANSITION_PAGE_REMOVAL (Pfn);
00801 }
00802
00803
if (
MmAvailablePages <
MmMinimumFreePages) {
00804
00805
00806
00807
00808
00809
MiObtainFreePages();
00810
00811 }
00812 }
00813
else if (ListHead->
ListName ==
ModifiedPageList || ListHead->
ListName ==
ModifiedNoWritePageList) {
00814
MI_TALLY_TRANSITION_PAGE_REMOVAL (Pfn);
00815 }
00816
00817
return;
00818 }
00819
00820
VOID
00821 MiUnlinkFreeOrZeroedPage (
00822 IN PFN_NUMBER Page
00823 )
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 {
00849
PMMPFNLIST ListHead;
00850 PFN_NUMBER Previous;
00851 PFN_NUMBER Next;
00852
PMMPFN Pfn2;
00853
PMMPFN Pfn;
00854 ULONG Color;
00855
00856 Pfn =
MI_PFN_ELEMENT (Page);
00857
00858
MM_PFN_LOCK_ASSERT();
00859
00860 ListHead =
MmPageLocationList[Pfn->
u3.e1.PageLocation];
00861
ASSERT (ListHead->
Total != 0);
00862 ListHead->
Total -= 1;
00863
00864
ASSERT (ListHead->
ListName <=
FreePageList);
00865
ASSERT (Pfn->
u3.e1.WriteInProgress == 0);
00866
ASSERT (Pfn->
u3.e1.ReadInProgress == 0);
00867
00868
PERFINFO_UNLINKFREEPAGE((ULONG_PTR)(Pfn -
MmPfnDatabase), Pfn->
u3.e1.PageLocation);
00869
00870 Next = Pfn->
u1.Flink;
00871 Pfn->
u1.Flink = 0;
00872 Previous = Pfn->
u2.Blink;
00873 Pfn->
u2.Blink = 0;
00874
00875
if (Next ==
MM_EMPTY_LIST) {
00876 ListHead->
Blink = Previous;
00877 }
else {
00878 Pfn2 =
MI_PFN_ELEMENT(Next);
00879 Pfn2->
u2.Blink = Previous;
00880 }
00881
00882
if (Previous ==
MM_EMPTY_LIST) {
00883 ListHead->
Flink = Next;
00884 }
else {
00885 Pfn2 =
MI_PFN_ELEMENT(Previous);
00886 Pfn2->
u1.Flink = Next;
00887 }
00888
00889
00890
00891
00892
00893
00894 Color =
MI_GET_SECONDARY_COLOR (Page, Pfn);
00895
ASSERT (Pfn->
u3.e1.PageColor ==
MI_GET_COLOR_FROM_SECONDARY(Color));
00896
00897
00898
00899
00900
00901 Next =
MmFreePagesByColor[ListHead->
ListName][Color].
Flink;
00902
if (Next == Page) {
00903
MmFreePagesByColor[ListHead->
ListName][Color].
Flink =
00904 (PFN_NUMBER) Pfn->
OriginalPte.
u.Long;
00905 }
else {
00906
00907
00908
00909
00910
00911
for (; ; ) {
00912 Pfn2 =
MI_PFN_ELEMENT (Next);
00913 Next = (PFN_NUMBER) Pfn2->
OriginalPte.
u.Long;
00914
if (Page == Next) {
00915 Pfn2->
OriginalPte.
u.Long = Pfn->
OriginalPte.
u.Long;
00916
if ((PFN_NUMBER) Pfn->
OriginalPte.
u.Long ==
MM_EMPTY_LIST) {
00917
MmFreePagesByColor[ListHead->
ListName][Color].
Blink = Pfn2;
00918 }
00919
break;
00920 }
00921 }
00922 }
00923
00924
MmAvailablePages -= 1;
00925
00926
if (
MmAvailablePages <
MmMinimumFreePages) {
00927
00928
00929
00930
00931
00932
MiObtainFreePages();
00933 }
00934
00935
return;
00936 }
00937
00938
00939 ULONG
00940
FASTCALL
00941 MiEnsureAvailablePageOrWait (
00942 IN
PEPROCESS Process,
00943 IN PVOID VirtualAddress
00944 )
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 {
00984 PVOID
Event;
00985
NTSTATUS Status;
00986 KIRQL OldIrql;
00987 KIRQL Ignore;
00988 ULONG Limit;
00989 ULONG Relock;
00990 PFN_NUMBER StrandedPages;
00991 LOGICAL WsHeldSafe;
00992
PMMPFN Pfn1;
00993
PMMPFN EndPfn;
00994 LARGE_INTEGER WaitBegin;
00995 LARGE_INTEGER WaitEnd;
00996
00997
MM_PFN_LOCK_ASSERT();
00998
00999
if (
MmAvailablePages >=
MM_HIGH_LIMIT) {
01000
01001
01002
01003
01004
01005
return FALSE;
01006 }
01007
01008
01009
01010
01011
01012
01013
#if defined(_IA64_)
01014
if (
MI_IS_SYSTEM_ADDRESS(VirtualAddress) ||
01015 (
MI_IS_HYPER_SPACE_ADDRESS(VirtualAddress))) {
01016
#else
01017
if (((
PMMPTE)VirtualAddress >
MiGetPteAddress(
HYPER_SPACE)) ||
01018 ((VirtualAddress > MM_HIGHEST_USER_ADDRESS) &&
01019 (VirtualAddress < (PVOID)PTE_BASE))) {
01020
#endif
01021
01022
01023
01024
01025
01026
if (
MmAvailablePages >=
MM_LOW_LIMIT) {
01027
01028
01029
01030
01031
01032
return FALSE;
01033 }
01034
01035 Limit =
MM_LOW_LIMIT;
01036
Event = (PVOID)&
MmAvailablePagesEvent;
01037 }
else {
01038 Limit =
MM_HIGH_LIMIT;
01039
Event = (PVOID)&
MmAvailablePagesEventHigh;
01040 }
01041
01042
while (
MmAvailablePages < Limit) {
01043
KeClearEvent ((
PKEVENT)
Event);
01044
01045
UNLOCK_PFN (
APC_LEVEL);
01046
01047
if (Process ==
HYDRA_PROCESS) {
01048
UNLOCK_SESSION_SPACE_WS (
APC_LEVEL);
01049 }
01050
else if (Process !=
NULL) {
01051
01052
01053
01054
01055
01056
01057
UNLOCK_WS_REGARDLESS (Process, WsHeldSafe);
01058 }
01059
else {
01060 Relock =
FALSE;
01061
if (
MmSystemLockOwner ==
PsGetCurrentThread()) {
01062
UNLOCK_SYSTEM_WS (
APC_LEVEL);
01063 Relock =
TRUE;
01064 }
01065 }
01066
01067 KiQueryInterruptTime(&WaitBegin);
01068
01069
01070
01071
01072
01073
Status =
KeWaitForSingleObject(
Event,
01074
WrFreePage,
01075
KernelMode,
01076
FALSE,
01077 (PLARGE_INTEGER)&
MmSevenMinutes);
01078
01079
if (
Status == STATUS_TIMEOUT) {
01080
01081 KiQueryInterruptTime(&WaitEnd);
01082
01083
01084
01085
01086
01087
01088
01089 Limit = 0;
01090 StrandedPages = 0;
01091
01092
do {
01093
01094 Pfn1 =
MI_PFN_ELEMENT (
MmPhysicalMemoryBlock->
Run[Limit].
BasePage);
01095 EndPfn = Pfn1 +
MmPhysicalMemoryBlock->
Run[Limit].
PageCount;
01096
01097
while (Pfn1 < EndPfn) {
01098
if ((Pfn1->
u3.e1.PageLocation ==
TransitionPage) &&
01099 (Pfn1->
u3.e2.ReferenceCount != 0)) {
01100 StrandedPages += 1;
01101 }
01102 Pfn1 += 1;
01103 }
01104 Limit += 1;
01105
01106 }
while (Limit !=
MmPhysicalMemoryBlock->
NumberOfRuns);
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
KeBugCheckEx (NO_PAGES_AVAILABLE,
01139
MmModifiedPageListHead.
Total,
01140
MmTotalPagesForPagingFile,
01141 (
MmMaximumNonPagedPoolInBytes >>
PAGE_SHIFT) -
MmAllocatedNonPagedPool,
01142 StrandedPages);
01143
01144
if (!
KdDebuggerNotPresent) {
01145
DbgPrint (
"MmEnsureAvailablePageOrWait: 7 min timeout %x %x %x %x\n", WaitEnd.HighPart, WaitEnd.LowPart, WaitBegin.HighPart, WaitBegin.LowPart);
01146 DbgBreakPoint ();
01147 }
01148 }
01149
01150
if (Process ==
HYDRA_PROCESS) {
01151
LOCK_SESSION_SPACE_WS (Ignore);
01152 }
01153
else if (Process !=
NULL) {
01154
01155
01156
01157
01158
01159
01160
LOCK_WS_REGARDLESS (Process, WsHeldSafe);
01161 }
01162
else {
01163
if (Relock) {
01164
LOCK_SYSTEM_WS (Ignore);
01165 }
01166 }
01167
01168
LOCK_PFN (OldIrql);
01169 }
01170
01171
return TRUE;
01172 }
01173
01174
01175 PFN_NUMBER
01176
FASTCALL
01177 MiRemoveZeroPage (
01178 IN ULONG PageColor
01179 )
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210 {
01211 PFN_NUMBER Page;
01212
PMMPFN Pfn1;
01213 ULONG Color;
01214
01215
MM_PFN_LOCK_ASSERT();
01216
ASSERT(
MmAvailablePages != 0);
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
if (
MmFreePagesByColor[
ZeroedPageList][PageColor].
Flink !=
MM_EMPTY_LIST) {
01230
01231
01232
01233
01234
01235 Page =
MmFreePagesByColor[
ZeroedPageList][PageColor].
Flink;
01236
01237
#if DBG
01238
Pfn1 =
MI_PFN_ELEMENT(Page);
01239
ASSERT (Pfn1->
u3.e1.PageLocation ==
ZeroedPageList);
01240
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01241
#endif
01242
01243
MiRemovePageByColor (Page, PageColor);
01244
01245
#if DBG
01246
ASSERT (Pfn1->
u3.e1.PageColor == (PageColor &
MM_COLOR_MASK));
01247
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
01248
ASSERT (Pfn1->
u2.ShareCount == 0);
01249
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01250
#endif
01251
return Page;
01252
01253 }
01254
01255
01256
01257
01258
01259
01260
if (
MmZeroedPageListHead.
Flink !=
MM_EMPTY_LIST) {
01261 Page =
MmZeroedPageListHead.
Flink;
01262
#if DBG
01263
Pfn1 =
MI_PFN_ELEMENT(Page);
01264
ASSERT (Pfn1->
u3.e1.PageLocation ==
ZeroedPageList);
01265
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01266
#endif
01267
Color =
MI_GET_SECONDARY_COLOR (Page,
MI_PFN_ELEMENT(Page));
01268
MiRemovePageByColor (Page, Color);
01269
#if DBG
01270
Pfn1 =
MI_PFN_ELEMENT(Page);
01271
ASSERT (Pfn1->
u3.e1.PageColor == (PageColor &
MM_COLOR_MASK));
01272
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
01273
ASSERT (Pfn1->
u2.ShareCount == 0);
01274
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01275
#endif
01276
return Page;
01277 }
01278
01279
01280
01281
01282
01283
01284
if (
MmFreePagesByColor[
FreePageList][PageColor].
Flink !=
MM_EMPTY_LIST) {
01285
01286
01287
01288
01289
01290 Page =
MmFreePagesByColor[
FreePageList][PageColor].
Flink;
01291
01292
#if DBG
01293
Pfn1 =
MI_PFN_ELEMENT(Page);
01294
ASSERT (Pfn1->
u3.e1.PageLocation ==
FreePageList);
01295
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01296
#endif
01297
01298
MiRemovePageByColor (Page, PageColor);
01299
#if DBG
01300
Pfn1 =
MI_PFN_ELEMENT(Page);
01301
ASSERT (Pfn1->
u3.e1.PageColor == (PageColor &
MM_COLOR_MASK));
01302
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
01303
ASSERT (Pfn1->
u2.ShareCount == 0);
01304
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01305
#endif
01306
goto ZeroPage;
01307 }
01308
01309
if (
MmFreePageListHead.
Flink !=
MM_EMPTY_LIST) {
01310 Page =
MmFreePageListHead.
Flink;
01311
01312 Color =
MI_GET_SECONDARY_COLOR (Page,
MI_PFN_ELEMENT(Page));
01313
MiRemovePageByColor (Page, Color);
01314
#if DBG
01315
Pfn1 =
MI_PFN_ELEMENT(Page);
01316
ASSERT (Pfn1->
u3.e1.PageColor == (PageColor &
MM_COLOR_MASK));
01317
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
01318
ASSERT (Pfn1->
u2.ShareCount == 0);
01319
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01320
#endif
01321
goto ZeroPage;
01322 }
01323
01324
ASSERT (
MmZeroedPageListHead.
Total == 0);
01325
ASSERT (
MmFreePageListHead.
Total == 0);
01326
01327
if (
MmZeroedPageListHead.
Total != 0) {
01328
01329 Page =
MiRemovePageFromList(&
MmZeroedPageListHead);
01330
MI_CHECK_PAGE_ALIGNMENT(Page, PageColor &
MM_COLOR_MASK);
01331
01332 }
else {
01333
01334
01335
01336
01337
01338
01339
01340
if (
MmFreePageListHead.
Total != 0) {
01341 Page =
MiRemovePageFromList(&
MmFreePageListHead);
01342
ASSERT ((
MI_PFN_ELEMENT(Page))->PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01343 }
else {
01344
01345
01346
01347
01348
01349
01350
01351
ASSERT (
MmStandbyPageListHead.
Total != 0);
01352
01353 Page =
MiRemovePageFromList(&
MmStandbyPageListHead);
01354
ASSERT ((
MI_PFN_ELEMENT(Page))->PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01355 }
01356
01357
01358
01359
01360
01361 ZeroPage:
01362
01363 Pfn1 =
MI_PFN_ELEMENT(Page);
01364
01365
#if defined(_ALPHA_)
01366
HalZeroPage((PVOID)ULongToPtr((PageColor &
MM_COLOR_MASK) <<
PAGE_SHIFT),
01367 (PVOID)ULongToPtr((Pfn1->
u3.e1.PageColor) <<
PAGE_SHIFT),
01368 Page);
01369
#else
01370
MiZeroPhysicalPage (Page, 0);
01371
#endif
01372
01373
01374
01375
01376
01377
MI_BARRIER_STAMP_ZEROED_PAGE (&Pfn1->
PteFrame);
01378
01379 Pfn1->
u3.e1.PageColor = PageColor &
MM_COLOR_MASK;
01380
01381 }
01382
01383
#if DBG
01384
Pfn1 =
MI_PFN_ELEMENT (Page);
01385
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
01386
ASSERT (Pfn1->
u2.ShareCount == 0);
01387
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01388
#endif
01389
01390
return Page;
01391 }
01392
01393 PFN_NUMBER
01394
FASTCALL
01395 MiRemoveAnyPage (
01396 IN ULONG PageColor
01397 )
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429 {
01430 PFN_NUMBER Page;
01431
PMMPFN Pfn1;
01432 ULONG Color;
01433
01434
MM_PFN_LOCK_ASSERT();
01435
ASSERT(
MmAvailablePages != 0);
01436
01437
01438
01439
01440
01441
01442
if (
MmFreePagesByColor[
FreePageList][PageColor].
Flink !=
MM_EMPTY_LIST) {
01443
01444
01445
01446
01447
01448 Page =
MmFreePagesByColor[
FreePageList][PageColor].
Flink;
01449
#if DBG
01450
Pfn1 =
MI_PFN_ELEMENT(Page);
01451
ASSERT (Pfn1->
u3.e1.PageLocation ==
FreePageList);
01452
ASSERT (Pfn1->
u3.e1.PageColor == (PageColor &
MM_COLOR_MASK));
01453
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01454
#endif
01455
MiRemovePageByColor (Page, PageColor);
01456
#if DBG
01457
ASSERT (Pfn1->
u3.e1.PageColor == (PageColor &
MM_COLOR_MASK));
01458
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
01459
ASSERT (Pfn1->
u2.ShareCount == 0);
01460
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01461
#endif
01462
return Page;
01463
01464 }
01465
01466
if (
MmFreePagesByColor[
ZeroedPageList][PageColor].
Flink
01467 !=
MM_EMPTY_LIST) {
01468
01469
01470
01471
01472
01473 Page =
MmFreePagesByColor[
ZeroedPageList][PageColor].
Flink;
01474
#if DBG
01475
Pfn1 =
MI_PFN_ELEMENT(Page);
01476
ASSERT (Pfn1->
u3.e1.PageColor == (PageColor &
MM_COLOR_MASK));
01477
ASSERT (Pfn1->
u3.e1.PageLocation ==
ZeroedPageList);
01478
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01479
#endif
01480
01481
MiRemovePageByColor (Page, PageColor);
01482
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01483
return Page;
01484 }
01485
01486
01487
01488
01489
01490
if (
MmFreePageListHead.
Flink !=
MM_EMPTY_LIST) {
01491 Page =
MmFreePageListHead.
Flink;
01492 Color =
MI_GET_SECONDARY_COLOR (Page,
MI_PFN_ELEMENT(Page));
01493
01494
#if DBG
01495
Pfn1 =
MI_PFN_ELEMENT(Page);
01496
ASSERT (Pfn1->
u3.e1.PageColor == (PageColor &
MM_COLOR_MASK));
01497
ASSERT (Pfn1->
u3.e1.PageLocation ==
FreePageList);
01498
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01499
#endif
01500
MiRemovePageByColor (Page, Color);
01501
#if DBG
01502
ASSERT (Pfn1->
u3.e1.PageColor == (PageColor &
MM_COLOR_MASK));
01503
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
01504
ASSERT (Pfn1->
u2.ShareCount == 0);
01505
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01506
#endif
01507
return Page;
01508
01509 }
01510
01511
if (
MmZeroedPageListHead.
Flink !=
MM_EMPTY_LIST) {
01512 Page =
MmZeroedPageListHead.
Flink;
01513 Color =
MI_GET_SECONDARY_COLOR (Page,
MI_PFN_ELEMENT(Page));
01514
MiRemovePageByColor (Page, Color);
01515
#if DBG
01516
Pfn1 =
MI_PFN_ELEMENT(Page);
01517
ASSERT (Pfn1->
u3.e1.PageColor == (PageColor &
MM_COLOR_MASK));
01518
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
01519
ASSERT (Pfn1->
u2.ShareCount == 0);
01520
ASSERT (Pfn1->
PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01521
#endif
01522
return Page;
01523 }
01524
01525
if (
MmFreePageListHead.
Total != 0) {
01526
01527 Page =
MiRemovePageFromList(&
MmFreePageListHead);
01528
ASSERT ((
MI_PFN_ELEMENT(Page))->PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01529
01530 }
else {
01531
01532
01533
01534
01535
01536
01537
if (
MmZeroedPageListHead.
Total != 0) {
01538
01539 Page =
MiRemovePageFromList(&
MmZeroedPageListHead);
01540
ASSERT ((
MI_PFN_ELEMENT(Page))->PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01541
01542 }
else {
01543
01544
01545
01546
01547
01548
01549
ASSERT(
MmStandbyPageListHead.
Total != 0);
01550
01551 Page =
MiRemovePageFromList(&
MmStandbyPageListHead);
01552
ASSERT ((
MI_PFN_ELEMENT(Page))->PteFrame !=
MI_MAGIC_AWE_PTEFRAME);
01553 }
01554 }
01555
01556
MI_CHECK_PAGE_ALIGNMENT(Page, PageColor &
MM_COLOR_MASK);
01557
#if DBG
01558
Pfn1 =
MI_PFN_ELEMENT (Page);
01559
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
01560
ASSERT (Pfn1->
u2.ShareCount == 0);
01561
#endif
01562
return Page;
01563 }
01564
01565
01566
VOID
01567 MiRemovePageByColor (
01568 IN PFN_NUMBER Page,
01569 IN ULONG Color
01570 )
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594 {
01595
PMMPFNLIST ListHead;
01596
PMMPFNLIST PrimaryListHead;
01597 PFN_NUMBER Previous;
01598 PFN_NUMBER Next;
01599
PMMPFN Pfn1;
01600
PMMPFN Pfn2;
01601 ULONG PrimaryColor;
01602
01603
MM_PFN_LOCK_ASSERT();
01604
01605 Pfn1 =
MI_PFN_ELEMENT (Page);
01606 PrimaryColor = Pfn1->
u3.e1.PageColor;
01607
01608
PERFINFO_REMOVEPAGE(Page, PERFINFO_LOG_TYPE_REMOVEPAGEBYCOLOR);
01609
01610 ListHead =
MmPageLocationList[Pfn1->
u3.e1.PageLocation];
01611
01612 ListHead->
Total -= 1;
01613
01614 PrimaryListHead = ListHead;
01615
01616
#if PFN_CONSISTENCY
01617
if (
MmFreePagesByColor[PrimaryListHead->
ListName][Color].
Flink != Page) {
01618
01619
KeBugCheckEx (PFN_LIST_CORRUPT,
01620 0x9A,
01621 Page,
01622 Color,
01623 (PFN_NUMBER)&
MmFreePagesByColor[PrimaryListHead->
ListName][Color].Flink);
01624 }
01625
#endif
01626
01627 Next = Pfn1->
u1.Flink;
01628 Pfn1->
u1.Flink = 0;
01629 Previous = Pfn1->
u2.Blink;
01630 Pfn1->
u2.Blink = 0;
01631
01632
if (Next ==
MM_EMPTY_LIST) {
01633 PrimaryListHead->
Blink = Previous;
01634 }
else {
01635 Pfn2 =
MI_PFN_ELEMENT(Next);
01636 Pfn2->
u2.Blink = Previous;
01637 }
01638
01639
if (Previous ==
MM_EMPTY_LIST) {
01640 PrimaryListHead->
Flink = Next;
01641 }
else {
01642 Pfn2 =
MI_PFN_ELEMENT(Previous);
01643 Pfn2->
u1.Flink = Next;
01644 }
01645
01646
01647
01648
01649
01650
ASSERT (Pfn1->
u3.e1.RemovalRequested == 0);
01651 Pfn1->
u3.e2.ShortFlags = 0;
01652 Pfn1->
u3.e1.PageColor = PrimaryColor;
01653
01654
01655
01656
01657
01658
MmFreePagesByColor[ListHead->ListName][Color].
Flink =
01659 (PFN_NUMBER) Pfn1->
OriginalPte.
u.Long;
01660
01661
01662
01663
01664
01665
MmAvailablePages -= 1;
01666
01667
if (
MmAvailablePages <
MmMinimumFreePages) {
01668
01669
01670
01671
01672
01673
MiObtainFreePages();
01674
01675 }
01676
01677
return;
01678 }
01679
01680
01681
VOID
01682
FASTCALL
01683 MiInsertFrontModifiedNoWrite (
01684 IN PFN_NUMBER PageFrameIndex
01685 )
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709 {
01710 PFN_NUMBER first;
01711
PMMPFN Pfn1;
01712
PMMPFN Pfn2;
01713
01714
MM_PFN_LOCK_ASSERT();
01715
ASSERT ((PageFrameIndex != 0) && (PageFrameIndex <=
MmHighestPhysicalPage) &&
01716 (PageFrameIndex >=
MmLowestPhysicalPage));
01717
01718
01719
01720
01721
01722
01723 Pfn1 =
MI_PFN_ELEMENT(PageFrameIndex);
01724
01725
ASSERT (Pfn1->
u3.e2.ReferenceCount == 0);
01726
01727
MmModifiedNoWritePageListHead.
Total += 1;
01728
01729
MI_TALLY_TRANSITION_PAGE_ADDITION (Pfn1);
01730
01731 first =
MmModifiedNoWritePageListHead.
Flink;
01732
if (first ==
MM_EMPTY_LIST) {
01733
01734
01735
01736
01737
01738
MmModifiedNoWritePageListHead.
Blink = PageFrameIndex;
01739 }
else {
01740 Pfn2 =
MI_PFN_ELEMENT (first);
01741 Pfn2->
u2.Blink = PageFrameIndex;
01742 }
01743
01744
MmModifiedNoWritePageListHead.
Flink = PageFrameIndex;
01745 Pfn1->
u1.Flink = first;
01746 Pfn1->
u2.Blink =
MM_EMPTY_LIST;
01747 Pfn1->
u3.e1.PageLocation =
ModifiedNoWritePageList;
01748
return;
01749 }