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

wsmanage.c File Reference

#include "mi.h"

Go to the source code of this file.

Classes

union  _MMWS_TRIM_CRITERIA

Defines

#define MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM   (6)
#define MM_REDUCE_FAULT_COUNT   (10000)
#define MM_IGNORE_FAULT_COUNT   (100)
#define MM_WS_REORG_BUCKETS_MAX   7

Typedefs

typedef _MMWS_TRIM_CRITERIA MMWS_TRIM_CRITERIA
typedef _MMWS_TRIM_CRITERIAPMMWS_TRIM_CRITERIA

Functions

VOID MiEmptyAllWorkingSetsWorker (VOID)
LOGICAL MiCheckAndSetSystemTrimCriteria (IN OUT PMMWS_TRIM_CRITERIA Criteria)
BOOLEAN MiCheckSystemTrimEndCriteria (IN OUT PMMWS_TRIM_CRITERIA Criteria, IN KIRQL OldIrql)
BOOLEAN MiCheckProcessTrimCriteria (IN PMMWS_TRIM_CRITERIA Criteria, IN PMMSUPPORT VmSupport, IN PEPROCESS Process, IN PLARGE_INTEGER CurrentTime)
LOGICAL MiCheckSystemCacheWsTrimCriteria (IN PMMSUPPORT VmSupport)
ULONG MiDetermineWsTrimAmount (IN PMMWS_TRIM_CRITERIA Criteria, IN PMMSUPPORT VmSupport, IN PEPROCESS Process)
VOID MiRearrangeWorkingSetExpansionList (VOID)
VOID MiAdjustWorkingSetManagerParameters (BOOLEAN WorkStation)
VOID MiObtainFreePages (VOID)
VOID MmWorkingSetManager (VOID)
LOGICAL MiCheckAndSetSystemTrimCriteria (PMMWS_TRIM_CRITERIA Criteria)
BOOLEAN MiCheckSystemTrimEndCriteria (IN PMMWS_TRIM_CRITERIA Criteria, IN KIRQL OldIrql)
BOOLEAN MiCheckProcessTrimCriteria (PMMWS_TRIM_CRITERIA Criteria, PMMSUPPORT VmSupport, PEPROCESS Process, PLARGE_INTEGER CurrentTime)
LOGICAL MiCheckSystemCacheWsTrimCriteria (PMMSUPPORT VmSupport)
ULONG MiDetermineWsTrimAmount (PMMWS_TRIM_CRITERIA Criteria, PMMSUPPORT VmSupport, PEPROCESS Process)
VOID MiEmptyAllWorkingSets (VOID)
LOGICAL MmTrimAllSystemPagableMemory (IN LOGICAL PurgeTransition)

Variables

ULONG MiIdealPassFaultCountDisable
ULONG PsMinimumWorkingSet
PEPROCESS ExpDefaultErrorPortProcess
KEVENT MiWaitForEmptyEvent
BOOLEAN MiWaitingForWorkingSetEmpty
PFN_NUMBER MmMoreThanEnoughFreePages = 1000
ULONG MmAmpleFreePages = 200
ULONG MmWorkingSetReductionMin = 12
ULONG MmWorkingSetReductionMinCacheWs = 12
ULONG MmWorkingSetReductionMax = 60
ULONG MmWorkingSetReductionMaxCacheWs = 60
ULONG MmWorkingSetReductionHuge = (512*1024) >> PAGE_SHIFT
ULONG MmWorkingSetVolReductionMin = 12
ULONG MmWorkingSetVolReductionMax = 60
ULONG MmWorkingSetVolReductionMaxCacheWs = 60
ULONG MmWorkingSetVolReductionHuge = (2*1024*1024) >> PAGE_SHIFT
ULONG MmWorkingSetSwapReduction = 75
ULONG MmWorkingSetSwapReductionHuge = (4*1024*1024) >> PAGE_SHIFT
ULONG MmNumberOfForegroundProcesses
ULONG MiCheckCounter
ULONG MmLastFaultCount
PVOID MmPagableKernelStart
PVOID MmPagableKernelEnd
 PERFINFO_WSMANAGE_GLOBAL_DECL
LONG MiTrimInProgressCount = 1
ULONG MiTrimAllPageFaultCount


Define Documentation

#define MM_IGNORE_FAULT_COUNT   (100)
 

Definition at line 117 of file wsmanage.c.

Referenced by MiCheckAndSetSystemTrimCriteria().

#define MM_REDUCE_FAULT_COUNT   (10000)
 

Definition at line 115 of file wsmanage.c.

Referenced by MiCheckAndSetSystemTrimCriteria().

#define MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM   (6)
 

Definition at line 101 of file wsmanage.c.

Referenced by MiCheckAndSetSystemTrimCriteria(), MiCheckProcessTrimCriteria(), MiCheckSystemCacheWsTrimCriteria(), MiDetermineWsTrimAmount(), and MmWorkingSetManager().

#define MM_WS_REORG_BUCKETS_MAX   7
 

Definition at line 2458 of file wsmanage.c.

Referenced by MiRearrangeWorkingSetExpansionList().


Typedef Documentation

typedef union _MMWS_TRIM_CRITERIA MMWS_TRIM_CRITERIA
 

typedef union _MMWS_TRIM_CRITERIA * PMMWS_TRIM_CRITERIA
 


Function Documentation

VOID MiAdjustWorkingSetManagerParameters BOOLEAN  WorkStation  ) 
 

Definition at line 259 of file wsmanage.c.

References FALSE, KeInitializeEvent, MiIdealPassFaultCountDisable, MiWaitForEmptyEvent, MiWaitingForWorkingSetEmpty, MmNumberOfPhysicalPages, MmWorkingSetReductionMax, MmWorkingSetReductionMin, MmWorkingSetVolReductionMax, PAGE_SIZE, and TRUE.

Referenced by MmInitSystem().

00264 : 00265 00266 This function is called from MmInitSystem to adjust the working set manager 00267 trim algorithms based on system type and size. 00268 00269 Arguments: 00270 00271 WorkStation - TRUE if this is a workstation, FALSE if not. 00272 00273 Return Value: 00274 00275 None. 00276 00277 Environment: 00278 00279 Kernel mode 00280 00281 --*/ 00282 { 00283 00284 #ifdef _MI_USE_CLAIMS_ 00285 00286 if (WorkStation && MmNumberOfPhysicalPages <= 63*1024*1024/PAGE_SIZE) { 00287 MiAgingShift = 4; 00288 MiEstimationShift = 5; 00289 } 00290 else { 00291 MiAgingShift = 5; 00292 MiEstimationShift = 6; 00293 } 00294 00295 if (MmNumberOfPhysicalPages >= 63*1024*1024/PAGE_SIZE) { 00296 MmPlentyFreePages *= 2; 00297 } 00298 #else 00299 00300 if (WorkStation && (MmNumberOfPhysicalPages <= (31*1024*1024/PAGE_SIZE))) { 00301 00302 // 00303 // To get fault protection, you have to take 45 faults instead of 00304 // the old 15 fault protection threshold. 00305 // 00306 00307 MiIdealPassFaultCountDisable = 45; 00308 00309 // 00310 // Take more away when you are over your working set in both 00311 // forced and voluntary mode, but leave cache WS trim amounts 00312 // alone. 00313 // 00314 00315 MmWorkingSetVolReductionMax = 100; 00316 MmWorkingSetReductionMax = 100; 00317 00318 // 00319 // In forced mode, even if you are within your working set, take 00320 // memory away more aggressively. 00321 // 00322 00323 MmWorkingSetReductionMin = 40; 00324 } 00325 else { 00326 MiIdealPassFaultCountDisable = 15; 00327 } 00328 #endif 00329 00330 MiWaitingForWorkingSetEmpty = FALSE; 00331 KeInitializeEvent (&MiWaitForEmptyEvent, NotificationEvent, TRUE); 00332 }

LOGICAL MiCheckAndSetSystemTrimCriteria PMMWS_TRIM_CRITERIA  Criteria  ) 
 

Definition at line 996 of file wsmanage.c.

References DbgPrint, _MMWS_TRIM_CRITERIA::DesiredFreeGoal, FALSE, _MMWS_TRIM_CRITERIA::FaultBased, KeSetEvent(), LOCK_EXPANSION, LOCK_PFN, MiCheckCounter, MiEmptyAllWorkingSetsWorker(), MiHydra, MiIdealPassFaultCountDisable, MiRearrangeWorkingSetExpansionList(), MiWaitForEmptyEvent, MiWaitingForWorkingSetEmpty, MM_DBG_WS_EXPANSION, MM_IGNORE_FAULT_COUNT, MM_REDUCE_FAULT_COUNT, MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM, MmAmpleFreePages, MmAvailablePages, MmFreeGoal, MmInfoCounters, MmLastFaultCount, MmMinimumFreePages, MmMoreThanEnoughFreePages, MmNumberOfPhysicalPages, MmPagesAboveWsMinimum, _MMWS_TRIM_CRITERIA::NumberOfForegroundProcesses, _MMWS_TRIM_CRITERIA::NumPasses, _MMINFO_COUNTERS::PageFaultCount, PERFINFO_WSMANAGE_DECL, PERFINFO_WSMANAGE_DUMPENTRIES_CLAIMS, PERFINFO_WSMANAGE_DUMPENTRIES_FAULTS, PERFINFO_WSMANAGE_STARTLOG_CLAIMS, PERFINFO_WSMANAGE_STARTLOG_FAULTS, PERFINFO_WSMANAGE_TRIMACTION, PERFINFO_WSMANAGE_WILLTRIM_CLAIMS, PERFINFO_WSMANAGE_WILLTRIM_FAULTS, TRUE, UNLOCK_EXPANSION, and UNLOCK_PFN.

Referenced by MmWorkingSetManager().

