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

wstree.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 wstree.c 00008 00009 Abstract: 00010 00011 This module contains the routines which manipulate the working 00012 set list tree. 00013 00014 Author: 00015 00016 Lou Perazzoli (loup) 15-May-1989 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "mi.h" 00023 00024 #if (_MSC_VER >= 800) 00025 #pragma warning(disable:4010) /* Allow pretty pictures without the noise */ 00026 #endif 00027 00028 extern ULONG MmSystemCodePage; 00029 extern ULONG MmSystemCachePage; 00030 extern ULONG MmPagedPoolPage; 00031 extern ULONG MmSystemDriverPage; 00032 00033 #if DBG 00034 ULONG MmNumberOfInserts; 00035 #endif 00036 00037 ULONG 00038 MiLookupWsleHashIndex ( 00039 IN ULONG_PTR WsleEntry, 00040 IN PMMWSL WorkingSetList 00041 ); 00042 00043 VOID 00044 MiCheckWsleHash ( 00045 IN PMMWSL WorkingSetList 00046 ); 00047 00048 00049 VOID 00050 FASTCALL 00051 MiInsertWsle ( 00052 IN WSLE_NUMBER Entry, 00053 IN PMMWSL WorkingSetList 00054 ) 00055 00056 /*++ 00057 00058 Routine Description: 00059 00060 This routine inserts a Working Set List Entry (WSLE) into the 00061 working set. 00062 00063 Arguments: 00064 00065 Entry - The index number of the WSLE to insert. 00066 00067 WorkingSetList - Supplies the working set list to insert into. 00068 00069 Return Value: 00070 00071 None. 00072 00073 Environment: 00074 00075 Kernel mode, APCs disabled, Working Set Mutex held. 00076 00077 --*/ 00078 00079 { 00080 PVOID VirtualAddress; 00081 PMMWSLE Wsle; 00082 PMMSUPPORT WsInfo; 00083 WSLE_NUMBER Hash; 00084 PMMWSLE_HASH Table; 00085 WSLE_NUMBER j; 00086 PMMPTE PointerPte; 00087 WSLE_NUMBER Index; 00088 LARGE_INTEGER TickCount; 00089 ULONG Size; 00090 #if defined(_ALPHA_) && !defined(_AXP64_) 00091 KIRQL OldIrql; 00092 #endif 00093 00094 Wsle = WorkingSetList->Wsle; 00095 00096 VirtualAddress = PAGE_ALIGN(Wsle[Entry].u1.VirtualAddress); 00097 00098 #if DBG 00099 if (MmDebug & MM_DBG_PTE_UPDATE) { 00100 DbgPrint("inserting element %lx %lx\n", Entry, Wsle[Entry].u1.Long); 00101 } 00102 00103 ASSERT (Wsle[Entry].u1.e1.Valid == 1); 00104 ASSERT (Wsle[Entry].u1.e1.Direct != 1); 00105 #endif //DBG 00106 00107 WorkingSetList->NonDirectCount += 1; 00108 00109 if ((Table = WorkingSetList->HashTable) == NULL) { 00110 return; 00111 } 00112 00113 #if DBG 00114 MmNumberOfInserts += 1; 00115 #endif //DBG 00116 00117 Hash = MI_WSLE_HASH(Wsle[Entry].u1.Long, WorkingSetList); 00118 00119 // 00120 // Check hash table size and see if there is enough room to 00121 // hash or if the table should be grown. 00122 // 00123 00124 if ((WorkingSetList->NonDirectCount + 10 + 00125 (WorkingSetList->HashTableSize >> 4)) > 00126 WorkingSetList->HashTableSize) { 00127 00128 if (WorkingSetList == MmWorkingSetList) { 00129 WsInfo = &PsGetCurrentProcess()->Vm; 00130 ASSERT (WsInfo->u.Flags.SessionSpace == 0); 00131 } 00132 else if (WorkingSetList == MmSystemCacheWorkingSetList) { 00133 WsInfo = &MmSystemCacheWs; 00134 ASSERT (WsInfo->u.Flags.SessionSpace == 0); 00135 } 00136 else { 00137 WsInfo = &MmSessionSpace->Vm; 00138 ASSERT (WsInfo->u.Flags.SessionSpace == 1); 00139 } 00140 00141 if ((Table + WorkingSetList->HashTableSize + ((2*PAGE_SIZE) / sizeof (MMWSLE_HASH)) <= (PMMWSLE_HASH)WorkingSetList->HighestPermittedHashAddress) && 00142 (WsInfo->AllowWorkingSetAdjustment)) { 00143 00144 #if defined(_ALPHA_) && !defined(_AXP64_) 00145 LOCK_EXPANSION_IF_ALPHA (OldIrql); 00146 #endif 00147 WsInfo->AllowWorkingSetAdjustment = MM_GROW_WSLE_HASH; 00148 #if defined(_ALPHA_) && !defined(_AXP64_) 00149 UNLOCK_EXPANSION_IF_ALPHA (OldIrql); 00150 #endif 00151 } 00152 00153 if ((WorkingSetList->NonDirectCount + 00154 (WorkingSetList->HashTableSize >> 4)) > 00155 WorkingSetList->HashTableSize) { 00156 00157 // 00158 // No more room in the hash table, remove one and add there. 00159 // Pick a victim within 16 of where this would hash to. 00160 // 00161 00162 KeQueryTickCount(&TickCount); 00163 j = Hash + (TickCount.LowPart & 0xF); 00164 00165 Size = WorkingSetList->HashTableSize; 00166 00167 if (j >= Size) { 00168 j = TickCount.LowPart & 0xF; 00169 } 00170 00171 do { 00172 if (Table[j].Key != 0) { 00173 PERFINFO_PAGE_INFO_DECL(); 00174 00175 PointerPte = MiGetPteAddress (Table[j].Key); 00176 Index = WorkingSetList->HashTable[j].Index; 00177 ASSERT (Wsle[Index].u1.e1.Valid == 1); 00178 PointerPte = MiGetPteAddress (Wsle[Index].u1.VirtualAddress); 00179 00180 PERFINFO_GET_PAGE_INFO(PointerPte); 00181 if (MiFreeWsle (Index, WsInfo, PointerPte)) { 00182 PERFINFO_LOG_WS_REMOVAL(PERFINFO_LOG_TYPE_OUTWS_HASHFULL, WsInfo); 00183 break; 00184 } 00185 } 00186 j += 1; 00187 if (j >= Size) { 00188 j = 0; 00189 } 00190 } while (TRUE); 00191 } 00192 } 00193 00194 // 00195 // Add to the hash table. 00196 // 00197 00198 while (Table[Hash].Key != 0) { 00199 Hash += 1; 00200 if (Hash >= WorkingSetList->HashTableSize) { 00201 Hash = 0; 00202 } 00203 } 00204 00205 Table[Hash].Key = Wsle[Entry].u1.Long & ~(PAGE_SIZE - 1); 00206 Table[Hash].Index = Entry; 00207 00208 #if DBG 00209 if ((MmNumberOfInserts % 1000) == 0) { 00210 MiCheckWsleHash (WorkingSetList); 00211 } 00212 #endif //DBG 00213 return; 00214 } 00215 00216 #if DBG 00217 VOID 00218 MiCheckWsleHash ( 00219 IN PMMWSL WorkingSetList 00220 ) 00221 00222 { 00223 ULONG j; 00224 ULONG found = 0; 00225 PMMWSLE Wsle; 00226 00227 Wsle = WorkingSetList->Wsle; 00228 00229 for (j =0; j < WorkingSetList->HashTableSize ; j++ ) { 00230 if (WorkingSetList->HashTable[j].Key != 0) { 00231 found += 1; 00232 ASSERT (WorkingSetList->HashTable[j].Key == 00233 (Wsle[WorkingSetList->HashTable[j].Index].u1.Long & 00234 ~(PAGE_SIZE -1))); 00235 } 00236 } 00237 if (found != WorkingSetList->NonDirectCount) { 00238 DbgPrint("MMWSLE: Found %lx, nondirect %lx\n", 00239 found, WorkingSetList->NonDirectCount); 00240 DbgBreakPoint(); 00241 } 00242 } 00243 #endif //dbg 00244 00245 00246 WSLE_NUMBER 00247 FASTCALL 00248 MiLocateWsle ( 00249 IN PVOID VirtualAddress, 00250 IN PMMWSL WorkingSetList, 00251 IN WSLE_NUMBER WsPfnIndex 00252 ) 00253 00254 /*++ 00255 00256 Routine Description: 00257 00258 This function locates the specified virtual address within the 00259 working set list. 00260 00261 Arguments: 00262 00263 VirtualAddress - Supplies the virtual to locate within the working 00264 set list. 00265 00266 WorkingSetList - Supplies the working set list to search. 00267 00268 WsPfnIndex - Supplies a hint to try before hashing or walking linearly. 00269 00270 Return Value: 00271 00272 Returns the index into the working set list which contains the entry. 00273 00274 Environment: 00275 00276 Kernel mode, APCs disabled, Working Set Mutex held. 00277 00278 --*/ 00279 00280 { 00281 WSLE_NUMBER i; 00282 PMMWSLE Wsle; 00283 ULONG Hash; 00284 PMMWSLE_HASH Table; 00285 ULONG Tries; 00286 WSLE_NUMBER WsPteIndex; 00287 PMMPTE PointerPte; 00288 00289 Wsle = WorkingSetList->Wsle; 00290 00291 VirtualAddress = PAGE_ALIGN(VirtualAddress); 00292 00293 #if defined (_WIN64) 00294 PointerPte = MiGetPteAddress (VirtualAddress); 00295 WsPteIndex = MI_GET_WORKING_SET_FROM_PTE (PointerPte); 00296 if (WsPteIndex != 0) { 00297 while (WsPteIndex <= WorkingSetList->LastInitializedWsle) { 00298 if ((VirtualAddress == PAGE_ALIGN(Wsle[WsPteIndex].u1.VirtualAddress)) && 00299 (Wsle[WsPteIndex].u1.e1.Valid == 1)) { 00300 return WsPteIndex; 00301 } 00302 WsPteIndex += MI_MAXIMUM_PTE_WORKING_SET_INDEX; 00303 } 00304 00305 // 00306 // No working set index for this PTE ! 00307 // 00308 00309 KeBugCheckEx (MEMORY_MANAGEMENT, 00310 0x41283, 00311 (ULONG_PTR)VirtualAddress, 00312 PointerPte->u.Long, 00313 (ULONG_PTR)WorkingSetList); 00314 } 00315 #endif 00316 00317 if (WsPfnIndex <= WorkingSetList->LastInitializedWsle) { 00318 if ((VirtualAddress == PAGE_ALIGN(Wsle[WsPfnIndex].u1.VirtualAddress)) && 00319 (Wsle[WsPfnIndex].u1.e1.Valid == 1)) { 00320 return WsPfnIndex; 00321 } 00322 } 00323 00324 if (WorkingSetList->HashTable) { 00325 Tries = 0; 00326 Table = WorkingSetList->HashTable; 00327 00328 Hash = MI_WSLE_HASH(VirtualAddress, WorkingSetList); 00329 00330 while (Table[Hash].Key != (ULONG_PTR)VirtualAddress) { 00331 Hash += 1; 00332 if (Hash >= WorkingSetList->HashTableSize) { 00333 Hash = 0; 00334 if (Tries != 0) { 00335 KeBugCheckEx (MEMORY_MANAGEMENT, 00336 0x41284, 00337 (ULONG_PTR)VirtualAddress, 00338 WsPfnIndex, 00339 (ULONG_PTR)WorkingSetList); 00340 } 00341 Tries = 1; 00342 } 00343 } 00344 ASSERT (WorkingSetList->Wsle[Table[Hash].Index].u1.e1.Direct == 0); 00345 return Table[Hash].Index; 00346 } 00347 00348 i = 0; 00349 00350 for (; ; ) { 00351 if ((VirtualAddress == PAGE_ALIGN(Wsle[i].u1.VirtualAddress)) && 00352 (Wsle[i].u1.e1.Valid == 1)) { 00353 ASSERT (WorkingSetList->Wsle[i].u1.e1.Direct == 0); 00354 return i; 00355 } 00356 i += 1; 00357 } 00358 } 00359 00360 00361 #if 0 00362 00363 ULONG 00364 MiLocateWsleAndParent ( 00365 IN PVOID VirtualAddress, 00366 OUT PULONG Parent, 00367 IN PMMWSL WorkingSetList, 00368 IN ULONG WsPfnIndex 00369 ) 00370 00371 /*++ 00372 00373 Routine Description: 00374 00375 This routine locates both the working set list entry (via index) and 00376 it's parent. 00377 00378 Arguments: 00379 00380 VirtualAddress - Supplies the virtual address of the WSLE to locate. 00381 00382 Parent - Returns the index into the working set list for the parent. 00383 00384 WorkingSetList - Supplies a pointer to the working set list. 00385 00386 WsPfnIndex - Supplies the index field from the PFN database for 00387 the physical page that maps the specified virtual address. 00388 00389 Return Value: 00390 00391 Returns the index of the virtual address in the working set list. 00392 00393 Environment: 00394 00395 Kernel mode, APCs disabled, Working Set Mutex held. 00396 00397 --*/ 00398 00399 { 00400 ULONG Previous; 00401 ULONG Entry; 00402 PMMWSLE Wsle; 00403 00404 Wsle = WorkingSetList->Wsle; 00405 00406 // 00407 // Check to see if the PfnIndex field refers to the WSLE in question. 00408 // Make sure the index is within the specified working set list. 00409 // 00410 00411 if (WsPfnIndex <= WorkingSetList->LastInitializedWsle) { 00412 if (VirtualAddress == PAGE_ALIGN(Wsle[WsPfnIndex].u1.VirtualAddress)) { 00413 00414 // 00415 // The index field points to the WSLE, however, this could 00416 // have been just a coincidence, so check to ensure it 00417 // really doesn't have a parent. 00418 // 00419 00420 if (Wsle[WsPfnIndex].u2.BothPointers == 0) { 00421 00422 // 00423 // Not in tree, therefore has no parent. 00424 // 00425 00426 *Parent = WSLE_NULL_INDEX; 00427 return WsPfnIndex; 00428 } 00429 } 00430 } 00431 00432 // 00433 // Search the tree for the entry remembering the parents. 00434 // 00435 00436 Entry = WorkingSetList->Root; 00437 Previous = Entry; 00438 00439 for (;;) { 00440 00441 ASSERT (Entry != WSLE_NULL_INDEX); 00442 00443 if (VirtualAddress == PAGE_ALIGN(Wsle[Entry].u1.VirtualAddress)) { 00444 break; 00445 } 00446 00447 if (VirtualAddress < PAGE_ALIGN(Wsle[Entry].u1.VirtualAddress)) { 00448 Previous = Entry; 00449 Entry = Wsle[Entry].u2.s.LeftChild; 00450 } else { 00451 Previous = Entry; 00452 Entry = Wsle[Entry].u2.s.RightChild; 00453 } 00454 } 00455 00456 *Parent = Previous; 00457 return Entry; 00458 } 00459 #endif //0 00460 00461 00462 VOID 00463 FASTCALL 00464 MiRemoveWsle ( 00465 IN WSLE_NUMBER Entry, 00466 IN PMMWSL WorkingSetList 00467 ) 00468 00469 /*++ 00470 00471 Routine Description: 00472 00473 This routine removes a Working Set List Entry (WSLE) from the 00474 working set. 00475 00476 Arguments: 00477 00478 Entry - The index number of the WSLE to remove. 00479 00480 00481 Return Value: 00482 00483 None. 00484 00485 Environment: 00486 00487 Kernel mode, APCs disabled, Working Set Mutex held. 00488 00489 --*/ 00490 { 00491 PMMWSLE Wsle; 00492 PVOID VirtualAddress; 00493 PMMWSLE_HASH Table; 00494 ULONG Hash; 00495 ULONG Tries; 00496 00497 Wsle = WorkingSetList->Wsle; 00498 00499 // 00500 // Locate the entry in the tree. 00501 // 00502 00503 #if DBG 00504 if (MmDebug & MM_DBG_PTE_UPDATE) { 00505 DbgPrint("removing wsle %lx %lx\n", 00506 Entry, Wsle[Entry].u1.Long); 00507 } 00508 if (MmDebug & MM_DBG_DUMP_WSL) { 00509 MiDumpWsl(); 00510 DbgPrint(" \n"); 00511 } 00512 00513 #endif //DBG 00514 00515 ASSERT (Wsle[Entry].u1.e1.Valid == 1); 00516 00517 VirtualAddress = PAGE_ALIGN (Wsle[Entry].u1.VirtualAddress); 00518 00519 if (WorkingSetList == MmSystemCacheWorkingSetList) { 00520 00521 // 00522 // count system space inserts and removals. 00523 // 00524 00525 #if defined(_X86_) 00526 if (MI_IS_SYSTEM_CACHE_ADDRESS(VirtualAddress)) { 00527 MmSystemCachePage -= 1; 00528 } else 00529 #endif 00530 if (VirtualAddress < MmSystemCacheStart) { 00531 MmSystemCodePage -= 1; 00532 } else if (VirtualAddress < MM_PAGED_POOL_START) { 00533 MmSystemCachePage -= 1; 00534 } else if (VirtualAddress < MmNonPagedSystemStart) { 00535 MmPagedPoolPage -= 1; 00536 } else { 00537 MmSystemDriverPage -= 1; 00538 } 00539 } 00540 00541 Wsle[Entry].u1.e1.Valid = 0; 00542 00543 if (Wsle[Entry].u1.e1.Direct == 0) { 00544 00545 WorkingSetList->NonDirectCount -= 1; 00546 00547 if (WorkingSetList->HashTable) { 00548 Hash = MI_WSLE_HASH(Wsle[Entry].u1.Long, WorkingSetList); 00549 Table = WorkingSetList->HashTable; 00550 Tries = 0; 00551 00552 while (Table[Hash].Key != (ULONG_PTR)VirtualAddress) { 00553 Hash += 1; 00554 if (Hash >= WorkingSetList->HashTableSize) { 00555 Hash = 0; 00556 if (Tries != 0) { 00557 KeBugCheckEx (MEMORY_MANAGEMENT, 00558 0x41784, 00559 (ULONG_PTR)VirtualAddress, 00560 Entry, 00561 (ULONG_PTR)WorkingSetList); 00562 } 00563 Tries = 1; 00564 } 00565 } 00566 Table[Hash].Key = 0; 00567 00568 } 00569 } 00570 00571 return; 00572 } 00573 00574 00575 VOID 00576 MiSwapWslEntries ( 00577 IN WSLE_NUMBER SwapEntry, 00578 IN WSLE_NUMBER Entry, 00579 IN PMMSUPPORT WsInfo 00580 ) 00581 00582 /*++ 00583 00584 Routine Description: 00585 00586 This routine swaps the working set list entries Entry and SwapEntry 00587 in the specified working set list (process or system cache). 00588 00589 Arguments: 00590 00591 SwapEntry - Supplies the first entry to swap. This entry must be 00592 valid, i.e. in the working set at the current time. 00593 00594 Entry - Supplies the other entry to swap. This entry may be valid 00595 or invalid. 00596 00597 WsInfo - Supplies the working set list. 00598 00599 Return Value: 00600 00601 None. 00602 00603 Environment: 00604 00605 Kernel mode, Working set lock and PFN lock held (if system cache), 00606 APCs disabled. 00607 00608 --*/ 00609 00610 { 00611 MMWSLE WsleEntry; 00612 MMWSLE WsleSwap; 00613 PMMPTE PointerPte; 00614 PMMPFN Pfn1; 00615 PMMWSLE Wsle; 00616 PMMWSL WorkingSetList; 00617 PMMWSLE_HASH Table; 00618 #if DBG 00619 WSLE_NUMBER CurrentSize = WsInfo->WorkingSetSize; 00620 #endif //DBG 00621 #if PFN_CONSISTENCY 00622 KIRQL OldIrql; 00623 #endif 00624 00625 WorkingSetList = WsInfo->VmWorkingSetList; 00626 Wsle = WorkingSetList->Wsle; 00627 00628 WsleSwap = Wsle[SwapEntry]; 00629 00630 ASSERT (WsleSwap.u1.e1.Valid != 0); 00631 00632 WsleEntry = Wsle[Entry]; 00633 00634 Table = WorkingSetList->HashTable; 00635 00636 if (WsleEntry.u1.e1.Valid == 0) { 00637 00638 // 00639 // Entry is not on any list. Remove it from the free list. 00640 // 00641 00642 MiRemoveWsleFromFreeList (Entry, Wsle, WorkingSetList); 00643 00644 // 00645 // Copy the Entry to this free one. 00646 // 00647 00648 Wsle[Entry] = WsleSwap; 00649 00650 PointerPte = MiGetPteAddress (WsleSwap.u1.VirtualAddress); 00651 00652 if (WsleSwap.u1.e1.Direct) { 00653 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 00654 #if PFN_CONSISTENCY 00655 OldIrql = 99; 00656 if (PFN_LOCK_OWNED_BY_ME() == 0) { 00657 LOCK_PFN (OldIrql); 00658 } 00659 #endif 00660 Pfn1->u1.WsIndex = Entry; 00661 #if PFN_CONSISTENCY 00662 if (OldIrql != 99) { 00663 UNLOCK_PFN (OldIrql); 00664 } 00665 #endif 00666 } else { 00667 00668 // 00669 // Update hash table. 00670 // 00671 00672 if (Table) { 00673 Table [ MiLookupWsleHashIndex (WsleSwap.u1.Long, 00674 WorkingSetList)].Index = Entry; 00675 } 00676 } 00677 00678 MI_SET_PTE_IN_WORKING_SET (PointerPte, Entry); 00679 00680 // 00681 // Put entry on free list. 00682 // 00683 00684 ASSERT (WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle); 00685 Wsle[SwapEntry].u1.Long = WorkingSetList->FirstFree << MM_FREE_WSLE_SHIFT; 00686 WorkingSetList->FirstFree = SwapEntry; 00687 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 00688 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 00689 00690 } else { 00691 00692 // 00693 // Both entries are valid. 00694 // 00695 00696 Wsle[SwapEntry] = WsleEntry; 00697 00698 PointerPte = MiGetPteAddress (WsleEntry.u1.VirtualAddress); 00699 00700 if (WsleEntry.u1.e1.Direct) { 00701 00702 // 00703 // Swap the PFN WsIndex element to point to the new slot. 00704 // 00705 00706 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 00707 #if PFN_CONSISTENCY 00708 OldIrql = 99; 00709 if (PFN_LOCK_OWNED_BY_ME() == 0) { 00710 LOCK_PFN (OldIrql); 00711 } 00712 #endif 00713 Pfn1->u1.WsIndex = SwapEntry; 00714 #if PFN_CONSISTENCY 00715 if (OldIrql != 99) { 00716 UNLOCK_PFN (OldIrql); 00717 } 00718 #endif 00719 } else { 00720 00721 // 00722 // Update hash table. 00723 // 00724 00725 if (Table) { 00726 Table[ MiLookupWsleHashIndex (WsleEntry.u1.Long, 00727 WorkingSetList)].Index = SwapEntry; 00728 } 00729 } 00730 00731 MI_SET_PTE_IN_WORKING_SET (PointerPte, SwapEntry); 00732 00733 Wsle[Entry] = WsleSwap; 00734 00735 PointerPte = MiGetPteAddress (WsleSwap.u1.VirtualAddress); 00736 00737 if (WsleSwap.u1.e1.Direct) { 00738 00739 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 00740 #if PFN_CONSISTENCY 00741 OldIrql = 99; 00742 if (PFN_LOCK_OWNED_BY_ME() == 0) { 00743 LOCK_PFN (OldIrql); 00744 } 00745 #endif 00746 Pfn1->u1.WsIndex = Entry; 00747 #if PFN_CONSISTENCY 00748 if (OldIrql != 99) { 00749 UNLOCK_PFN (OldIrql); 00750 } 00751 #endif 00752 } else { 00753 if (Table) { 00754 Table[ MiLookupWsleHashIndex (WsleSwap.u1.Long, 00755 WorkingSetList)].Index = Entry; 00756 } 00757 } 00758 MI_SET_PTE_IN_WORKING_SET (PointerPte, Entry); 00759 } 00760 ASSERT (CurrentSize == WsInfo->WorkingSetSize); 00761 return; 00762 } 00763 00764 ULONG 00765 MiLookupWsleHashIndex ( 00766 IN ULONG_PTR WsleEntry, 00767 IN PMMWSL WorkingSetList 00768 ) 00769 00770 { 00771 ULONG Hash; 00772 ULONG_PTR VirtualAddress; 00773 PMMWSLE_HASH Table; 00774 ULONG Tries = 0; 00775 00776 Table = WorkingSetList->HashTable; 00777 VirtualAddress = WsleEntry & ~(PAGE_SIZE - 1); 00778 00779 Hash = MI_WSLE_HASH(WsleEntry, WorkingSetList); 00780 00781 while (Table[Hash].Key != (ULONG_PTR)VirtualAddress) { 00782 Hash += 1; 00783 if (Hash >= WorkingSetList->HashTableSize) { 00784 Hash = 0; 00785 if (Tries != 0) { 00786 KeBugCheckEx (MEMORY_MANAGEMENT, 00787 0x41884, 00788 (ULONG_PTR)VirtualAddress, 00789 WsleEntry, 00790 (ULONG_PTR)WorkingSetList); 00791 } 00792 Tries = 1; 00793 } 00794 } 00795 return Hash; 00796 } 00797 00798 VOID 00799 MiRemoveWsleFromFreeList ( 00800 IN ULONG Entry, 00801 IN PMMWSLE Wsle, 00802 IN PMMWSL WorkingSetList 00803 ) 00804 00805 /*++ 00806 00807 Routine Description: 00808 00809 This routine removes a working set list entry from the free list. 00810 It is used when the entry required is not the first element 00811 in the free list. 00812 00813 Arguments: 00814 00815 Entry - Supplies the index of the entry to remove. 00816 00817 Wsle - Supplies a pointer to the array of WSLEs. 00818 00819 WorkingSetList - Supplies a pointer to the working set list. 00820 00821 Return Value: 00822 00823 None. 00824 00825 Environment: 00826 00827 Kernel mode, Working set lock and PFN lock held, APCs disabled. 00828 00829 --*/ 00830 00831 { 00832 WSLE_NUMBER Free; 00833 WSLE_NUMBER ParentFree; 00834 00835 Free = WorkingSetList->FirstFree; 00836 00837 if (Entry == Free) { 00838 ASSERT ((Wsle[Entry].u1.Long >> MM_FREE_WSLE_SHIFT) <= WorkingSetList->LastInitializedWsle); 00839 WorkingSetList->FirstFree = (WSLE_NUMBER)(Wsle[Entry].u1.Long >> MM_FREE_WSLE_SHIFT); 00840 00841 } else { 00842 do { 00843 ParentFree = Free; 00844 ASSERT (Wsle[Free].u1.e1.Valid == 0); 00845 Free = (WSLE_NUMBER)(Wsle[Free].u1.Long >> MM_FREE_WSLE_SHIFT); 00846 } while (Free != Entry); 00847 00848 Wsle[ParentFree].u1.Long = Wsle[Entry].u1.Long; 00849 } 00850 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 00851 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 00852 return; 00853 } 00854 00855 00856 #if 0 00857 00858 VOID 00859 MiSwapWslEntries ( 00860 IN ULONG Entry, 00861 IN ULONG Parent, 00862 IN ULONG SwapEntry, 00863 IN PMMWSL WorkingSetList 00864 ) 00865 00866 /*++ 00867 00868 Routine Description: 00869 00870 This function swaps the specified entry and updates its parent with 00871 the specified swap entry. 00872 00873 The entry must be valid, i.e., the page is resident. The swap entry 00874 can be valid or on the free list. 00875 00876 Arguments: 00877 00878 Entry - The index of the WSLE to swap. 00879 00880 Parent - The index of the parent of the WSLE to swap. 00881 00882 SwapEntry - The index to swap the entry with. 00883 00884 Return Value: 00885 00886 None. 00887 00888 Environment: 00889 00890 Kernel mode, working set mutex held, APCs disabled. 00891 00892 --*/ 00893 00894 { 00895 00896 ULONG SwapParent; 00897 ULONG SavedRight; 00898 ULONG SavedLeft; 00899 ULONG Free; 00900 ULONG ParentFree; 00901 ULONG SavedLong; 00902 PVOID VirtualAddress; 00903 PMMWSLE Wsle; 00904 PMMPFN Pfn1; 00905 PMMPTE PointerPte; 00906 00907 Wsle = WorkingSetList->Wsle; 00908 00909 if (Wsle[SwapEntry].u1.e1.Valid == 0) { 00910 00911 // 00912 // This entry is not in use and must be removed from 00913 // the free list. 00914 // 00915 00916 Free = WorkingSetList->FirstFree; 00917 00918 if (SwapEntry == Free) { 00919 WorkingSetList->FirstFree = Entry; 00920 ASSERT ((WorkingSetList->FirstFree <= WorkingSetList->LastInitializedWsle) || 00921 (WorkingSetList->FirstFree == WSLE_NULL_INDEX)); 00922 00923 } else { 00924 00925 while (Free != SwapEntry) { 00926 ParentFree = Free; 00927 Free = Wsle[Free].u2.s.LeftChild; 00928 } 00929 00930 Wsle[ParentFree].u2.s.LeftChild = Entry; 00931 } 00932 00933 // 00934 // Swap the previous entry and the new unused entry. 00935 // 00936 00937 SavedLeft = Wsle[Entry].u2.s.LeftChild; 00938 Wsle[Entry].u2.s.LeftChild = Wsle[SwapEntry].u2.s.LeftChild; 00939 Wsle[SwapEntry].u2.s.LeftChild = SavedLeft; 00940 Wsle[SwapEntry].u2.s.RightChild = Wsle[Entry].u2.s.RightChild; 00941 Wsle[SwapEntry].u1.Long = Wsle[Entry].u1.Long; 00942 Wsle[Entry].u1.Long = 0; 00943 00944 // 00945 // Make the parent point to the new entry. 00946 // 00947 00948 if (Parent == WSLE_NULL_INDEX) { 00949 00950 // 00951 // This entry is not in the tree. 00952 // 00953 00954 PointerPte = MiGetPteAddress (Wsle[SwapEntry].u1.VirtualAddress); 00955 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 00956 Pfn1->u1.WsIndex = SwapEntry; 00957 return; 00958 } 00959 00960 if (Parent == Entry) { 00961 00962 // 00963 // This element is the root, update the root pointer. 00964 // 00965 00966 WorkingSetList->Root = SwapEntry; 00967 00968 } else { 00969 00970 if (Wsle[Parent].u2.s.LeftChild == Entry) { 00971 Wsle[Parent].u2.s.LeftChild = SwapEntry; 00972 } else { 00973 ASSERT (Wsle[Parent].u2.s.RightChild == Entry); 00974 00975 Wsle[Parent].u2.s.RightChild = SwapEntry; 00976 } 00977 } 00978 00979 } else { 00980 00981 if ((Parent == WSLE_NULL_INDEX) && 00982 (Wsle[SwapEntry].u2.BothPointers == 0)) { 00983 00984 // 00985 // Neither entry is in the tree, just swap their pointers. 00986 // 00987 00988 SavedLong = Wsle[SwapEntry].u1.Long; 00989 Wsle[SwapEntry].u1.Long = Wsle[Entry].u1.Long; 00990 Wsle[Entry].u1.Long = SavedLong; 00991 00992 PointerPte = MiGetPteAddress (Wsle[Entry].u1.VirtualAddress); 00993 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 00994 Pfn1->u1.WsIndex = Entry; 00995 00996 PointerPte = MiGetPteAddress (Wsle[SwapEntry].u1.VirtualAddress); 00997 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 00998 Pfn1->u1.WsIndex = SwapEntry; 00999 01000 return; 01001 } 01002 01003 // 01004 // The entry at FirstDynamic is valid; swap it with this one and 01005 // update both parents. 01006 // 01007 01008 SwapParent = WorkingSetList->Root; 01009 01010 if (SwapParent == SwapEntry) { 01011 01012 // 01013 // The entry we are swapping with is at the root. 01014 // 01015 01016 if (Wsle[SwapEntry].u2.s.LeftChild == Entry) { 01017 01018 // 01019 // The entry we are going to swap is the left child of this 01020 // entry. 01021 // 01022 // R(SwapEntry) 01023 // / \ 01024 // (entry) 01025 // 01026 01027 WorkingSetList->Root = Entry; 01028 01029 Wsle[SwapEntry].u2.s.LeftChild = Wsle[Entry].u2.s.LeftChild; 01030 Wsle[Entry].u2.s.LeftChild = SwapEntry; 01031 SavedRight = Wsle[SwapEntry].u2.s.RightChild; 01032 Wsle[SwapEntry].u2.s.RightChild = Wsle[Entry].u2.s.RightChild; 01033 Wsle[Entry].u2.s.RightChild = SavedRight; 01034 01035 SavedLong = Wsle[Entry].u1.Long; 01036 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01037 Wsle[SwapEntry].u1.Long = SavedLong; 01038 01039 return; 01040 01041 } else { 01042 01043 if (Wsle[SwapEntry].u2.s.RightChild == Entry) { 01044 01045 // 01046 // The entry we are going to swap is the right child of this 01047 // entry. 01048 // 01049 // R(SwapEntry) 01050 // / \ 01051 // (entry) 01052 // 01053 01054 WorkingSetList->Root = Entry; 01055 01056 Wsle[SwapEntry].u2.s.RightChild = Wsle[Entry].u2.s.RightChild; 01057 Wsle[Entry].u2.s.RightChild = SwapEntry; 01058 SavedLeft = Wsle[SwapEntry].u2.s.LeftChild; 01059 Wsle[SwapEntry].u2.s.LeftChild = Wsle[Entry].u2.s.LeftChild; 01060 Wsle[Entry].u2.s.LeftChild = SavedLeft; 01061 01062 01063 SavedLong = Wsle[Entry].u1.Long; 01064 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01065 Wsle[SwapEntry].u1.Long = SavedLong; 01066 01067 return; 01068 } 01069 } 01070 01071 // 01072 // The swap entry is the root, but the other entry is not 01073 // its child. 01074 // 01075 // 01076 // R(SwapEntry) 01077 // / \ 01078 // ..... 01079 // Parent(Entry) 01080 // \ 01081 // Entry (left or right) 01082 // 01083 // 01084 01085 WorkingSetList->Root = Entry; 01086 01087 SavedRight = Wsle[SwapEntry].u2.s.RightChild; 01088 Wsle[SwapEntry].u2.s.RightChild = Wsle[Entry].u2.s.RightChild; 01089 Wsle[Entry].u2.s.RightChild = SavedRight; 01090 SavedLeft = Wsle[SwapEntry].u2.s.LeftChild; 01091 Wsle[SwapEntry].u2.s.LeftChild = Wsle[Entry].u2.s.LeftChild; 01092 Wsle[Entry].u2.s.LeftChild = SavedLeft; 01093 01094 SavedLong = Wsle[Entry].u1.Long; 01095 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01096 Wsle[SwapEntry].u1.Long = SavedLong; 01097 01098 if (Parent == WSLE_NULL_INDEX) { 01099 01100 // 01101 // This entry is not in the tree. 01102 // 01103 01104 PointerPte = MiGetPteAddress (Wsle[SwapEntry].u1.VirtualAddress); 01105 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01106 Pfn1->u1.WsIndex = SwapEntry; 01107 return; 01108 } 01109 01110 // 01111 // Change the parent of the entry to point to the swap entry. 01112 // 01113 01114 if (Wsle[Parent].u2.s.RightChild == Entry) { 01115 Wsle[Parent].u2.s.RightChild = SwapEntry; 01116 } else { 01117 Wsle[Parent].u2.s.LeftChild = SwapEntry; 01118 } 01119 01120 return; 01121 01122 } 01123 01124 // 01125 // The SwapEntry is not the root, find its parent. 01126 // 01127 01128 if (Wsle[SwapEntry].u2.BothPointers == 0) { 01129 01130 // 01131 // Entry is not in tree, therefore no parent. 01132 01133 SwapParent = WSLE_NULL_INDEX; 01134 01135 } else { 01136 01137 VirtualAddress = PAGE_ALIGN(Wsle[SwapEntry].u1.VirtualAddress); 01138 01139 for (;;) { 01140 01141 ASSERT (SwapParent != WSLE_NULL_INDEX); 01142 01143 if (Wsle[SwapParent].u2.s.LeftChild == SwapEntry) { 01144 break; 01145 } 01146 if (Wsle[SwapParent].u2.s.RightChild == SwapEntry) { 01147 break; 01148 } 01149 01150 01151 if (VirtualAddress < PAGE_ALIGN(Wsle[SwapParent].u1.VirtualAddress)) { 01152 SwapParent = Wsle[SwapParent].u2.s.LeftChild; 01153 } else { 01154 SwapParent = Wsle[SwapParent].u2.s.RightChild; 01155 } 01156 } 01157 } 01158 01159 if (Parent == WorkingSetList->Root) { 01160 01161 // 01162 // The entry is at the root. 01163 // 01164 01165 if (Wsle[Entry].u2.s.LeftChild == SwapEntry) { 01166 01167 // 01168 // The entry we are going to swap is the left child of this 01169 // entry. 01170 // 01171 // R(Entry) 01172 // / \ 01173 // (SwapEntry) 01174 // 01175 01176 WorkingSetList->Root = SwapEntry; 01177 01178 Wsle[Entry].u2.s.LeftChild = Wsle[SwapEntry].u2.s.LeftChild; 01179 Wsle[SwapEntry].u2.s.LeftChild = Entry; 01180 SavedRight = Wsle[Entry].u2.s.RightChild; 01181 Wsle[Entry].u2.s.RightChild = Wsle[SwapEntry].u2.s.RightChild; 01182 Wsle[SwapEntry].u2.s.RightChild = SavedRight; 01183 01184 SavedLong = Wsle[Entry].u1.Long; 01185 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01186 Wsle[SwapEntry].u1.Long = SavedLong; 01187 01188 return; 01189 01190 } else if (Wsle[SwapEntry].u2.s.RightChild == Entry) { 01191 01192 // 01193 // The entry we are going to swap is the right child of this 01194 // entry. 01195 // 01196 // R(SwapEntry) 01197 // / \ 01198 // (entry) 01199 // 01200 01201 WorkingSetList->Root = Entry; 01202 01203 Wsle[SwapEntry].u2.s.RightChild = Wsle[Entry].u2.s.RightChild; 01204 Wsle[Entry].u2.s.RightChild = SwapEntry; 01205 SavedLeft = Wsle[SwapEntry].u2.s.LeftChild; 01206 Wsle[SwapEntry].u2.s.LeftChild = Wsle[Entry].u2.s.LeftChild; 01207 Wsle[Entry].u2.s.LeftChild = SavedLeft; 01208 01209 01210 SavedLong = Wsle[Entry].u1.Long; 01211 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01212 Wsle[SwapEntry].u1.Long = SavedLong; 01213 01214 return; 01215 } 01216 01217 // 01218 // The swap entry is the root, but the other entry is not 01219 // its child. 01220 // 01221 // 01222 // R(SwapEntry) 01223 // / \ 01224 // ..... 01225 // Parent(Entry) 01226 // \ 01227 // Entry (left or right) 01228 // 01229 // 01230 01231 WorkingSetList->Root = Entry; 01232 01233 SavedRight = Wsle[SwapEntry].u2.s.RightChild; 01234 Wsle[SwapEntry].u2.s.RightChild = Wsle[Entry].u2.s.RightChild; 01235 Wsle[Entry].u2.s.RightChild = SavedRight; 01236 SavedLeft = Wsle[SwapEntry].u2.s.LeftChild; 01237 Wsle[SwapEntry].u2.s.LeftChild = Wsle[Entry].u2.s.LeftChild; 01238 Wsle[Entry].u2.s.LeftChild = SavedLeft; 01239 01240 SavedLong = Wsle[Entry].u1.Long; 01241 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01242 Wsle[SwapEntry].u1.Long = SavedLong; 01243 01244 if (SwapParent == WSLE_NULL_INDEX) { 01245 01246 // 01247 // This entry is not in the tree. 01248 // 01249 01250 PointerPte = MiGetPteAddress (Wsle[Entry].u1.VirtualAddress); 01251 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01252 ASSERT (Pfn1->u1.WsIndex == SwapEntry); 01253 Pfn1->u1.WsIndex = Entry; 01254 return; 01255 } 01256 01257 // 01258 // Change the parent of the entry to point to the swap entry. 01259 // 01260 01261 if (Wsle[SwapParent].u2.s.RightChild == SwapEntry) { 01262 Wsle[SwapParent].u2.s.RightChild = Entry; 01263 } else { 01264 Wsle[SwapParent].u2.s.LeftChild = Entry; 01265 } 01266 01267 return; 01268 01269 } 01270 01271 // 01272 // Neither entry is the root. 01273 // 01274 01275 if (Parent == SwapEntry) { 01276 01277 // 01278 // The parent of the entry is the swap entry. 01279 // 01280 // 01281 // R 01282 // ..... 01283 // 01284 // (SwapParent) 01285 // | 01286 // (SwapEntry) 01287 // | 01288 // (Entry) 01289 // 01290 01291 // 01292 // Update the parent pointer for the swapentry. 01293 // 01294 01295 if (Wsle[SwapParent].u2.s.LeftChild == SwapEntry) { 01296 Wsle[SwapParent].u2.s.LeftChild = Entry; 01297 } else { 01298 Wsle[SwapParent].u2.s.RightChild = Entry; 01299 } 01300 01301 // 01302 // Determine if this goes left or right. 01303 // 01304 01305 if (Wsle[SwapEntry].u2.s.LeftChild == Entry) { 01306 01307 // 01308 // The entry we are going to swap is the left child of this 01309 // entry. 01310 // 01311 // R 01312 // ..... 01313 // 01314 // (SwapParent) 01315 // 01316 // (SwapEntry) [Parent(entry)] 01317 // / \ 01318 // (entry) 01319 // 01320 01321 Wsle[SwapEntry].u2.s.LeftChild = Wsle[Entry].u2.s.LeftChild; 01322 Wsle[Entry].u2.s.LeftChild = SwapEntry; 01323 SavedRight = Wsle[SwapEntry].u2.s.RightChild; 01324 Wsle[SwapEntry].u2.s.RightChild = Wsle[Entry].u2.s.RightChild; 01325 Wsle[Entry].u2.s.RightChild = SavedRight; 01326 01327 SavedLong = Wsle[Entry].u1.Long; 01328 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01329 Wsle[SwapEntry].u1.Long = SavedLong; 01330 01331 return; 01332 01333 } else { 01334 01335 ASSERT (Wsle[SwapEntry].u2.s.RightChild == Entry); 01336 01337 // 01338 // The entry we are going to swap is the right child of this 01339 // entry. 01340 // 01341 // R 01342 // ..... 01343 // 01344 // (SwapParent) 01345 // \ 01346 // (SwapEntry) 01347 // / \ 01348 // (entry) 01349 // 01350 01351 Wsle[SwapEntry].u2.s.RightChild = Wsle[Entry].u2.s.RightChild; 01352 Wsle[Entry].u2.s.RightChild = SwapEntry; 01353 SavedLeft = Wsle[SwapEntry].u2.s.LeftChild; 01354 Wsle[SwapEntry].u2.s.LeftChild = Wsle[Entry].u2.s.LeftChild; 01355 Wsle[Entry].u2.s.LeftChild = SavedLeft; 01356 01357 01358 SavedLong = Wsle[Entry].u1.Long; 01359 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01360 Wsle[SwapEntry].u1.Long = SavedLong; 01361 01362 return; 01363 } 01364 01365 01366 } 01367 if (SwapParent == Entry) { 01368 01369 01370 // 01371 // The parent of the swap entry is the entry. 01372 // 01373 // R 01374 // ..... 01375 // 01376 // (Parent) 01377 // | 01378 // (Entry) 01379 // | 01380 // (SwapEntry) 01381 // 01382 01383 // 01384 // Update the parent pointer for the entry. 01385 // 01386 01387 if (Wsle[Parent].u2.s.LeftChild == Entry) { 01388 Wsle[Parent].u2.s.LeftChild = SwapEntry; 01389 } else { 01390 Wsle[Parent].u2.s.RightChild = SwapEntry; 01391 } 01392 01393 // 01394 // Determine if this goes left or right. 01395 // 01396 01397 if (Wsle[Entry].u2.s.LeftChild == SwapEntry) { 01398 01399 // 01400 // The entry we are going to swap is the left child of this 01401 // entry. 01402 // 01403 // R 01404 // ..... 01405 // 01406 // (Parent) 01407 // | 01408 // (Entry) 01409 // / 01410 // (SwapEntry) 01411 // 01412 01413 Wsle[Entry].u2.s.LeftChild = Wsle[SwapEntry].u2.s.LeftChild; 01414 Wsle[SwapEntry].u2.s.LeftChild = Entry; 01415 SavedRight = Wsle[Entry].u2.s.RightChild; 01416 Wsle[Entry].u2.s.RightChild = Wsle[SwapEntry].u2.s.RightChild; 01417 Wsle[SwapEntry].u2.s.RightChild = SavedRight; 01418 01419 SavedLong = Wsle[Entry].u1.Long; 01420 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01421 Wsle[SwapEntry].u1.Long = SavedLong; 01422 01423 return; 01424 01425 } else { 01426 01427 ASSERT (Wsle[Entry].u2.s.RightChild == SwapEntry); 01428 01429 // 01430 // The entry we are going to swap is the right child of this 01431 // entry. 01432 // 01433 // R(Entry) 01434 // / \ 01435 // (SwapEntry) 01436 // 01437 01438 Wsle[Entry].u2.s.RightChild = Wsle[SwapEntry].u2.s.RightChild; 01439 Wsle[SwapEntry].u2.s.RightChild = Entry; 01440 SavedLeft = Wsle[SwapEntry].u2.s.LeftChild; 01441 Wsle[SwapEntry].u2.s.LeftChild = Wsle[Entry].u2.s.LeftChild; 01442 Wsle[Entry].u2.s.LeftChild = SavedLeft; 01443 01444 SavedLong = Wsle[Entry].u1.Long; 01445 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01446 Wsle[SwapEntry].u1.Long = SavedLong; 01447 01448 return; 01449 } 01450 01451 } 01452 01453 // 01454 // Neither entry is the parent of the other. Just swap them 01455 // and update the parent entries. 01456 // 01457 01458 if (Parent == WSLE_NULL_INDEX) { 01459 01460 // 01461 // This entry is not in the tree. 01462 // 01463 01464 PointerPte = MiGetPteAddress (Wsle[Entry].u1.VirtualAddress); 01465 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01466 ASSERT (Pfn1->u1.WsIndex == Entry); 01467 Pfn1->u1.WsIndex = SwapEntry; 01468 01469 } else { 01470 01471 if (Wsle[Parent].u2.s.LeftChild == Entry) { 01472 Wsle[Parent].u2.s.LeftChild = SwapEntry; 01473 } else { 01474 Wsle[Parent].u2.s.RightChild = SwapEntry; 01475 } 01476 } 01477 01478 if (SwapParent == WSLE_NULL_INDEX) { 01479 01480 // 01481 // This entry is not in the tree. 01482 // 01483 01484 PointerPte = MiGetPteAddress (Wsle[SwapEntry].u1.VirtualAddress); 01485 Pfn1 = MI_PFN_ELEMENT (PointerPte->u.Hard.PageFrameNumber); 01486 ASSERT (Pfn1->u1.WsIndex == SwapEntry); 01487 Pfn1->u1.WsIndex = Entry; 01488 } else { 01489 01490 if (Wsle[SwapParent].u2.s.LeftChild == SwapEntry) { 01491 Wsle[SwapParent].u2.s.LeftChild = Entry; 01492 } else { 01493 Wsle[SwapParent].u2.s.RightChild = Entry; 01494 } 01495 } 01496 01497 SavedRight = Wsle[SwapEntry].u2.s.RightChild; 01498 Wsle[SwapEntry].u2.s.RightChild = Wsle[Entry].u2.s.RightChild; 01499 Wsle[Entry].u2.s.RightChild = SavedRight; 01500 SavedLeft = Wsle[SwapEntry].u2.s.LeftChild; 01501 Wsle[SwapEntry].u2.s.LeftChild = Wsle[Entry].u2.s.LeftChild; 01502 Wsle[Entry].u2.s.LeftChild = SavedLeft; 01503 01504 SavedLong = Wsle[Entry].u1.Long; 01505 Wsle[Entry].u1.Long = Wsle[SwapEntry].u1.Long; 01506 Wsle[SwapEntry].u1.Long = SavedLong; 01507 01508 return; 01509 } 01510 } 01511 #endif //0

Generated on Sat May 15 19:42:29 2004 for test by doxygen 1.3.7