test: pfndec.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# pfndec.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007    pfndec.c
    00008
    00009 Abstract:
    00010
    00011     This module contains the routines to decrement the share count and
    00012     the reference counts within the Page Frame Database.
    00013
    00014 Author:
    00015
    00016     Lou Perazzoli (loup) 5-Apr-1989
    00017     Landy Wang (landyw) 2-Jun-1997
    00018
    00019 Revision History:
    00020
    00021 --*/
    00022
    00023 #include "mi.h"
    00024
    00025 ULONG MmFrontOfList;
    00026
    00027
    00028 VOID
    00029 FASTCALL
    00030 MiDecrementShareCount (
    00031     IN PFN_NUMBER PageFrameIndex
    00032     )
    00033
    00034 /*++
    00035
    00036 Routine Description:
    00037
    00038     This routine decrements the share count within the PFN element
    00039     for the specified physical page.  If the share count becomes
    00040     zero the corresponding PTE is converted to the transition state
    00041     and the reference count is decremented and the ValidPte count
    00042     of the PTEframe is decremented.
    00043
    00044 Arguments:
    00045
    00046     PageFrameIndex - Supplies the physical page number of which to decrement
    00047                      the share count.
    00048
    00049 Return Value:
    00050
    00051     None.
    00052
    00053 Environment:
    00054
    00055     Must be holding the PFN database mutex with APCs disabled.
    00056
    00057 --*/
    00058
    00059 {
    00060     MMPTE TempPte;
    00061     PMMPTE PointerPte;
    00062     PMMPFN Pfn1;
    00063     KIRQL OldIrql;
    00064
    00065     ASSERT ((PageFrameIndex <= MmHighestPhysicalPage) &&
    00066             (PageFrameIndex > 0));
    00067
    00068     Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
    00069
    00070     if (Pfn1->u3.e1.PageLocation != ActiveAndValid &&
    00071         Pfn1->u3.e1.PageLocation != StandbyPageList) {
    00072             KeBugCheckEx (PFN_LIST_CORRUPT,
    00073                       0x99,
    00074                       PageFrameIndex,
    00075                       Pfn1->u3.e1.PageLocation,
    00076                       0);
    00077     }
    00078
    00079 #if PFN_CONSISTENCY
    00080     if (Pfn1->u3.e1.PageTablePage == 1) {
    00081
    00082         // Need to run the page and see if the number of transition & valid
    00083         // pages + 1 matches up to the share count.
    00084         //
    00085         // For the page being freed (share == 1), need to snap the caller here
    00086
    00087     }
    00088 #endif
    00089
    00090     Pfn1->u2.ShareCount -= 1;
    00091
    00092     PERFINFO_DECREFCNT(Pfn1, PERFINFO_LOG_WSCHANGE, PERFINFO_LOG_TYPE_DECSHARCNT)
    00093
    00094     ASSERT (Pfn1->u2.ShareCount < 0xF000000);
    00095
    00096     if (Pfn1->u2.ShareCount == 0) {
    00097
    00098         PERFINFO_DECREFCNT(Pfn1, PERFINFO_LOG_EMPTYQ, PERFINFO_LOG_TYPE_ZEROSHARECOUNT)
    00099
    00100         //
    00101         // The share count is now zero, decrement the reference count
    00102         // for the PFN element and turn the referenced PTE into
    00103         // the transition state if it refers to a prototype PTE.
    00104         // PTEs which are not prototype PTEs do not need to be placed
    00105         // into transition as they are placed in transition when
    00106         // they are removed from the working set (working set free routine).
    00107         //
    00108
    00109         //
    00110         // If the PTE referenced by this PFN element is actually
    00111         // a prototype PTE, it must be mapped into hyperspace and
    00112         // then operated on.
    00113         //
    00114
    00115         if (Pfn1->u3.e1.PrototypePte == 1) {
    00116
    00117             OldIrql = 99;
    00118             if (MmIsAddressValid (Pfn1->PteAddress)) {
    00119                 PointerPte = Pfn1->PteAddress;
    00120             } else {
    00121
    00122                 //
    00123                 // The address is not valid in this process, map it into
    00124                 // hyperspace so it can be operated upon.
    00125                 //
    00126
    00127                 PointerPte = (PMMPTE)MiMapPageInHyperSpace(Pfn1->PteFrame,
    00128                                                            &OldIrql);
    00129                 PointerPte = (PMMPTE)((PCHAR)PointerPte +
    00130                                         MiGetByteOffset(Pfn1->PteAddress));
    00131             }
    00132
    00133             TempPte = *PointerPte;
    00134             MI_MAKE_VALID_PTE_TRANSITION (TempPte,
    00135                                           Pfn1->OriginalPte.u.Soft.Protection);
    00136             MI_WRITE_INVALID_PTE (PointerPte, TempPte);
    00137
    00138             if (OldIrql != 99) {
    00139                 MiUnmapPageInHyperSpace (OldIrql);
    00140             }
    00141
    00142             //
    00143             // There is no need to flush the translation buffer at this
    00144             // time as we only invalidated a prototype PTE.
    00145             //
    00146
    00147         }
    00148
    00149         //
    00150         // Change the page location to inactive (from active and valid).
    00151         //
    00152
    00153         Pfn1->u3.e1.PageLocation = TransitionPage;
    00154
    00155         //
    00156         // Decrement the reference count as the share count is now zero.
    00157         //
    00158
    00159         MiDecrementReferenceCount (PageFrameIndex);
    00160     }
    00161
    00162     return;
    00163 }
    00164
    00165 VOID
    00166 FASTCALL
    00167 MiDecrementReferenceCount (
    00168     IN PFN_NUMBER PageFrameIndex
    00169     )
    00170
    00171 /*++
    00172
    00173 Routine Description:
    00174
    00175     This routine decrements the reference count for the specified page.
    00176     If the reference count becomes zero, the page is placed on the
    00177     appropriate list (free, modified, standby or bad).  If the page
    00178     is placed on the free or standby list, the number of available
    00179     pages is incremented and if it transitions from zero to one, the
    00180     available page event is set.
    00181
    00182
    00183 Arguments:
    00184
    00185     PageFrameIndex - Supplies the physical page number of which to
    00186                      decrement the reference count.
    00187
    00188 Return Value:
    00189
    00190     none.
    00191
    00192 Environment:
    00193
    00194     Must be holding the PFN database mutex with APCs disabled.
    00195
    00196 --*/
    00197
    00198 {
    00199     PMMPFN Pfn1;
    00200
    00201     MM_PFN_LOCK_ASSERT();
    00202
    00203     ASSERT (PageFrameIndex <= MmHighestPhysicalPage);
    00204
    00205     Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
    00206     ASSERT (Pfn1->u3.e2.ReferenceCount != 0);
    00207     Pfn1->u3.e2.ReferenceCount -= 1;
    00208
    00209
    00210     if (Pfn1->u3.e2.ReferenceCount != 0) {
    00211
    00212         //
    00213         // The reference count is not zero, return.
    00214         //
    00215
    00216         return;
    00217     }
    00218
    00219     //
    00220     // The reference count is now zero, put the page on some
    00221     // list.
    00222     //
    00223
    00224
    00225     if (Pfn1->u2.ShareCount != 0) {
    00226
    00227         KeBugCheckEx (PFN_LIST_CORRUPT,
    00228                       7,
    00229                       PageFrameIndex,
    00230                       Pfn1->u2.ShareCount,
    00231                       0);
    00232         return;
    00233     }
    00234
    00235     ASSERT (Pfn1->u3.e1.PageLocation != ActiveAndValid);
    00236
    00237     if (MI_IS_PFN_DELETED (Pfn1)) {
    00238
    00239         //
    00240         // There is no referenced PTE for this page, delete the page file
    00241         // space (if any), and place the page on the free list.
    00242         //
    00243
    00244         MiReleasePageFileSpace (Pfn1->OriginalPte);
    00245
    00246         if (Pfn1->u3.e1.RemovalRequested == 1) {
    00247             MiInsertPageInList (MmPageLocationList[BadPageList],
    00248                                 PageFrameIndex);
    00249         }
    00250         else {
    00251             MiInsertPageInList (MmPageLocationList[FreePageList],
    00252                                 PageFrameIndex);
    00253         }
    00254
    00255         return;
    00256     }
    00257
    00258     //
    00259     // Place the page on the modified or standby list depending
    00260     // on the state of the modify bit in the PFN element.
    00261     //
    00262
    00263     if (Pfn1->u3.e1.Modified == 1) {
    00264         MiInsertPageInList (MmPageLocationList[ModifiedPageList], PageFrameIndex);
    00265     } else {
    00266
    00267         if (Pfn1->u3.e1.RemovalRequested == 1) {
    00268
    00269             //
    00270             // The page may still be marked as on the modified list if the
    00271             // current thread is the modified writer completing the write.
    00272             // Mark it as standby so restoration of the transition PTE
    00273             // doesn't flag this as illegal.
    00274             //
    00275
    00276             Pfn1->u3.e1.PageLocation = StandbyPageList;
    00277
    00278             MiRestoreTransitionPte (PageFrameIndex);
    00279             MiInsertPageInList (MmPageLocationList[BadPageList],
    00280                                 PageFrameIndex);
    00281             return;
    00282         }
    00283
    00284         if (!MmFrontOfList) {
    00285             MiInsertPageInList (MmPageLocationList[StandbyPageList],
    00286                                 PageFrameIndex);
    00287         } else {
    00288             MiInsertStandbyListAtFront (PageFrameIndex);
    00289         }
    00290     }
    00291
    00292     return;
    00293 }