01002 : 01003 01004 Decide whether to trim at this time. If using claims, then this 01005 routine may initiate aging and claim adjustments as well. 01006 01007 Arguments: 01008 01009 Criteria - Supplies a pointer to the trim criteria information. Various 01010 fields in this structure are set as needed by this routine. 01011 01012 Return Value: 01013 01014 TRUE if the caller should initiate trimming, FALSE if not. 01015 01016 Environment: 01017 01018 Kernel mode. No locks held. APC level or below. 01019 01020 --*/ 01021 01022 { 01023 PFN_NUMBER Available; 01024 ULONG PageFaultCount; 01025 KIRQL OldIrql; 01026 BOOLEAN InitiateTrim; 01027 01028 PERFINFO_WSMANAGE_DECL(); 01029 01030 // 01031 // See if an empty-all-working-sets request has been queued to us. 01032 // This only happens on Hydra. 01033 // 01034 01035 if (MiWaitingForWorkingSetEmpty == TRUE) { 01036 01037 MiEmptyAllWorkingSetsWorker (); 01038 01039 LOCK_EXPANSION (OldIrql); 01040 01041 KeSetEvent (&MiWaitForEmptyEvent, 0, FALSE); 01042 MiWaitingForWorkingSetEmpty = FALSE; 01043 01044 UNLOCK_EXPANSION (OldIrql); 01045 01046 #ifdef _MI_USE_CLAIMS_ 01047 MiReplacing = FALSE; 01048 #endif 01049 01050 return FALSE; 01051 } 01052 01053 // 01054 // Check the number of pages available to see if any trimming 01055 // is really required. 01056 // 01057 01058 LOCK_PFN (OldIrql); 01059 Available = MmAvailablePages; 01060 PageFaultCount = MmInfoCounters.PageFaultCount; 01061 UNLOCK_PFN (OldIrql); 01062 01063 #ifdef _MI_USE_CLAIMS_ 01064 PERFINFO_WSMANAGE_STARTLOG_CLAIMS(); 01065 if (Available > MmPlentyFreePages && MiReplacing == FALSE) { 01066 01067 // 01068 // Don't trim but do age unused pages and estimate 01069 // the amount available in working sets. 01070 // 01071 01072 MiAgePagesAndEstimateClaims (); 01073 MiAdjustClaimParameters (TRUE); 01074 PERFINFO_WSMANAGE_TRIMACTION (WS_ACTION_RESET_COUNTER); 01075 } 01076 else { 01077 01078 // 01079 // Inform our caller to start trimming since we're below 01080 // plenty pages - order the list so the bigger working sets are 01081 // in front so our caller trims those first. 01082 // 01083 01084 Criteria->ClaimBased.NumPasses = 0; 01085 Criteria->ClaimBased.DesiredFreeGoal = MmPlentyFreePages + 01086 (MmPlentyFreePages / 2); 01087 Criteria->ClaimBased.NewTotalClaim = 0; 01088 Criteria->ClaimBased.NewTotalEstimatedAvailable = 0; 01089 Criteria->ClaimBased.NumberOfForegroundProcesses = 0; 01090 01091 // 01092 // Start trimming the bigger working sets first. 01093 // 01094 01095 MiRearrangeWorkingSetExpansionList (); 01096 01097 #if DBG 01098 if (MmDebug & MM_DBG_WS_EXPANSION) { 01099 DbgPrint("\nMM-wsmanage: Desired = %ld, Avail %ld\n", 01100 Criteria->ClaimBased.DesiredFreeGoal, MmAvailablePages); 01101 } 01102 #endif //DBG 01103 01104 PERFINFO_WSMANAGE_WILLTRIM_CLAIMS(Criteria); 01105 01106 MiReplacing = FALSE; 01107 01108 return TRUE; 01109 } 01110 PERFINFO_WSMANAGE_DUMPENTRIES_CLAIMS(); 01111 01112 // 01113 // If we've been replacing within a given working set, it's worth doing 01114 // a trim. No need to lock synchronize the MiReplacing clearing as it 01115 // gets set every time a page replacement happens anyway. 01116 // 01117 01118 InitiateTrim = MiReplacing; 01119 01120 MiReplacing = FALSE; 01121 01122 return InitiateTrim; 01123 01124 #else 01125 01126 PERFINFO_WSMANAGE_STARTLOG_FAULTS(); 01127 01128 if ((Available > (MmNumberOfPhysicalPages >> 2)) || 01129 ((Available > MmMoreThanEnoughFreePages) && 01130 ((PageFaultCount - MmLastFaultCount) < MM_REDUCE_FAULT_COUNT))) { 01131 01132 // 01133 // Don't trim and zero the check counter. 01134 // 01135 01136 MiCheckCounter = 0; 01137 PERFINFO_WSMANAGE_TRIMACTION(WS_ACTION_RESET_COUNTER); 01138 01139 } else if ((Available > MmAmpleFreePages) && 01140 ((PageFaultCount - MmLastFaultCount) < MM_IGNORE_FAULT_COUNT)) { 01141 01142 // 01143 // Don't do anything. 01144 // 01145 01146 NOTHING; 01147 PERFINFO_WSMANAGE_TRIMACTION(WS_ACTION_NOTHING); 01148 01149 } else if ((Available > MmFreeGoal) && 01150 (MiCheckCounter < MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM)) { 01151 01152 // 01153 // Don't trim, but increment the check counter. 01154 // 01155 01156 MiCheckCounter += 1; 01157 PERFINFO_WSMANAGE_TRIMACTION(WS_ACTION_INCREMENT_COUNTER); 01158 01159 } 01160 else { 01161 01162 // 01163 // Initialize state variables. 01164 // 01165 01166 Criteria->FaultBased.NumPasses = 0; 01167 Criteria->FaultBased.TotalReduction = 0; 01168 Criteria->FaultBased.NumberOfForegroundProcesses = 0; 01169 01170 // 01171 // Set the total reduction goals. 01172 // 01173 01174 Criteria->FaultBased.DesiredReductionGoal = MmPagesAboveWsMinimum >> 2; 01175 if (MmPagesAboveWsMinimum > (MmFreeGoal << 1)) { 01176 Criteria->FaultBased.DesiredFreeGoal = MmFreeGoal; 01177 } 01178 else { 01179 Criteria->FaultBased.DesiredFreeGoal = MmMinimumFreePages + 10; 01180 } 01181 01182 // 01183 // Calculate the number of faults to be taken to not be trimmed. 01184 // 01185 01186 if (Available > MmMoreThanEnoughFreePages) { 01187 Criteria->FaultBased.FaultCount = 1; 01188 } 01189 else { 01190 Criteria->FaultBased.FaultCount = MiIdealPassFaultCountDisable; 01191 } 01192 01193 #if DBG 01194 if (MmDebug & MM_DBG_WS_EXPANSION) { 01195 DbgPrint("\nMM-wsmanage: checkcounter = %ld, Desired = %ld, Free = %ld Avail %ld\n", 01196 MiCheckCounter, Criteria->FaultBased.DesiredReductionGoal, 01197 Criteria->FaultBased.DesiredFreeGoal, MmAvailablePages); 01198 } 01199 #endif //DBG 01200 01201 PERFINFO_WSMANAGE_WILLTRIM_FAULTS(Criteria); 01202 01203 if (MiHydra == TRUE) { 01204 MiRearrangeWorkingSetExpansionList (); 01205 } 01206 01207 MmLastFaultCount = PageFaultCount; 01208 01209 return TRUE; 01210 } 01211 PERFINFO_WSMANAGE_DUMPENTRIES_FAULTS(); 01212 01213 return FALSE; 01214 #endif 01215 }

LOGICAL MiCheckAndSetSystemTrimCriteria IN OUT PMMWS_TRIM_CRITERIA  Criteria  ) 
 

BOOLEAN MiCheckProcessTrimCriteria PMMWS_TRIM_CRITERIA  Criteria,
PMMSUPPORT  VmSupport,
PEPROCESS  Process,
PLARGE_INTEGER  CurrentTime
 

Definition at line 1372 of file wsmanage.c.

References ASSERT, DbgPrint, FALSE, _MMWS_TRIM_CRITERIA::FaultBased, _EPROCESS::ImageFileName, _MMSUPPORT::LastTrimFaultCount, _MMSUPPORT::LastTrimTime, MEMORY_PRIORITY_FOREGROUND, _MMSUPPORT::MemoryPriority, MiCheckCounter, MiHydra, _MMSUPPORT::MinimumWorkingSetSize, MM_DBG_WS_EXPANSION, MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM, MmAvailablePages, MmFreeGoal, MmMoreThanEnoughFreePages, MmNumberOfForegroundProcesses, MmWorkingSetProtectionTime, _MMSUPPORT::PageFaultCount, PERFINFO_WSMANAGE_PROCESS_RESET, _EPROCESS::ProcessOutswapEnabled, _MM_SESSION_SPACE::SessionId, TRUE, _MMSUPPORT::u, _EPROCESS::Vm, and _MMSUPPORT::WorkingSetSize.

Referenced by MmWorkingSetManager().

01381 : 01382 01383 Determine whether the specified working set should be trimmed. 01384 01385 Arguments: 01386 01387 Criteria - Supplies the trim criteria information. 01388 01389 VmSupport - Supplies the working set information for the candidate process. 01390 01391 Process - Supplies the process to trim. NULL if this is for a session. 01392 01393 CurrentTime - Supplies the time at the start of this trim round. 01394 01395 Return Value: 01396 01397 TRUE if trimming should be done on this process, FALSE otherwise. 01398 01399 Environment: 01400 01401 Kernel mode. Expansion lock held. APC level or below. 01402 01403 --*/ 01404 01405 { 01406 BOOLEAN Trim; 01407 BOOLEAN Reset; 01408 BOOLEAN Responsive; 01409 01410 #if DBG 01411 if (Process) { 01412 ASSERT (VmSupport->u.Flags.SessionSpace == 0); 01413 } 01414 else { 01415 ASSERT (VmSupport->u.Flags.SessionSpace == 1); 01416 } 01417 #endif 01418 01419 if (VmSupport->u.Flags.TrimHard == 1 && VmSupport->WorkingSetSize) { 01420 return TRUE; 01421 } 01422 01423 #ifdef _MI_USE_CLAIMS_ 01424 01425 // 01426 // Always trim if there's anything left. Note that the 01427 // foreground process is given priority by putting it last in the 01428 // working set list and stopping trimming when we have enough pages. 01429 // 01430 01431 if (VmSupport->WorkingSetSize <= 3) { 01432 return FALSE; 01433 } 01434 01435 return TRUE; 01436 #else 01437 01438 Trim = TRUE; 01439 Reset = FALSE; 01440 01441 if (Process && Process->Vm.MemoryPriority == MEMORY_PRIORITY_FOREGROUND && Criteria->FaultBased.NumPasses == 0) { 01442 01443 Criteria->FaultBased.NumberOfForegroundProcesses += 1; 01444 } 01445 01446 if (MiCheckCounter >= MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM) { 01447 01448 // 01449 // This is a voluntary trim so don't trim if 01450 // - the page fault count is too high 01451 // - or the size is too small 01452 // - or not enough time has elapsed since it was last trimmed 01453 // 01454 01455 if (((VmSupport->PageFaultCount - VmSupport->LastTrimFaultCount) > 01456 Criteria->FaultBased.FaultCount) 01457 || 01458 (VmSupport->WorkingSetSize <= 5) 01459 01460 || 01461 ((CurrentTime->QuadPart - VmSupport->LastTrimTime.QuadPart) < 01462 MmWorkingSetProtectionTime.QuadPart)) { 01463 01464 #if DBG 01465 if (MmDebug & MM_DBG_WS_EXPANSION) { 01466 if (VmSupport->WorkingSetSize > 5) { 01467 01468 if (Process) { 01469 DbgPrint(" ***** Skipping Process %16s %5d Faults, WS %6d\n", 01470 Process->ImageFileName, 01471 VmSupport->PageFaultCount - VmSupport->LastTrimFaultCount, 01472 VmSupport->WorkingSetSize 01473 ); 01474 } 01475 else { 01476 PMM_SESSION_SPACE SessionSpace; 01477 01478 ASSERT (MiHydra == TRUE); 01479 SessionSpace = CONTAINING_RECORD(VmSupport, 01480 MM_SESSION_SPACE, 01481 Vm); 01482 01483 DbgPrint(" ***** Skipping Session %d %5d Faults, WS %6d\n", 01484 SessionSpace->SessionId, 01485 VmSupport->PageFaultCount - VmSupport->LastTrimFaultCount, 01486 VmSupport->WorkingSetSize 01487 ); 01488 } 01489 } 01490 } 01491 #endif //DBG 01492 01493 Reset = TRUE; 01494 Trim = FALSE; 01495 } 01496 } else { 01497 01498 // 01499 // This is a forced trim. If this process is above its 01500 // minimum it's a candidate. 01501 // 01502 01503 if (VmSupport->WorkingSetSize <= VmSupport->MinimumWorkingSetSize) { 01504 01505 // 01506 // If this process is below its minimum, don't trim it 01507 // unless stacks are swapped out or it's paging a bit. 01508 // 01509 01510 if (((MmAvailablePages + 5) >= MmFreeGoal) && 01511 (((VmSupport->LastTrimFaultCount != 01512 VmSupport->PageFaultCount) || 01513 (Process && Process->ProcessOutswapEnabled == FALSE)))) { 01514 01515 // 01516 // If we've almost reached our goal and either this process 01517 // has taken page faults since the last trim or it's 01518 // not swap enabled, then don't trim it but do reset it. 01519 // 01520 01521 Reset = TRUE; 01522 Trim = FALSE; 01523 } 01524 else if ((VmSupport->WorkingSetSize < 5) || 01525 ((CurrentTime->QuadPart - VmSupport->LastTrimTime.QuadPart) < 01526 MmWorkingSetProtectionTime.QuadPart)) { 01527 01528 // 01529 // If the working set is very small or it was trimmed 01530 // recently don't trim it again. 01531 // 01532 01533 Reset = TRUE; 01534 Trim = FALSE; 01535 } 01536 } 01537 } 01538 01539 if (Trim == TRUE) { 01540 01541 // 01542 // Fix to supply foreground responsiveness by not trimming 01543 // foreground priority applications as aggressively. 01544 // 01545 01546 Responsive = FALSE; 01547 01548 if ((MmNumberOfForegroundProcesses <= 3) && 01549 (Criteria->FaultBased.NumberOfForegroundProcesses <= 3) && 01550 (VmSupport->MemoryPriority)) { 01551 01552 if ((MmAvailablePages > (MmMoreThanEnoughFreePages >> 2)) || 01553 (VmSupport->MemoryPriority >= MEMORY_PRIORITY_FOREGROUND)) { 01554 01555 // 01556 // Indicate that memory responsiveness to the foreground 01557 // process is important (not so for large console trees). 01558 // 01559 01560 Responsive = TRUE; 01561 } 01562 } 01563 01564 if (Responsive == TRUE && Criteria->FaultBased.NumPasses == 0) { 01565 01566 // 01567 // Note that NumPasses yields a measurement of how 01568 // desperate we are for memory, if NumPasses is nonzero, 01569 // we are in trouble. 01570 // 01571 01572 Trim = FALSE; 01573 } 01574 } 01575 01576 if (Trim == FALSE) { 01577 if (Reset == TRUE) { 01578 VmSupport->LastTrimTime = *CurrentTime; 01579 VmSupport->LastTrimFaultCount = VmSupport->PageFaultCount; 01580 } 01581 01582 PERFINFO_WSMANAGE_PROCESS_RESET(VmSupport); 01583 } 01584 01585 return Trim; 01586 #endif 01587 } #ifndef _MI_USE_CLAIMS_

BOOLEAN MiCheckProcessTrimCriteria IN PMMWS_TRIM_CRITERIA  Criteria,
IN PMMSUPPORT  VmSupport,
IN PEPROCESS  Process,
IN PLARGE_INTEGER  CurrentTime
 

LOGICAL MiCheckSystemCacheWsTrimCriteria PMMSUPPORT  VmSupport  ) 
 

