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 }

Generated on Sat May 15 19:41:09 2004 for test by doxygen 1.3.7