Definition at line 1591 of file wsmanage.c.

References FALSE, MiCheckCounter, _MMSUPPORT::MinimumWorkingSetSize, MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM, TRUE, and _MMSUPPORT::WorkingSetSize.

Referenced by MmWorkingSetManager().

01597 : 01598 01599 Determine whether the system cache should be trimmed 01600 01601 Arguments: 01602 01603 VmSupport - Supplies the working set information for the system cache. 01604 01605 Return Value: 01606 01607 TRUE if trimming should be done on this process, FALSE otherwise. 01608 01609 Environment: 01610 01611 Kernel mode. Expansion lock held. APC level or below. 01612 01613 --*/ 01614 01615 { 01616 LOGICAL Trim; 01617 01618 // 01619 // Don't trim the system cache if this is a voluntary trim and 01620 // the working set is within 100 pages of the minimum or 01621 // if the cache is at its minimum. 01622 // 01623 01624 if ((MiCheckCounter >= MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM) && 01625 (((LONG)VmSupport->WorkingSetSize - 01626 (LONG)VmSupport->MinimumWorkingSetSize) < 100)) { 01627 01628 // 01629 // Don't trim it if it's near its minimum and it's not a forced trim. 01630 // 01631 01632 Trim = FALSE; 01633 } 01634 else { 01635 Trim = TRUE; 01636 } 01637 01638 return Trim; 01639 } #endif

LOGICAL MiCheckSystemCacheWsTrimCriteria IN PMMSUPPORT  VmSupport  ) 
 

BOOLEAN MiCheckSystemTrimEndCriteria IN PMMWS_TRIM_CRITERIA  Criteria,
IN KIRQL  OldIrql
 

Definition at line 1218 of file wsmanage.c.

References FALSE, KeDelayExecutionThread(), KernelMode, LOCK_EXPANSION, MI_MAX_TRIM_PASSES, MiCheckCounter, MmAvailablePages, MmMinimumFreePages, MmNumberOfForegroundProcesses, MmShortTime, PERFINFO_WSMANAGE_DECL, PERFINFO_WSMANAGE_TRIMACTION, PERFINFO_WSMANAGE_WAITFORWRITER_CLAIMS, PERFINFO_WSMANAGE_WAITFORWRITER_FAULTS, TRUE, and UNLOCK_EXPANSION.

Referenced by MmWorkingSetManager().

01225 : 01226 01227 Check the ending criteria. If we're not done, delay for a little 01228 bit to let the modified write catch up. 01229 01230 Arguments: 01231 01232 Criteria - Supplies the trim criteria information. 01233 01234 OldIrql - Supplies the old IRQL to lower to if the expansion lock needs 01235 to be released. 01236 01237 Return Value: 01238 01239 TRUE if trimming can be stopped, FALSE otherwise. 01240 01241 Environment: 01242 01243 Kernel mode. Expansion lock held. APC level or below. 01244 01245 --*/ 01246 01247 { 01248 BOOLEAN FinishedTrimming; 01249 PERFINFO_WSMANAGE_DECL(); 01250 01251 FinishedTrimming = FALSE; 01252 01253 #ifdef _MI_USE_CLAIMS_ 01254 if ((MmAvailablePages > Criteria->ClaimBased.DesiredFreeGoal) || 01255 (Criteria->ClaimBased.NumPasses >= MI_MAX_TRIM_PASSES)) { 01256 01257 // 01258 // We have enough pages or we trimmed as many as we're going to get. 01259 // 01260 01261 FinishedTrimming = TRUE; 01262 } 01263 else { 01264 01265 // 01266 // Update the global claim and estimate before we wait. 01267 // 01268 01269 MmTotalClaim = Criteria->ClaimBased.NewTotalClaim; 01270 MmTotalEstimatedAvailable = Criteria->ClaimBased.NewTotalEstimatedAvailable; 01271 } 01272 #else 01273 if (MmAvailablePages > MmMinimumFreePages) { 01274 01275 // 01276 // Every process has been examined and ample pages 01277 // now exist. 01278 // 01279 01280 MmNumberOfForegroundProcesses = Criteria->FaultBased.NumberOfForegroundProcesses; 01281 01282 FinishedTrimming = TRUE; 01283 } 01284 #endif 01285 01286 if (FinishedTrimming == FALSE) { 01287 01288 // 01289 // If we don't have enough pages wait 10 milliseconds 01290 // for the modified page writer to catch up. The wait is also 01291 // important because a thread may have the system cache locked but 01292 // has been preempted by the balance set manager due to its higher 01293 // priority. We must give this thread a shot at running so it can 01294 // release the system cache lock (all the trimmable pages may reside in 01295 // the system cache). 01296 // 01297 01298 UNLOCK_EXPANSION (OldIrql); 01299 01300 KeDelayExecutionThread (KernelMode, 01301 FALSE, 01302 &MmShortTime); 01303 01304 #ifdef _MI_USE_CLAIMS_ 01305 PERFINFO_WSMANAGE_WAITFORWRITER_CLAIMS(); 01306 #else 01307 PERFINFO_WSMANAGE_WAITFORWRITER_FAULTS(); 01308 #endif 01309 01310 // 01311 // Check again to see if we've met the criteria to stop trimming. 01312 // 01313 01314 #ifdef _MI_USE_CLAIMS_ 01315 if (MmAvailablePages > Criteria->ClaimBased.DesiredFreeGoal) { 01316 01317 // 01318 // Now we have enough pages so break out. 01319 // 01320 01321 FinishedTrimming = TRUE; 01322 } 01323 else { 01324 01325 // 01326 // We don't have enough pages so let's do another pass. 01327 // Go get the next working set list which is probably the 01328 // one we put back before we gave up the processor. 01329 // 01330 01331 if (Criteria->ClaimBased.NumPasses == 0) { 01332 MiAdjustClaimParameters(FALSE); 01333 } 01334 01335 Criteria->ClaimBased.NumPasses += 1; 01336 Criteria->ClaimBased.NewTotalClaim = 0; 01337 Criteria->ClaimBased.NewTotalEstimatedAvailable = 0; 01338 01339 PERFINFO_WSMANAGE_TRIMACTION(WS_ACTION_FORCE_TRIMMING_PROCESS); 01340 } 01341 #else 01342 01343 if (MmAvailablePages > MmMinimumFreePages) { 01344 01345 // 01346 // Now we have enough pages so break out. 01347 // 01348 01349 FinishedTrimming = TRUE; 01350 } 01351 else { 01352 01353 // 01354 // Change this to a forced trim, so we get pages 01355 // available, and reset the current time. 01356 // 01357 01358 PERFINFO_WSMANAGE_TRIMACTION(WS_ACTION_FORCE_TRIMMING_PROCESS); 01359 01360 MiCheckCounter = 0; 01361 Criteria->FaultBased.NumPasses += 1; 01362 } 01363 #endif 01364 01365 LOCK_EXPANSION (OldIrql); 01366 } 01367 01368 return FinishedTrimming; 01369 }

BOOLEAN MiCheckSystemTrimEndCriteria IN OUT PMMWS_TRIM_CRITERIA  Criteria,
IN KIRQL  OldIrql
 

ULONG MiDetermineWsTrimAmount PMMWS_TRIM_CRITERIA  Criteria,
PMMSUPPORT  VmSupport,
PEPROCESS  Process
 

Definition at line 1644 of file wsmanage.c.

References ASSERT, _MMSUPPORT::Claim, _MMSUPPORT::EstimatedAvailable, FALSE, _MMWSL::FirstDynamic, _MMSUPPORT::MaximumWorkingSetSize, MEMORY_PRIORITY_FOREGROUND, _MMSUPPORT::MemoryPriority, MI_BACKGROUND_CLAIM_AVAILABLE_SHIFT, MI_FOREGROUND_CLAIM_AVAILABLE_SHIFT, MI_PASS0_TRIM_AGE, MI_PASS1_TRIM_AGE, MI_PASS2_TRIM_AGE, MI_PASS3_TRIM_AGE, MI_PASS4_TRIM_AGE, MiCheckCounter, _MMSUPPORT::MinimumWorkingSetSize, MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM, MmAvailablePages, MmSystemCacheWs, MmWorkingSetReductionHuge, MmWorkingSetReductionMax, MmWorkingSetReductionMaxCacheWs, MmWorkingSetReductionMin, MmWorkingSetReductionMinCacheWs, MmWorkingSetSwapReduction, MmWorkingSetSwapReductionHuge, MmWorkingSetVolReductionHuge, MmWorkingSetVolReductionMax, MmWorkingSetVolReductionMaxCacheWs, MmWorkingSetVolReductionMin, _MMWS_TRIM_CRITERIA::NumPasses, _EPROCESS::ProcessOutswapEnabled, _MMWSL::Quota, TRUE, _MMSUPPORT::u, _MMSUPPORT::VmWorkingSetList, and _MMSUPPORT::WorkingSetSize.

Referenced by MmWorkingSetManager().

01652 : 01653 01654 Determine whether this process should be trimmed. 01655 01656 Arguments: 01657 01658 Criteria - Supplies the trim criteria information. 01659 01660 VmSupport - Supplies the working set information for the candidate process. 01661 01662 Process - Supplies the candidate process to be trimmed. 01663 01664 Return Value: 01665 01666 TRUE if trimming should be done on this process, FALSE if not. 01667 01668 Environment: 01669 01670 Kernel mode. Expansion lock held. APC level or below. 01671 01672 --*/ 01673 01674 { 01675 PMMWSL WorkingSetList; 01676 ULONG MaxTrim; 01677 ULONG Trim; 01678 BOOLEAN OutswapEnabled; 01679 01680 if (Process) { 01681 OutswapEnabled = Process->ProcessOutswapEnabled; 01682 } 01683 else { 01684 if (VmSupport->u.Flags.TrimHard == 1) { 01685 OutswapEnabled = TRUE; 01686 } 01687 else { 01688 OutswapEnabled = FALSE; 01689 } 01690 } 01691 01692 WorkingSetList = VmSupport->VmWorkingSetList; 01693 01694 if (VmSupport->WorkingSetSize <= WorkingSetList->FirstDynamic) { 01695 return 0; 01696 } 01697 01698 #ifdef _MI_USE_CLAIMS_ 01699 MaxTrim = VmSupport->WorkingSetSize; 01700 01701 if (OutswapEnabled == FALSE) { 01702 01703 // 01704 // Don't trim the cache or non-swapped sessions or processes 01705 // below their minimum. 01706 // 01707 01708 MaxTrim -= VmSupport->MinimumWorkingSetSize; 01709 } 01710 01711 switch (Criteria->ClaimBased.NumPasses) { 01712 case 0: 01713 Trim = VmSupport->Claim >> 01714 ((VmSupport->MemoryPriority == MEMORY_PRIORITY_FOREGROUND) 01715 ? MI_FOREGROUND_CLAIM_AVAILABLE_SHIFT 01716 : MI_BACKGROUND_CLAIM_AVAILABLE_SHIFT); 01717 Criteria->ClaimBased.TrimAge = MI_PASS0_TRIM_AGE; 01718 Criteria->ClaimBased.DoAging = TRUE; 01719 break; 01720 case 1: 01721 Trim = VmSupport->Claim >> 01722 ((VmSupport->MemoryPriority == MEMORY_PRIORITY_FOREGROUND) 01723 ? MI_FOREGROUND_CLAIM_AVAILABLE_SHIFT 01724 : MI_BACKGROUND_CLAIM_AVAILABLE_SHIFT); 01725 Criteria->ClaimBased.TrimAge = MI_PASS1_TRIM_AGE; 01726 Criteria->ClaimBased.DoAging = FALSE; 01727 break; 01728 case 2: 01729 Trim = VmSupport->Claim; 01730 Criteria->ClaimBased.TrimAge = MI_PASS2_TRIM_AGE; 01731 Criteria->ClaimBased.DoAging = FALSE; 01732 break; 01733 case 3: 01734 Trim = VmSupport->EstimatedAvailable; 01735 Criteria->ClaimBased.TrimAge = MI_PASS3_TRIM_AGE; 01736 Criteria->ClaimBased.DoAging = FALSE; 01737 break; 01738 default: 01739 Trim = VmSupport->EstimatedAvailable; 01740 Criteria->ClaimBased.TrimAge = MI_PASS3_TRIM_AGE; 01741 Criteria->ClaimBased.DoAging = FALSE; 01742 01743 if (MmAvailablePages < 100) { 01744 if (VmSupport->WorkingSetSize > VmSupport->MinimumWorkingSetSize) { 01745 Trim = (VmSupport->WorkingSetSize - VmSupport->MinimumWorkingSetSize) >> 2; 01746 } 01747 Criteria->ClaimBased.TrimAge = MI_PASS4_TRIM_AGE; 01748 Criteria->ClaimBased.DoAging = TRUE; 01749 } 01750 01751 break; 01752 } 01753 01754 if (Trim > MaxTrim) { 01755 Trim = MaxTrim; 01756 } 01757 01758 #else 01759 01760 UNREFERENCED_PARAMETER (Criteria); 01761 01762 // 01763 // Calculate Trim size. 01764 // 01765 01766 if (VmSupport->WorkingSetSize <= VmSupport->MinimumWorkingSetSize && 01767 OutswapEnabled == TRUE) { 01768 01769 // 01770 // Set the quota to the minimum and reduce the working 01771 // set size. 01772 // 01773 01774 WorkingSetList->Quota = VmSupport->MinimumWorkingSetSize; 01775 Trim = VmSupport->WorkingSetSize - WorkingSetList->FirstDynamic; 01776 if (Trim > MmWorkingSetSwapReduction) { 01777 Trim = MmWorkingSetSwapReduction; 01778 } 01779 01780 ASSERT ((LONG)Trim >= 0); 01781 01782 } else { 01783 01784 MaxTrim = VmSupport->WorkingSetSize - 01785 VmSupport->MinimumWorkingSetSize; 01786 01787 if (OutswapEnabled == TRUE) { 01788 01789 // 01790 // All thread stacks have been swapped out this process or 01791 // all the processes and threads have been swapped out of this 01792 // session. 01793 // 01794 01795 ULONG i; 01796 01797 Trim = MmWorkingSetSwapReduction; 01798 i = VmSupport->WorkingSetSize - VmSupport->MaximumWorkingSetSize; 01799 if ((LONG)i > 0) { 01800 Trim = i; 01801 if (Trim > MmWorkingSetSwapReductionHuge) { 01802 Trim = MmWorkingSetSwapReductionHuge; 01803 } 01804 } 01805 01806 } else if (MiCheckCounter >= MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM) { 01807 01808 // 01809 // Haven't faulted much, reduce a bit. 01810 // 01811 01812 if (VmSupport->WorkingSetSize > 01813 (VmSupport->MaximumWorkingSetSize + 01814 (6 * MmWorkingSetVolReductionHuge))) { 01815 Trim = MmWorkingSetVolReductionHuge; 01816 01817 } else if ( (VmSupport != &MmSystemCacheWs) && 01818 VmSupport->WorkingSetSize > 01819 ( VmSupport->MaximumWorkingSetSize + (2 * MmWorkingSetReductionHuge))) { 01820 Trim = MmWorkingSetReductionHuge; 01821 } else if (VmSupport->WorkingSetSize > VmSupport->MaximumWorkingSetSize) { 01822 if (VmSupport != &MmSystemCacheWs) { 01823 Trim = MmWorkingSetVolReductionMax; 01824 } else { 01825 Trim = MmWorkingSetVolReductionMaxCacheWs; 01826 } 01827 } else { 01828 Trim = MmWorkingSetVolReductionMin; 01829 } 01830 01831 } else { 01832 01833 if (VmSupport->WorkingSetSize > 01834 (VmSupport->MaximumWorkingSetSize + 01835 (2 * MmWorkingSetReductionHuge))) { 01836 Trim = MmWorkingSetReductionHuge; 01837 01838 } else if (VmSupport->WorkingSetSize > VmSupport->MaximumWorkingSetSize) { 01839 if (VmSupport != &MmSystemCacheWs) { 01840 Trim = MmWorkingSetReductionMax; 01841 } else { 01842 Trim = MmWorkingSetReductionMaxCacheWs; 01843 } 01844 } else { 01845 if (VmSupport != &MmSystemCacheWs) { 01846 Trim = MmWorkingSetReductionMin; 01847 } else { 01848 Trim = MmWorkingSetReductionMinCacheWs; 01849 } 01850 } 01851 } 01852 01853 if (MaxTrim < Trim) { 01854 Trim = MaxTrim; 01855 } 01856 } 01857 #endif 01858 01859 return Trim; 01860 } #ifdef _MI_USE_CLAIMS_

ULONG MiDetermineWsTrimAmount IN PMMWS_TRIM_CRITERIA  Criteria,
IN PMMSUPPORT  VmSupport,
IN PEPROCESS  Process
 

VOID MiEmptyAllWorkingSets VOID   ) 
 

Definition at line 2715 of file wsmanage.c.

References ASSERT, ExPageLockHandle, FALSE, KeClearEvent, KernelMode, KeSetEvent(), KeWaitForSingleObject(), LOCK_EXPANSION, MiEmptyAllWorkingSetsWorker(), MiHydra, MiWaitForEmptyEvent, MiWaitingForWorkingSetEmpty, MmLockPagableSectionByHandle(), MmUnlockPagableImageSection(), MmWorkingSetManagerEvent, PAGED_CODE, PsGetCurrentThread, TRUE, UNLOCK_EXPANSION, and WrVirtualMemory.

Referenced by MiAllocateContiguousMemory(), MmGatherMemoryForHibernate(), and MmRemovePhysicalMemory().

02721 : 02722 02723 This routine attempts to empty all the working sets on the 02724 expansion list. 02725 02726 Arguments: 02727 02728 None. 02729 02730 Return Value: 02731 02732 None. 02733 02734 Environment: 02735 02736 Kernel mode. No locks held. APC level or below. 02737 02738 --*/ 02739 02740 { 02741 KIRQL OldIrql; 02742 02743 PAGED_CODE (); 02744 02745 MmLockPagableSectionByHandle (ExPageLockHandle); 02746 02747 if (MiHydra == FALSE) { 02748 MiEmptyAllWorkingSetsWorker (); 02749 } 02750 else { 02751 ASSERT (PsGetCurrentThread () != MmWorkingSetThread); 02752 02753 // 02754 // For Hydra, we cannot attach directly to the session space to be 02755 // trimmed because it would result in session space references by 02756 // other threads in this process to the attached session instead 02757 // of the (currently) correct one. In fact, we cannot even queue 02758 // this to a worker thread because the working set manager 02759 // (who shares the same page directory) may be attaching or 02760 // detaching from a session (any session). So this must be queued 02761 // to the working set manager. 02762 // 02763 02764 LOCK_EXPANSION (OldIrql); 02765 02766 if (MiWaitingForWorkingSetEmpty == FALSE) { 02767 MiWaitingForWorkingSetEmpty = TRUE; 02768 KeClearEvent (&MiWaitForEmptyEvent); 02769 } 02770 02771 UNLOCK_EXPANSION (OldIrql); 02772 02773 KeSetEvent (&MmWorkingSetManagerEvent, 0, FALSE); 02774 02775 KeWaitForSingleObject (&MiWaitForEmptyEvent, 02776 WrVirtualMemory, 02777 KernelMode, 02778 FALSE, 02779 (PLARGE_INTEGER)0); 02780 } 02781 02782 MmUnlockPagableImageSection (ExPageLockHandle); 02783 02784 return; 02785 }

VOID MiEmptyAllWorkingSetsWorker VOID   ) 
 

Definition at line 2788 of file wsmanage.c.

References _EPROCESS::AddressSpaceDeleted, ASSERT, FALSE, KeAttachProcess(), KeDetachProcess(), KeSetEvent(), _MMWORKING_SET_EXPANSION_HEAD::ListHead, LOCK_EXPANSION, MiAttachSession(), MiDetachSession(), MiEmptyWorkingSet(), MiHydra, MM_NO_WS_EXPANSION, MM_WS_EXPANSION_IN_PROGRESS, MmSystemCacheWs, MmWorkingSetExpansionHead, MmWorkingSetList, NULL, PAGED_CODE, _EPROCESS::Pcb, TRUE, _MMSUPPORT::u, UNLOCK_EXPANSION, _EPROCESS::Vm, _MMSUPPORT::VmWorkingSetList, _MMSUPPORT::WorkingSetExpansionLinks, and _MMSUPPORT::WorkingSetSize.

Referenced by MiCheckAndSetSystemTrimCriteria(), and MiEmptyAllWorkingSets().

02794 : 02795 02796 This routine attempts to empty all the working sets on the expansion list. 02797 02798 Arguments: 02799 02800 None. 02801 02802 Return Value: 02803 02804 None. 02805 02806 Environment: 02807 02808 Kernel mode. No locks held. APC level or below. 02809 02810 --*/ 02811 02812 { 02813 PMMSUPPORT VmSupport; 02814 PMMSUPPORT FirstSeen; 02815 ULONG SystemCacheSeen; 02816 KIRQL OldIrql; 02817 PLIST_ENTRY ListEntry; 02818 PEPROCESS ProcessToTrim; 02819 PMM_SESSION_SPACE SessionSpace; 02820 ULONG LoopCount; 02821 02822 PAGED_CODE (); 02823 02824 FirstSeen = NULL; 02825 SystemCacheSeen = FALSE; 02826 LoopCount = 0; 02827 02828 LOCK_EXPANSION (OldIrql); 02829 02830 while (!IsListEmpty (&MmWorkingSetExpansionHead.ListHead)) { 02831 02832 // 02833 // Remove the entry at the head and trim it. 02834 // 02835 02836 ListEntry = RemoveHeadList (&MmWorkingSetExpansionHead.ListHead); 02837 02838 if (ListEntry == &MmSystemCacheWs.WorkingSetExpansionLinks) { 02839 VmSupport = &MmSystemCacheWs; 02840 ASSERT (VmSupport->u.Flags.SessionSpace == 0); 02841 ProcessToTrim = NULL; 02842 if (SystemCacheSeen != FALSE) { 02843 02844 // 02845 // Seen this one already. 02846 // 02847 02848 FirstSeen = VmSupport; 02849 } 02850 SystemCacheSeen = TRUE; 02851 } 02852 else { 02853 VmSupport = CONTAINING_RECORD(ListEntry, 02854 MMSUPPORT, 02855 WorkingSetExpansionLinks); 02856 02857 if (VmSupport->u.Flags.SessionSpace == 0) { 02858 ProcessToTrim = CONTAINING_RECORD(VmSupport, 02859 EPROCESS, 02860 Vm); 02861 02862 ASSERT (VmSupport->VmWorkingSetList == MmWorkingSetList); 02863 ASSERT (VmSupport == &ProcessToTrim->Vm); 02864 ASSERT (ProcessToTrim->AddressSpaceDeleted == 0); 02865 ASSERT (VmSupport->u.Flags.SessionSpace == 0); 02866 } 02867 else { 02868 ASSERT (MiHydra == TRUE); 02869 SessionSpace = CONTAINING_RECORD(VmSupport, 02870 MM_SESSION_SPACE, 02871 Vm); 02872 02873 ProcessToTrim = NULL; 02874 } 02875 } 02876 02877 if (VmSupport == FirstSeen) { 02878 InsertHeadList (&MmWorkingSetExpansionHead.ListHead, 02879 &VmSupport->WorkingSetExpansionLinks); 02880 break; 02881 } 02882 02883 ASSERT (VmSupport->u.Flags.BeingTrimmed == 0); 02884 VmSupport->u.Flags.BeingTrimmed = 1; 02885 02886 VmSupport->WorkingSetExpansionLinks.Flink = MM_NO_WS_EXPANSION; 02887 VmSupport->WorkingSetExpansionLinks.Blink = 02888 MM_WS_EXPANSION_IN_PROGRESS; 02889 UNLOCK_EXPANSION (OldIrql); 02890 02891 if (FirstSeen == NULL) { 02892 FirstSeen = VmSupport; 02893 } 02894 02895 // 02896 // Empty the working set. 02897 // 02898 02899 if (ProcessToTrim == NULL) { 02900 if (VmSupport->u.Flags.SessionSpace == 0) { 02901 MiEmptyWorkingSet (VmSupport, FALSE); 02902 } 02903 else { 02904 ASSERT (MiHydra == TRUE); 02905 MiAttachSession (SessionSpace); 02906 MiEmptyWorkingSet (VmSupport, FALSE); 02907 MiDetachSession (); 02908 } 02909 } 02910 else { 02911 02912 if (VmSupport->WorkingSetSize > 4) { 02913 KeAttachProcess (&ProcessToTrim->Pcb); 02914 MiEmptyWorkingSet (VmSupport, FALSE); 02915 KeDetachProcess (); 02916 } 02917 } 02918 02919 // 02920 // Add back to the list. 02921 // 02922 02923 LOCK_EXPANSION (OldIrql); 02924 ASSERT (VmSupport->WorkingSetExpansionLinks.Flink == MM_NO_WS_EXPANSION); 02925 ASSERT (VmSupport->u.Flags.BeingTrimmed == 1); 02926 VmSupport->u.Flags.BeingTrimmed = 0; 02927 02928 ASSERT (VmSupport->WorkingSetExpansionLinks.Flink == MM_NO_WS_EXPANSION); 02929 if (VmSupport->WorkingSetExpansionLinks.Blink == 02930 MM_WS_EXPANSION_IN_PROGRESS) { 02931 02932 // 02933 // If the working set size is still above the minimum, 02934 // add this back at the tail of the list. 02935 // 02936 02937 InsertTailList (&MmWorkingSetExpansionHead.ListHead, 02938 &VmSupport->WorkingSetExpansionLinks); 02939 } 02940 else { 02941 02942 // 02943 // The value in the blink is the address of an event 02944 // to set. 02945 // 02946 02947 ASSERT (VmSupport != &MmSystemCacheWs); 02948 02949 KeSetEvent ((PKEVENT)VmSupport->WorkingSetExpansionLinks.Blink, 02950 0, 02951 FALSE); 02952 } 02953 02954 // 02955 // The initial working set that was chosen for FirstSeen may have 02956 // been trimmed down under its minimum and been removed from the 02957 // ExpansionHead links. It is possible that the system cache is not 02958 // on the links either. This check detects this extremely rare 02959 // situation so that the system does not spin forever. 02960 // 02961 02962 LoopCount += 1; 02963 if (LoopCount > 200) { 02964 if (MmSystemCacheWs.WorkingSetExpansionLinks.Blink == MM_WS_EXPANSION_IN_PROGRESS) { 02965 break; 02966 } 02967 } 02968 } 02969 02970 UNLOCK_EXPANSION (OldIrql); 02971 02972 return; 02973 }

VOID MiObtainFreePages VOID   ) 
 

Definition at line 336 of file wsmanage.c.

References FALSE, KeSetEvent(), MmAvailablePages, MmModifiedPageListHead, MmModifiedPageWriterEvent, MmModifiedWriteClusterSize, MmModNoWriteInsert, MmPagesAboveWsMinimum, MmPagesAboveWsThreshold, MmWorkingSetManagerEvent, and _MMPFNLIST::Total.

Referenced by MiRemovePageByColor(), MiRemovePageFromList(), MiUnlinkFreeOrZeroedPage(), and MiUnlinkPageFromList().

00342 : 00343 00344 This function examines the size of the modified list and the 00345 total number of pages in use because of working set increments 00346 and obtains pages by writing modified pages and/or reducing 00347 working sets. 00348 00349 Arguments: 00350 00351 None. 00352 00353 Return Value: 00354 00355 None. 00356 00357 Environment: 00358 00359 Kernel mode, APCs disabled, working set and PFN mutexes held. 00360 00361 --*/ 00362 00363 { 00364 00365 // 00366 // Check to see if there are enough modified pages to institute a 00367 // write. 00368 // 00369 00370 if ((MmModifiedPageListHead.Total >= MmModifiedWriteClusterSize) || 00371 (MmModNoWriteInsert)) { 00372 00373 // 00374 // Start the modified page writer. 00375 // 00376 00377 KeSetEvent (&MmModifiedPageWriterEvent, 0, FALSE); 00378 } 00379 00380 // 00381 // See if there are enough working sets above the minimum 00382 // threshold to make working set trimming worthwhile. 00383 // 00384 00385 if ((MmPagesAboveWsMinimum > MmPagesAboveWsThreshold) || 00386 (MmAvailablePages < 5)) { 00387 00388 // 00389 // Start the working set manager to reduce working sets. 00390 // 00391 00392 KeSetEvent (&MmWorkingSetManagerEvent, 0, FALSE); 00393 } 00394 }

VOID MiRearrangeWorkingSetExpansionList VOID   ) 
 

Definition at line 2465 of file wsmanage.c.

References ASSERT, _MMSUPPORT::Claim, DbgPrint, KeQuerySystemTime(), _MM_SESSION_SPACE::LastProcessSwappedOutTime, _MMWORKING_SET_EXPANSION_HEAD::ListHead, LOCK_EXPANSION, MEMORY_PRIORITY_FOREGROUND, _MMSUPPORT::MemoryPriority, MiHydra, MM_DBG_SESSIONS, MM_DBG_WS_EXPANSION, MM_WS_REORG_BUCKETS_MAX, MmWorkingSetExpansionHead, _MM_SESSION_SPACE::ReferenceCount, _MM_SESSION_SPACE::SessionId, Size, TRUE, _MMSUPPORT::u, UNLOCK_EXPANSION, _MMSUPPORT::WorkingSetExpansionLinks, and _MMSUPPORT::WorkingSetSize.

Referenced by MiCheckAndSetSystemTrimCriteria().

02471 : 02472 02473 This function arranges the working set list into different 02474 groups based upon the claim. This is done so the working set 02475 trimming will take place on fat processes first. 02476 02477 The working sets are sorted into buckets and then linked back up. 02478 02479 Swapped out sessions and processes are put at the front. 02480 02481 Arguments: 02482 02483 None. 02484 02485 Return Value: 02486 02487 None. 02488 02489 Environment: 02490 02491 Kernel mode, no locks held. 02492 02493 --*/ 02494 02495 { 02496 KIRQL OldIrql; 02497 PLIST_ENTRY ListEntry; 02498 PMMSUPPORT VmSupport; 02499 int Size; 02500 int PreviousNonEmpty; 02501 int NonEmpty; 02502 LIST_ENTRY ListHead[MM_WS_REORG_BUCKETS_MAX]; 02503 LARGE_INTEGER CurrentTime; 02504 LARGE_INTEGER SessionIdleTime; 02505 ULONG IdleTime; 02506 PMM_SESSION_SPACE SessionGlobal; 02507 02508 KeQuerySystemTime (&CurrentTime); 02509 02510 if (IsListEmpty(&MmWorkingSetExpansionHead.ListHead)) { 02511 return; 02512 } 02513 02514 for (Size = 0 ; Size < MM_WS_REORG_BUCKETS_MAX; Size++) { 02515 InitializeListHead(&ListHead[Size]); 02516 } 02517 02518 LOCK_EXPANSION (OldIrql); 02519 02520 while (!IsListEmpty (&MmWorkingSetExpansionHead.ListHead)) { 02521 ListEntry = RemoveHeadList (&MmWorkingSetExpansionHead.ListHead); 02522 02523 VmSupport = CONTAINING_RECORD(ListEntry, 02524 MMSUPPORT, 02525 WorkingSetExpansionLinks); 02526 02527 if (VmSupport->u.Flags.TrimHard == 1) { 02528 02529 ASSERT (MiHydra == TRUE); 02530 ASSERT (VmSupport->u.Flags.SessionSpace == 1); 02531 02532 SessionGlobal = CONTAINING_RECORD (VmSupport, 02533 MM_SESSION_SPACE, 02534 Vm); 02535 02536 SessionIdleTime.QuadPart = CurrentTime.QuadPart - SessionGlobal->LastProcessSwappedOutTime.QuadPart; 02537 02538 #if DBG 02539 if (MmDebug & MM_DBG_SESSIONS) { 02540 DbgPrint ("Mm: Session %d heavily trim/aged - all its processes (%d) swapped out %d seconds ago\n", 02541 SessionGlobal->SessionId, 02542 SessionGlobal->ReferenceCount, 02543 (ULONG)(SessionIdleTime.QuadPart / 10000000)); 02544 } 02545 #endif 02546 02547 if (SessionIdleTime.QuadPart < 0) { 02548 02549 // 02550 // The administrator has moved the system time backwards. 02551 // Give this session a fresh start. 02552 // 02553 02554 SessionIdleTime.QuadPart = 0; 02555 KeQuerySystemTime (&SessionGlobal->LastProcessSwappedOutTime); 02556 } 02557 02558 IdleTime = (ULONG) (SessionIdleTime.QuadPart / 10000000); 02559 } 02560 else { 02561 IdleTime = 0; 02562 } 02563 02564 if (VmSupport->MemoryPriority == MEMORY_PRIORITY_FOREGROUND) { 02565 02566 // 02567 // Put the foreground processes at the end of the list, 02568 // to give them priority. 02569 // 02570 02571 Size = 6; 02572 } 02573 #ifdef _MI_USE_CLAIMS_ 02574 else { 02575 02576 if (VmSupport->Claim > 400) { 02577 Size = 0; 02578 } else if (IdleTime > 30) { 02579 Size = 0; 02580 #if DBG 02581 MiSessionIdleBuckets[Size] += 1; 02582 #endif 02583 } else if (VmSupport->Claim > 200) { 02584 Size = 1; 02585 } else if (IdleTime > 20) { 02586 Size = 1; 02587 #if DBG 02588 MiSessionIdleBuckets[Size] += 1; 02589 #endif 02590 } else if (VmSupport->Claim > 100) { 02591 Size = 2; 02592 } else if (IdleTime > 10) { 02593 Size = 2; 02594 #if DBG 02595 MiSessionIdleBuckets[Size] += 1; 02596 #endif 02597 } else if (VmSupport->Claim > 50) { 02598 Size = 3; 02599 } else if (IdleTime) { 02600 Size = 3; 02601 #if DBG 02602 MiSessionIdleBuckets[Size] += 1; 02603 #endif 02604 } else if (VmSupport->Claim > 25) { 02605 Size = 4; 02606 } else { 02607 Size = 5; 02608 #if DBG 02609 if (VmSupport->u.Flags.SessionSpace == 1) { 02610 MiSessionIdleBuckets[Size] += 1; 02611 } 02612 #endif 02613 } 02614 } 02615 #else 02616 else { 02617 02618 // 02619 // Just put swapped out entries at the front and keep all other 02620 // entries in the same order, just in front of the foreground 02621 // processes. 02622 // 02623 02624 if (IdleTime > 40) { 02625 Size = 0; 02626 } else if (IdleTime > 30) { 02627 Size = 1; 02628 } else if (IdleTime > 20) { 02629 Size = 2; 02630 } else if (IdleTime > 10) { 02631 Size = 3; 02632 } else if (IdleTime) { 02633 Size = 4; 02634 } else { 02635 InsertTailList (&ListHead[5], 02636 &VmSupport->WorkingSetExpansionLinks); 02637 continue; 02638 } 02639 #if DBG 02640 ASSERT (MiHydra == TRUE); 02641 ASSERT (VmSupport->u.Flags.SessionSpace == 1); 02642 MiSessionIdleBuckets[Size] += 1; 02643 #endif 02644 } 02645 #endif 02646 02647 #if DBG 02648 if (MmDebug & MM_DBG_WS_EXPANSION) { 02649 DbgPrint("MM-rearrange: TrimHard = %d, WS Size = 0x%x, Claim 0x%x, Bucket %d\n", 02650 VmSupport->u.Flags.TrimHard, 02651 VmSupport->WorkingSetSize, 02652 VmSupport->Claim, 02653 Size); 02654 } 02655 #endif //DBG 02656 02657 // 02658 // Note: this reverses the bucket order each time we 02659 // reorganize the lists. This may be good or bad - 02660 // if you change it you may want to think about it. 02661 // 02662 02663 InsertHeadList (&ListHead[Size], 02664 &VmSupport->WorkingSetExpansionLinks); 02665 } 02666 02667 // 02668 // Find the first non-empty list. 02669 // 02670 02671 for (NonEmpty = 0 ; NonEmpty < MM_WS_REORG_BUCKETS_MAX ; NonEmpty += 1) { 02672 if (!IsListEmpty (&ListHead[NonEmpty])) { 02673 break; 02674 } 02675 } 02676 02677 // 02678 // Put the head of first non-empty list at the beginning 02679 // of the MmWorkingSetExpansion list. 02680 // 02681 02682 MmWorkingSetExpansionHead.ListHead.Flink = ListHead[NonEmpty].Flink; 02683 ListHead[NonEmpty].Flink->Blink = &MmWorkingSetExpansionHead.ListHead; 02684 02685 PreviousNonEmpty = NonEmpty; 02686 02687 // 02688 // Link the rest of the lists together. 02689 // 02690 02691 for (NonEmpty += 1; NonEmpty < MM_WS_REORG_BUCKETS_MAX; NonEmpty += 1) { 02692 02693 if (!IsListEmpty (&ListHead[NonEmpty])) { 02694 02695 ListHead[PreviousNonEmpty].Blink->Flink = ListHead[NonEmpty].Flink; 02696 ListHead[NonEmpty].Flink->Blink = ListHead[PreviousNonEmpty].Blink; 02697 PreviousNonEmpty = NonEmpty; 02698 } 02699 } 02700 02701 // 02702 // Link the tail of last non-empty to the MmWorkingSetExpansion list. 02703 // 02704 02705 MmWorkingSetExpansionHead.ListHead.Blink = ListHead[PreviousNonEmpty].Blink; 02706 ListHead[PreviousNonEmpty].Blink->Flink = &MmWorkingSetExpansionHead.ListHead; 02707 02708 UNLOCK_EXPANSION (OldIrql); 02709 02710 return; 02711 }

LOGICAL MmTrimAllSystemPagableMemory IN LOGICAL  PurgeTransition  ) 
 

Definition at line 2986 of file wsmanage.c.

References APC_LEVEL, ASSERT, ExReleaseResourceLite(), ExTryToAcquireResourceExclusiveLite(), FALSE, KeLowerIrql(), KeTryToAcquireSpinLock(), _MMWORKING_SET_EXPANSION_HEAD::ListHead, LOCK_EXPANSION, LOCK_PFN, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MiDecrementReferenceCount(), MiEmptyWorkingSet(), MiRemovePageFromList(), MiTrimAllPageFaultCount, MiTrimInProgressCount, MM_NO_WS_EXPANSION, MM_SET_EXPANSION_OWNER, MM_WS_EXPANSION_IN_PROGRESS, MmExpansionLock, MmStandbyPageListHead, MmSystemCacheWs, MmSystemLockOwner, MmSystemWsLock, MmWorkingSetExpansionHead, NULL, _MMPFN::OriginalPte, _MMSUPPORT::PageFaultCount, PsGetCurrentThread, _MMPFNLIST::Total, TRUE, _MMSUPPORT::u, _MMPFN::u2, _MMPFN::u3, UNLOCK_EXPANSION, UNLOCK_PFN, _MMSUPPORT::WorkingSetExpansionLinks, _MMSUPPORT::WorkingSetSize, WSLE_NUMBER, and ZeroPte.

Referenced by ViTrimAllSystemPagableMemory().

02992 : 02993 02994 This routine unmaps all pagable system memory. This does not unmap user 02995 memory or locked down kernel memory. Thus, the memory being unmapped 02996 resides in paged pool, pagable kernel/driver code & data, special pool 02997 and the system cache. 02998 02999 Note that pages with a reference count greater than 1 are skipped (ie: 03000 they remain valid, as they are assumed to be locked down). This prevents 03001 us from unmapping all of the system cache entries, etc. 03002 03003 Non-locked down kernel stacks must be outpaged by modifying the balance 03004 set manager to operate in conjunction with a support routine. This is not 03005 done here. 03006 03007 Arguments: 03008 03009 PurgeTransition - Supplies whether to purge all the clean pages from the 03010 transition list. 03011 03012 Return Value: 03013 03014 TRUE if accomplished, FALSE if not. 03015 03016 Environment: 03017 03018 Kernel mode. APC_LEVEL or below. 03019 03020 --*/ 03021 03022 { 03023 KIRQL OldIrql; 03024 KIRQL OldIrql2; 03025 PLIST_ENTRY Next; 03026 PMMSUPPORT VmSupport; 03027 WSLE_NUMBER PagesInUse; 03028 PFN_NUMBER PageFrameIndex; 03029 LOGICAL LockAvailable; 03030 PMMPFN Pfn1; 03031 PETHREAD CurrentThread; 03032 ULONG flags; 03033 03034 // 03035 // It's ok to check this without acquiring the system WS lock. 03036 // 03037 03038 if (MiTrimAllPageFaultCount == MmSystemCacheWs.PageFaultCount) { 03039 return FALSE; 03040 } 03041 03042 // 03043 // Working set mutexes will be acquired which require APC_LEVEL or below. 03044 // 03045 03046 if (KeGetCurrentIrql() > APC_LEVEL) { 03047 return FALSE; 03048 } 03049 03050 // 03051 // Just return if it's too early during system initialization or if 03052 // another thread/processor is racing here to do the work for us. 03053 // 03054 03055 if (InterlockedIncrement (&MiTrimInProgressCount) > 1) { 03056 InterlockedDecrement (&MiTrimInProgressCount); 03057 return FALSE; 03058 } 03059 03060 #if defined(_X86_) 03061 03062 _asm { 03063 pushfd 03064 pop flags 03065 } 03066 03067 if ((flags & EFLAGS_INTERRUPT_MASK) == 0) { 03068 InterlockedDecrement (&MiTrimInProgressCount); 03069 return FALSE; 03070 } 03071 03072 #endif 03073 03074 LockAvailable = KeTryToAcquireSpinLock (&MmExpansionLock, &OldIrql); 03075 03076 if (LockAvailable == FALSE) { 03077 InterlockedDecrement (&MiTrimInProgressCount); 03078 return FALSE; 03079 } 03080 03081 MM_SET_EXPANSION_OWNER (); 03082 03083 CurrentThread = PsGetCurrentThread(); 03084 03085 // 03086 // If the system cache resource is owned by this thread then don't bother 03087 // trying to trim now. Note that checking the MmSystemLockOwner is not 03088 // sufficient as this flag is cleared just before actually releasing it. 03089 // 03090 03091 if ((CurrentThread == MmSystemLockOwner) || 03092 (ExTryToAcquireResourceExclusiveLite(&MmSystemWsLock) == FALSE)) { 03093 UNLOCK_EXPANSION (OldIrql); 03094 InterlockedDecrement (&MiTrimInProgressCount); 03095 return FALSE; 03096 } 03097 03098 Next = MmWorkingSetExpansionHead.ListHead.Flink; 03099 03100 while (Next != &MmWorkingSetExpansionHead.ListHead) { 03101 if (Next == &MmSystemCacheWs.WorkingSetExpansionLinks) { 03102 break; 03103 } 03104 Next = Next->Flink; 03105 } 03106 03107 if (Next != &MmSystemCacheWs.WorkingSetExpansionLinks) { 03108 ExReleaseResourceLite(&MmSystemWsLock); 03109 UNLOCK_EXPANSION (OldIrql); 03110 InterlockedDecrement (&MiTrimInProgressCount); 03111 return FALSE; 03112 } 03113 03114 RemoveEntryList (Next); 03115 03116 VmSupport = &MmSystemCacheWs; 03117 VmSupport->WorkingSetExpansionLinks.Flink = MM_NO_WS_EXPANSION; 03118 VmSupport->WorkingSetExpansionLinks.Blink = MM_WS_EXPANSION_IN_PROGRESS; 03119 ASSERT (VmSupport->u.Flags.BeingTrimmed == 0); 03120 VmSupport->u.Flags.BeingTrimmed = 1; 03121 03122 MiTrimAllPageFaultCount = VmSupport->PageFaultCount; 03123 03124 PagesInUse = VmSupport->WorkingSetSize; 03125 03126 // 03127 // There are 2 issues here that are carefully dealt with : 03128 // 03129 // 1. APCs must be disabled while any resources are held to prevent 03130 // suspend APCs from deadlocking the system. 03131 // 2. Once the system cache has been marked MM_WS_EXPANSION_IN_PROGRESS, 03132 // either the thread must not be preempted or the system cache working 03133 // set lock must be held throughout. Otherwise a high priority thread 03134 // can fault on a system code and data address and the two pages will 03135 // thrash forever (at high priority) because no system working set 03136 // expansion is allowed while MM_WS_EXPANSION_IN_PROGRESS is set. 03137 // The decision was to hold the system working set lock throughout. 03138 // 03139 03140 MmSystemLockOwner = PsGetCurrentThread (); 03141 03142 UNLOCK_EXPANSION (APC_LEVEL); 03143 03144 MiEmptyWorkingSet (VmSupport, FALSE); 03145 03146 LOCK_EXPANSION (OldIrql2); 03147 ASSERT (OldIrql2 == APC_LEVEL); 03148 03149 ASSERT (VmSupport->WorkingSetExpansionLinks.Flink == MM_NO_WS_EXPANSION); 03150 03151 ASSERT (VmSupport->u.Flags.BeingTrimmed == 1); 03152 VmSupport->u.Flags.BeingTrimmed = 0; 03153 03154 ASSERT (VmSupport->WorkingSetExpansionLinks.Blink == 03155 MM_WS_EXPANSION_IN_PROGRESS); 03156 03157 InsertTailList (&MmWorkingSetExpansionHead.ListHead, 03158 &VmSupport->WorkingSetExpansionLinks); 03159 03160 UNLOCK_EXPANSION (APC_LEVEL); 03161 03162 // 03163 // Since MiEmptyWorkingSet will attempt to recursively acquire and release 03164 // the MmSystemWsLock, the MmSystemLockOwner field may get cleared. 03165 // This means here the resource must be explicitly released instead of 03166 // using UNLOCK_SYSTEM_WS. 03167 // 03168 03169 MmSystemLockOwner = NULL; 03170 ExReleaseResourceLite (&MmSystemWsLock); 03171 KeLowerIrql (OldIrql); 03172 ASSERT (KeGetCurrentIrql() <= APC_LEVEL); 03173 03174 if (PurgeTransition == TRUE) { 03175 03176 // 03177 // Run the transition list and free all the entries so transition 03178 // faults are not satisfied for any of the non modified pages that were 03179 // freed. 03180 // 03181 03182 LOCK_PFN (OldIrql); 03183 03184 while (MmStandbyPageListHead.Total != 0) { 03185 03186 PageFrameIndex = MiRemovePageFromList (&MmStandbyPageListHead); 03187 03188 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 03189 03190 ASSERT (Pfn1->u2.ShareCount == 0); 03191 ASSERT (Pfn1->u3.e2.ReferenceCount == 0); 03192 03193 Pfn1->u3.e2.ReferenceCount += 1; 03194 Pfn1->OriginalPte = ZeroPte; 03195 Pfn1->u3.e1.Modified = 0; 03196 MI_SET_PFN_DELETED (Pfn1); 03197 03198 MiDecrementReferenceCount (PageFrameIndex); 03199 } 03200 03201 UNLOCK_PFN (OldIrql); 03202 } 03203 03204 InterlockedDecrement (&MiTrimInProgressCount); 03205 03206 return TRUE; 03207 } }

VOID MmWorkingSetManager VOID   ) 
 

Definition at line 397 of file wsmanage.c.

References _EPROCESS::AddressSpaceDeleted, _MMSUPPORT::AllowWorkingSetAdjustment, APC_LEVEL, ASSERT, DbgPrint, _MMWS_TRIM_CRITERIA::DesiredFreeGoal, ExTryToAcquireResourceExclusiveLite(), FALSE, _MMWS_TRIM_CRITERIA::FaultBased, _EPROCESS::ImageFileName, KeDelayExecutionThread(), KeDetachProcess(), KeForceAttachProcess(), KeLowerIrql(), KeQuerySystemTime(), KeRaiseIrql(), KernelMode, KeSetEvent(), _MMSUPPORT::LastTrimFaultCount, _MMSUPPORT::LastTrimTime, _MMWORKING_SET_EXPANSION_HEAD::ListHead, LOCK_EXPANSION, MiAttachSession(), MiCheckAndSetSystemTrimCriteria(), MiCheckCounter, MiCheckProcessTrimCriteria(), MiCheckSystemCacheWsTrimCriteria(), MiCheckSystemTrimEndCriteria(), MiDetachSession(), MiDetermineWsTrimAmount(), MiHydra, _MMSUPPORT::MinimumWorkingSetSize, MiTrimWorkingSet(), MM_DBG_WS_EXPANSION, MM_FORCE_TRIM, MM_NO_WS_EXPANSION, MM_SET_SESSION_RESOURCE_OWNER, MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM, MM_WS_EXPANSION_IN_PROGRESS, MmAvailablePages, MmIsAddressValid(), MmMinimumFreePages, MmModifiedPageListHead, MmModifiedPageMaximum, MmModifiedPageWriterEvent, MmSessionSpace, MmShortTime, MmSystemCacheWorkingSetList, MmSystemCacheWs, MmSystemLockOwner, MmSystemWsLock, MmWorkingSetExpansionHead, MmWorkingSetList, NULL, _MMSUPPORT::PageFaultCount, _EPROCESS::Pcb, PERFINFO_WSMANAGE_ACTUALTRIM, PERFINFO_WSMANAGE_DECL, PERFINFO_WSMANAGE_FINALACTION, PERFINFO_WSMANAGE_PROCESS_RESET, PERFINFO_WSMANAGE_TOTRIM, PERFINFO_WSMANAGE_TRIMEND_CLAIMS, PERFINFO_WSMANAGE_TRIMEND_FAULTS, PERFINFO_WSMANAGE_TRIMWS, _MM_SESSION_SPACE::ProcessOutSwapCount, _EPROCESS::ProcessOutswapEnabled, _EPROCESS::ProcessOutswapped, PsGetCurrentProcess, PsGetCurrentThread, _MMWSL::Quota, _MM_SESSION_SPACE::SessionId, _MMPFNLIST::Total, TRUE, _MMSUPPORT::u, UNLOCK_EXPANSION, UNLOCK_SESSION_SPACE_WS, UNLOCK_SYSTEM_WS, UNLOCK_WS, _EPROCESS::Vm, _MMSUPPORT::VmWorkingSetList, _MMSUPPORT::WorkingSetExpansionLinks, _EPROCESS::WorkingSetLock, _MMSUPPORT::WorkingSetSize, and _MM_SESSION_SPACE::WsLock.

Referenced by KeBalanceSetManager().

00403 : 00404 00405 Implements the NT working set manager thread. When the number 00406 of free pages becomes critical and ample pages can be obtained by 00407 reducing working sets, the working set manager's event is set, and 00408 this thread becomes active. 00409 00410 Arguments: 00411 00412 None. 00413 00414 Return Value: 00415 00416 None. 00417 00418 Environment: 00419 00420 Kernel mode. 00421 00422 --*/ 00423 00424 { 00425 00426 PEPROCESS CurrentProcess; 00427 PEPROCESS ProcessToTrim; 00428 PLIST_ENTRY ListEntry; 00429 LOGICAL Attached; 00430 ULONG Trim; 00431 KIRQL OldIrql; 00432 PMMSUPPORT VmSupport; 00433 PMMWSL WorkingSetList; 00434 LARGE_INTEGER CurrentTime; 00435 ULONG count; 00436 LOGICAL DoTrimming; 00437 PMM_SESSION_SPACE SessionSpace; 00438 LOGICAL InformSessionOfRelease; 00439 #if DBG 00440 ULONG LastTrimFaultCount; 00441 #endif // DBG 00442 MMWS_TRIM_CRITERIA TrimCriteria; 00443 PERFINFO_WSMANAGE_DECL(); 00444 00445 #if DBG 00446 MmWorkingSetThread = PsGetCurrentThread (); 00447 #endif 00448 00449 ASSERT (MiHydra == FALSE || MmIsAddressValid (MmSessionSpace) == FALSE); 00450 00451 CurrentProcess = PsGetCurrentProcess (); 00452 00453 Trim = 0; 00454 00455 // 00456 // Set the trim criteria: If there are plenty of pages, the existing 00457 // sets are aged and FALSE is returned to signify no trim is necessary. 00458 // Otherwise, the working set expansion list is ordered so the best 00459 // candidates for trimming are placed at the front and TRUE is returned. 00460 // 00461 00462 DoTrimming = MiCheckAndSetSystemTrimCriteria(&TrimCriteria); 00463 00464 if (DoTrimming) { 00465 00466 Attached = 0; 00467 00468 KeQuerySystemTime (&CurrentTime); 00469 00470 ASSERT (MiHydra == FALSE || MmIsAddressValid (MmSessionSpace) == FALSE); 00471 00472 LOCK_EXPANSION (OldIrql); 00473 while (!IsListEmpty (&MmWorkingSetExpansionHead.ListHead)) { 00474 00475 // 00476 // Remove the entry at the head and trim it. 00477 // 00478 00479 ListEntry = RemoveHeadList (&MmWorkingSetExpansionHead.ListHead); 00480 00481 if (ListEntry == &MmSystemCacheWs.WorkingSetExpansionLinks) { 00482 VmSupport = &MmSystemCacheWs; 00483 ASSERT (VmSupport->u.Flags.SessionSpace == 0); 00484 ASSERT (VmSupport->u.Flags.TrimHard == 0); 00485 SessionSpace = NULL; 00486 } 00487 else { 00488 VmSupport = CONTAINING_RECORD(ListEntry, 00489 MMSUPPORT, 00490 WorkingSetExpansionLinks); 00491 00492 if (VmSupport->u.Flags.SessionSpace == 0) { 00493 ProcessToTrim = CONTAINING_RECORD(VmSupport, 00494 EPROCESS, 00495 Vm); 00496 00497 ASSERT (VmSupport == &ProcessToTrim->Vm); 00498 ASSERT (ProcessToTrim->AddressSpaceDeleted == 0); 00499 SessionSpace = NULL; 00500 } 00501 else { 00502 ASSERT (MiHydra == TRUE); 00503 SessionSpace = CONTAINING_RECORD(VmSupport, 00504 MM_SESSION_SPACE, 00505 Vm); 00506 } 00507 } 00508 00509 // 00510 // Note that other routines that set this bit must remove the 00511 // entry from the expansion list first. 00512 // 00513 00514 ASSERT (VmSupport->u.Flags.BeingTrimmed == 0); 00515 00516 // 00517 // Check to see if we've been here before. 00518 // 00519 00520 if ((*(PLARGE_INTEGER)&VmSupport->LastTrimTime).QuadPart == 00521 (*(PLARGE_INTEGER)&CurrentTime).QuadPart) { 00522 00523 InsertHeadList (&MmWorkingSetExpansionHead.ListHead, 00524 &VmSupport->WorkingSetExpansionLinks); 00525 00526 // 00527 // If we aren't finished we may sleep in this call. 00528 // 00529 00530 if (MiCheckSystemTrimEndCriteria(&TrimCriteria, OldIrql)) { 00531 00532 // 00533 // No more pages are needed so we're done. 00534 // 00535 00536 break; 00537 } 00538 00539 // 00540 // Start a new round of trimming. 00541 // 00542 00543 KeQuerySystemTime (&CurrentTime); 00544 00545 continue; 00546 } 00547 00548 PERFINFO_WSMANAGE_TRIMWS(ProcessToTrim, SessionSpace, VmSupport); 00549 00550 if (SessionSpace) { 00551 00552 if (MiCheckProcessTrimCriteria(&TrimCriteria, 00553 VmSupport, 00554 NULL, 00555 &CurrentTime) == FALSE) { 00556 00557 InsertTailList (&MmWorkingSetExpansionHead.ListHead, 00558 &VmSupport->WorkingSetExpansionLinks); 00559 continue; 00560 } 00561 00562 VmSupport->LastTrimTime = CurrentTime; 00563 VmSupport->u.Flags.BeingTrimmed = 1; 00564 00565 VmSupport->WorkingSetExpansionLinks.Flink = MM_NO_WS_EXPANSION; 00566 VmSupport->WorkingSetExpansionLinks.Blink = 00567 MM_WS_EXPANSION_IN_PROGRESS; 00568 UNLOCK_EXPANSION (OldIrql); 00569 00570 ProcessToTrim = NULL; 00571 00572 // 00573 // Attach directly to the session space to be trimmed. 00574 // 00575 00576 MiAttachSession (SessionSpace); 00577 00578 // 00579 // Try for the session working set lock. 00580 // 00581 00582 WorkingSetList = VmSupport->VmWorkingSetList; 00583 00584 KeRaiseIrql (APC_LEVEL, &OldIrql); 00585 00586 if (!ExTryToAcquireResourceExclusiveLite (&SessionSpace->WsLock)) { 00587 // 00588 // This session space's working set lock was not 00589 // granted, don't trim it. 00590 // 00591 00592 KeLowerIrql (OldIrql); 00593 00594 MiDetachSession (); 00595 00596 LOCK_EXPANSION (OldIrql); 00597 00598 ASSERT (VmSupport->u.Flags.BeingTrimmed == 1); 00599 00600 VmSupport->u.Flags.BeingTrimmed = 0; 00601 00602 VmSupport->AllowWorkingSetAdjustment = MM_FORCE_TRIM; 00603 00604 goto WorkingSetLockFailed; 00605 } 00606 00607 VmSupport->LastTrimFaultCount = VmSupport->PageFaultCount; 00608 00609 MM_SET_SESSION_RESOURCE_OWNER(); 00610 PERFINFO_WSMANAGE_PROCESS_RESET(VmSupport); 00611 } 00612 else if (VmSupport != &MmSystemCacheWs) { 00613 00614 // 00615 // Check to see if this is a forced trim or 00616 // if we are trimming because check counter is 00617 // at the maximum. 00618 // 00619 00620 if (MiCheckProcessTrimCriteria(&TrimCriteria, 00621 VmSupport, 00622 ProcessToTrim, 00623 &CurrentTime) == FALSE) { 00624 00625 InsertTailList (&MmWorkingSetExpansionHead.ListHead, 00626 &VmSupport->WorkingSetExpansionLinks); 00627 continue; 00628 } 00629 00630 VmSupport->LastTrimTime = CurrentTime; 00631 VmSupport->u.Flags.BeingTrimmed = 1; 00632 00633 VmSupport->WorkingSetExpansionLinks.Flink = MM_NO_WS_EXPANSION; 00634 VmSupport->WorkingSetExpansionLinks.Blink = 00635 MM_WS_EXPANSION_IN_PROGRESS; 00636 UNLOCK_EXPANSION (OldIrql); 00637 WorkingSetList = MmWorkingSetList; 00638 InformSessionOfRelease = FALSE; 00639 00640 // 00641 // Attach to the process in preparation for trimming. 00642 // 00643 00644 if (ProcessToTrim != CurrentProcess) { 00645 00646 Attached = KeForceAttachProcess (&ProcessToTrim->Pcb); 00647 00648 if (Attached == 0) { 00649 LOCK_EXPANSION (OldIrql); 00650 VmSupport->u.Flags.BeingTrimmed = 0; 00651 VmSupport->AllowWorkingSetAdjustment = MM_FORCE_TRIM; 00652 goto WorkingSetLockFailed; 00653 } 00654 if (ProcessToTrim->ProcessOutswapEnabled == TRUE) { 00655 ASSERT (ProcessToTrim->ProcessOutswapped == FALSE); 00656 if (MiHydra == TRUE && VmSupport->u.Flags.ProcessInSession == 1 && VmSupport->u.Flags.SessionLeader == 0) { 00657 InformSessionOfRelease = TRUE; 00658 } 00659 } 00660 } 00661 00662 // 00663 // Attempt to acquire the working set lock. If the 00664 // lock cannot be acquired, skip over this process. 00665 // 00666 00667 count = 0; 00668 do { 00669 if (ExTryToAcquireFastMutex(&ProcessToTrim->WorkingSetLock) != FALSE) { 00670 break; 00671 } 00672 KeDelayExecutionThread (KernelMode, FALSE, &MmShortTime); 00673 count += 1; 00674 if (count == 5) { 00675 00676 // 00677 // Could not get the lock, skip this process. 00678 // 00679 00680 if (InformSessionOfRelease == TRUE) { 00681 LOCK_EXPANSION (OldIrql); 00682 ASSERT (ProcessToTrim->ProcessOutswapEnabled == TRUE); 00683 ProcessToTrim->ProcessOutswapEnabled = FALSE; 00684 ASSERT (MmSessionSpace->ProcessOutSwapCount >= 1); 00685 MmSessionSpace->ProcessOutSwapCount -= 1; 00686 UNLOCK_EXPANSION (OldIrql); 00687 InformSessionOfRelease = FALSE; 00688 } 00689 00690 if (Attached) { 00691 KeDetachProcess (); 00692 Attached = 0; 00693 } 00694 00695 LOCK_EXPANSION (OldIrql); 00696 VmSupport->u.Flags.BeingTrimmed = 0; 00697 VmSupport->AllowWorkingSetAdjustment = MM_FORCE_TRIM; 00698 goto WorkingSetLockFailed; 00699 } 00700 } while (TRUE); 00701 00702 ASSERT (VmSupport->u.Flags.BeingTrimmed == 1); 00703 00704 #if DBG 00705 LastTrimFaultCount = VmSupport->LastTrimFaultCount; 00706 #endif // DBG 00707 VmSupport->LastTrimFaultCount = VmSupport->PageFaultCount; 00708 00709 PERFINFO_WSMANAGE_PROCESS_RESET(VmSupport); 00710 } 00711 else { 00712 00713 // 00714 // System cache, 00715 // 00716 00717 #if DBG 00718 LastTrimFaultCount = VmSupport->LastTrimFaultCount; 00719 #endif // DBG 00720 00721 PERFINFO_WSMANAGE_PROCESS_RESET(VmSupport); 00722 00723 // 00724 // Always try to trim the system cache when using claims. 00725 // Fault-based trimming might skip it from time to time. 00726 // 00727 00728 #ifndef _MI_USE_CLAIMS_ 00729 00730 if (!MiCheckSystemCacheWsTrimCriteria(VmSupport)) { 00731 00732 // 00733 // Don't trim the system cache. 00734 // 00735 00736 InsertTailList (&MmWorkingSetExpansionHead.ListHead, 00737 &VmSupport->WorkingSetExpansionLinks); 00738 continue; 00739 } 00740 #endif 00741 00742 VmSupport->LastTrimTime = CurrentTime; 00743 00744 // 00745 // Indicate that this working set is being trimmed. 00746 // 00747 00748 VmSupport->u.Flags.BeingTrimmed = 1; 00749 00750 UNLOCK_EXPANSION (OldIrql); 00751 00752 ProcessToTrim = NULL; 00753 WorkingSetList = MmSystemCacheWorkingSetList; 00754 00755 KeRaiseIrql (APC_LEVEL, &OldIrql); 00756 if (!ExTryToAcquireResourceExclusiveLite (&MmSystemWsLock)) { 00757 00758 // 00759 // System working set lock was not granted, don't trim 00760 // the system cache. 00761 // 00762 00763 KeLowerIrql (OldIrql); 00764 LOCK_EXPANSION (OldIrql); 00765 VmSupport->u.Flags.BeingTrimmed = 0; 00766 InsertTailList (&MmWorkingSetExpansionHead.ListHead, 00767 &VmSupport->WorkingSetExpansionLinks); 00768 continue; 00769 } 00770 00771 MmSystemLockOwner = PsGetCurrentThread(); 00772 00773 VmSupport->LastTrimFaultCount = VmSupport->PageFaultCount; 00774 00775 VmSupport->WorkingSetExpansionLinks.Flink = MM_NO_WS_EXPANSION; 00776 VmSupport->WorkingSetExpansionLinks.Blink = 00777 MM_WS_EXPANSION_IN_PROGRESS; 00778 } 00779 00780 // 00781 // Determine how many pages we want to trim from this working set. 00782 // 00783 00784 Trim = MiDetermineWsTrimAmount(&TrimCriteria, 00785 VmSupport, 00786 ProcessToTrim 00787 ); 00788 00789 #if DBG 00790 if (MmDebug & MM_DBG_WS_EXPANSION) { 00791 if (Trim) { 00792 if (VmSupport->u.Flags.SessionSpace == 0) { 00793 DbgPrint(" Trimming Process %16s %5d Faults, WS %6d, Trimming %5d ==> %5d\n", 00794 ProcessToTrim ? ProcessToTrim->ImageFileName : (PUCHAR)"System Cache", 00795 VmSupport->PageFaultCount - LastTrimFaultCount, 00796 VmSupport->WorkingSetSize, 00797 Trim, 00798 VmSupport->WorkingSetSize-Trim 00799 ); 00800 } 00801 else { 00802 DbgPrint(" Trimming Session 0x%x (id %d) %5d Faults, WS %6d, Trimming %5d ==> %5d\n", 00803 SessionSpace, 00804 SessionSpace->SessionId, 00805 VmSupport->PageFaultCount - LastTrimFaultCount, 00806 VmSupport->WorkingSetSize, 00807 Trim, 00808 VmSupport->WorkingSetSize-Trim 00809 ); 00810 } 00811 } 00812 } 00813 #endif //DBG 00814 00815 #ifdef _MI_USE_CLAIMS_ 00816 00817 // 00818 // If there's something to trim... 00819 // 00820 00821 if (Trim != 0 && 00822 (MmAvailablePages < TrimCriteria.ClaimBased.DesiredFreeGoal)) { 00823 00824 // 00825 // We haven't reached our goal, so trim now. 00826 // 00827 00828 PERFINFO_WSMANAGE_TOTRIM(Trim); 00829 00830 Trim = MiTrimWorkingSet (Trim, 00831 VmSupport, 00832 TrimCriteria.ClaimBased.TrimAge 00833 ); 00834 00835 PERFINFO_WSMANAGE_ACTUALTRIM(Trim); 00836 } 00837 00838 // 00839 // Estimating the current claim is always done here by taking a 00840 // sample of the working set. Aging is only done if the trim 00841 // pass warrants it (ie: the first pass only). 00842 // 00843 00844 MiAgeAndEstimateAvailableInWorkingSet( 00845 VmSupport, 00846 TrimCriteria.ClaimBased.DoAging, 00847 &TrimCriteria.ClaimBased.NewTotalClaim, 00848 &TrimCriteria.ClaimBased.NewTotalEstimatedAvailable 00849 ); 00850 #else 00851 if (Trim != 0) { 00852 00853 PERFINFO_WSMANAGE_TOTRIM(Trim); 00854 00855 Trim = MiTrimWorkingSet ( 00856 Trim, 00857 VmSupport, 00858 (BOOLEAN)(MiCheckCounter < MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM) 00859 ); 00860 00861 PERFINFO_WSMANAGE_ACTUALTRIM(Trim); 00862 } 00863 #endif 00864 00865 // 00866 // Set the quota to the current size. 00867 // 00868 00869 WorkingSetList->Quota = VmSupport->WorkingSetSize; 00870 if (WorkingSetList->Quota < VmSupport->MinimumWorkingSetSize) { 00871 WorkingSetList->Quota = VmSupport->MinimumWorkingSetSize; 00872 } 00873 00874 if (SessionSpace) { 00875 00876 ASSERT (VmSupport->u.Flags.SessionSpace == 1); 00877 00878 UNLOCK_SESSION_SPACE_WS (OldIrql); 00879 00880 MiDetachSession (); 00881 } 00882 else if (VmSupport != &MmSystemCacheWs) { 00883 00884 ASSERT (VmSupport->u.Flags.SessionSpace == 0); 00885 UNLOCK_WS (ProcessToTrim); 00886 00887 if (InformSessionOfRelease == TRUE) { 00888 LOCK_EXPANSION (OldIrql); 00889 ASSERT (ProcessToTrim->ProcessOutswapEnabled == TRUE); 00890 ProcessToTrim->ProcessOutswapEnabled = FALSE; 00891 ASSERT (MmSessionSpace->ProcessOutSwapCount >= 1); 00892 MmSessionSpace->ProcessOutSwapCount -= 1; 00893 UNLOCK_EXPANSION (OldIrql); 00894 InformSessionOfRelease = FALSE; 00895 } 00896 00897 if (Attached) { 00898 KeDetachProcess (); 00899 Attached = 0; 00900 } 00901 00902 } 00903 else { 00904 ASSERT (VmSupport->u.Flags.SessionSpace == 0); 00905 UNLOCK_SYSTEM_WS (OldIrql); 00906 } 00907 00908 LOCK_EXPANSION (OldIrql); 00909 00910 ASSERT (VmSupport->u.Flags.BeingTrimmed == 1); 00911 VmSupport->u.Flags.BeingTrimmed = 0; 00912 00913 WorkingSetLockFailed: 00914 00915 ASSERT (VmSupport->WorkingSetExpansionLinks.Flink == MM_NO_WS_EXPANSION); 00916 00917 if (VmSupport->WorkingSetExpansionLinks.Blink == 00918 MM_WS_EXPANSION_IN_PROGRESS) { 00919 00920 // 00921 // If the working set size is still above the minimum, 00922 // add this back at the tail of the list. 00923 // 00924 00925 InsertTailList (&MmWorkingSetExpansionHead.ListHead, 00926 &VmSupport->WorkingSetExpansionLinks); 00927 } 00928 else { 00929 00930 // 00931 // The value in the blink is the address of an event 00932 // to set. 00933 // 00934 00935 ASSERT (VmSupport != &MmSystemCacheWs); 00936 00937 KeSetEvent ((PKEVENT)VmSupport->WorkingSetExpansionLinks.Blink, 00938 0, 00939 FALSE); 00940 } 00941 00942 #ifndef _MI_USE_CLAIMS_ 00943 TrimCriteria.FaultBased.TotalReduction += Trim; 00944 00945 // 00946 // Zero this in case the next attach fails. 00947 // 00948 00949 Trim = 0; 00950 00951 if (MiCheckCounter < MM_TRIM_COUNTER_MAXIMUM_LARGE_MEM) { 00952 if ((MmAvailablePages > TrimCriteria.FaultBased.DesiredFreeGoal) || 00953 (TrimCriteria.FaultBased.TotalReduction > TrimCriteria.FaultBased.DesiredReductionGoal)) { 00954 00955 00956 // 00957 // Ample pages now exist. 00958 // 00959 00960 PERFINFO_WSMANAGE_FINALACTION(WS_ACTION_AMPLE_PAGES_EXIST); 00961 break; 00962 } 00963 } 00964 #endif 00965 00966 } 00967 00968 #ifdef _MI_USE_CLAIMS_ 00969 MmTotalClaim = TrimCriteria.ClaimBased.NewTotalClaim; 00970 MmTotalEstimatedAvailable = TrimCriteria.ClaimBased.NewTotalEstimatedAvailable; 00971 PERFINFO_WSMANAGE_TRIMEND_CLAIMS(&TrimCriteria); 00972 #else 00973 MiCheckCounter = 0; 00974 PERFINFO_WSMANAGE_TRIMEND_FAULTS(&TrimCriteria); 00975 #endif 00976 00977 UNLOCK_EXPANSION (OldIrql); 00978 } 00979 00980 // 00981 // Signal the modified page writer as we have moved pages 00982 // to the modified list and memory was critical. 00983 // 00984 00985 if ((MmAvailablePages < MmMinimumFreePages) || 00986 (MmModifiedPageListHead.Total >= MmModifiedPageMaximum)) { 00987 KeSetEvent (&MmModifiedPageWriterEvent, 0, FALSE); 00988 } 00989 00990 ASSERT (CurrentProcess == PsGetCurrentProcess ()); 00991 00992 return; 00993 }


Variable Documentation

PEPROCESS ExpDefaultErrorPortProcess
 

Definition at line 99 of file wsmanage.c.

ULONG MiCheckCounter
 

Definition at line 163 of file wsmanage.c.

Referenced by MiCheckAndSetSystemTrimCriteria(), MiCheckProcessTrimCriteria(), MiCheckSystemCacheWsTrimCriteria(), MiCheckSystemTrimEndCriteria(), MiDetermineWsTrimAmount(), and MmWorkingSetManager().

ULONG MiIdealPassFaultCountDisable
 

Definition at line 95 of file wsmanage.c.

Referenced by MiAdjustWorkingSetManagerParameters(), and MiCheckAndSetSystemTrimCriteria().

ULONG MiTrimAllPageFaultCount
 

Definition at line 2982 of file wsmanage.c.

Referenced by MmTrimAllSystemPagableMemory().

LONG MiTrimInProgressCount = 1
 

Definition at line 2980 of file wsmanage.c.

Referenced by MmInitSystem(), and MmTrimAllSystemPagableMemory().

KEVENT MiWaitForEmptyEvent
 

Definition at line 107 of file wsmanage.c.

Referenced by MiAdjustWorkingSetManagerParameters(), MiCheckAndSetSystemTrimCriteria(), and MiEmptyAllWorkingSets().

BOOLEAN MiWaitingForWorkingSetEmpty
 

Definition at line 108 of file wsmanage.c.

Referenced by MiAdjustWorkingSetManagerParameters(), MiCheckAndSetSystemTrimCriteria(), and MiEmptyAllWorkingSets().

ULONG MmAmpleFreePages = 200
 

Definition at line 125 of file wsmanage.c.

Referenced by MiCheckAndSetSystemTrimCriteria().

ULONG MmLastFaultCount
 

Definition at line 164 of file wsmanage.c.

Referenced by MiCheckAndSetSystemTrimCriteria().

PFN_NUMBER MmMoreThanEnoughFreePages = 1000
 

Definition at line 123 of file wsmanage.c.

ULONG MmNumberOfForegroundProcesses
 

Definition at line 146 of file wsmanage.c.

Referenced by MiCheckProcessTrimCriteria(), and MiCheckSystemTrimEndCriteria().

PVOID MmPagableKernelEnd
 

Definition at line 173 of file wsmanage.c.

PVOID MmPagableKernelStart
 

Definition at line 172 of file wsmanage.c.

ULONG MmWorkingSetReductionHuge = (512*1024) >> PAGE_SHIFT
 

Definition at line 133 of file wsmanage.c.

Referenced by MiDetermineWsTrimAmount().

ULONG MmWorkingSetReductionMax = 60
 

Definition at line 130 of file wsmanage.c.

Referenced by MiAdjustWorkingSetManagerParameters(), MiDetermineWsTrimAmount(), and MmSetMemoryPriorityProcess().

ULONG MmWorkingSetReductionMaxCacheWs = 60
 

Definition at line 131 of file wsmanage.c.

Referenced by MiDetermineWsTrimAmount().

ULONG MmWorkingSetReductionMin = 12
 

Definition at line 127 of file wsmanage.c.

Referenced by MiAdjustWorkingSetManagerParameters(), and MiDetermineWsTrimAmount().

ULONG MmWorkingSetReductionMinCacheWs = 12
 

Definition at line 128 of file wsmanage.c.

Referenced by MiDetermineWsTrimAmount().

ULONG MmWorkingSetSwapReduction = 75
 

Definition at line 142 of file wsmanage.c.

Referenced by MiDetermineWsTrimAmount().

ULONG MmWorkingSetSwapReductionHuge = (4*1024*1024) >> PAGE_SHIFT
 

Definition at line 144 of file wsmanage.c.

Referenced by MiDetermineWsTrimAmount().

ULONG MmWorkingSetVolReductionHuge = (2*1024*1024) >> PAGE_SHIFT
 

Definition at line 140 of file wsmanage.c.

Referenced by MiDetermineWsTrimAmount().

ULONG MmWorkingSetVolReductionMax = 60
 

Definition at line 137 of file wsmanage.c.

Referenced by MiAdjustWorkingSetManagerParameters(), and MiDetermineWsTrimAmount().

ULONG MmWorkingSetVolReductionMaxCacheWs = 60
 

Definition at line 138 of file wsmanage.c.

Referenced by MiDetermineWsTrimAmount().

ULONG MmWorkingSetVolReductionMin = 12
 

Definition at line 135 of file wsmanage.c.

Referenced by MiDetermineWsTrimAmount().

PERFINFO_WSMANAGE_GLOBAL_DECL
 

Definition at line 175 of file wsmanage.c.

ULONG PsMinimumWorkingSet
 

Definition at line 97 of file wsmanage.c.

Referenced by PspCreateProcess(), and PspInitPhase0().


Generated on Sat May 15 19:46:10 2004 for test by doxygen 1.3.7