ReactOS  0.4.15-dev-2985-g54406bf
wslist.cpp File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include "miarm.h"
Include dependency graph for wslist.cpp:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 

Functions

static MMPTE GetPteTemplateForWsList (PMMWSL WsList)
 
static ULONG GetNextPageColorForWsList (PMMWSL WsList)
 
static void FreeWsleIndex (PMMWSL WsList, ULONG Index)
 
static ULONG GetFreeWsleIndex (PMMWSL WsList)
 
static VOID RemoveFromWsList (PMMWSL WsList, PVOID Address)
 
static ULONG TrimWsList (PMMWSL WsList)
 
_Use_decl_annotations_ VOID NTAPI MiInsertInWorkingSetList (_Inout_ PMMSUPPORT Vm, _In_ PVOID Address, _In_ ULONG Protection)
 
_Use_decl_annotations_ VOID NTAPI MiRemoveFromWorkingSetList (_Inout_ PMMSUPPORT Vm, _In_ PVOID Address)
 
_Use_decl_annotations_ VOID NTAPI MiInitializeWorkingSetList (_Inout_ PMMSUPPORT WorkingSet)
 
VOID NTAPI MmWorkingSetManager (VOID)
 

Variables

PMMWSL MmWorkingSetList
 
KEVENT MmWorkingSetManagerEvent
 

Macro Definition Documentation

◆ MODULE_INVOLVED_IN_ARM3

#define MODULE_INVOLVED_IN_ARM3

Definition at line 15 of file wslist.cpp.

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file wslist.cpp.

Function Documentation

◆ FreeWsleIndex()

static void FreeWsleIndex ( PMMWSL  WsList,
ULONG  Index 
)
static

Definition at line 34 of file wslist.cpp.

35 {
36  PMMWSLE Wsle = WsList->Wsle;
37  ULONG& LastEntry = WsList->LastEntry;
38  ULONG& FirstFree = WsList->FirstFree;
39  ULONG& LastInitializedWsle = WsList->LastInitializedWsle;
40 
41  /* Erase it now */
42  Wsle[Index].u1.Long = 0;
43 
44  if (Index == (LastEntry - 1))
45  {
46  /* We're freeing the last index of our list. */
47  while (Wsle[Index].u1.e1.Valid == 0)
48  Index--;
49 
50  /* Should we bother about the Free entries */
51  if (FirstFree < Index)
52  {
53  /* Try getting the index of the last free entry */
54  ASSERT(Wsle[Index + 1].u1.Free.MustBeZero == 0);
55  ULONG PreviousFree = Wsle[Index + 1].u1.Free.PreviousFree;
56  ASSERT(PreviousFree < LastEntry);
57  ULONG LastFree = Index + 1 - PreviousFree;
58 #ifdef MMWSLE_PREVIOUS_FREE_JUMP
59  while (Wsle[LastFree].u1.e1.Valid)
60  {
62  LastFree -= MMWSLE_PREVIOUS_FREE_JUMP;
63  }
64 #endif
65  /* Update */
66  ASSERT(LastFree >= FirstFree);
67  Wsle[FirstFree].u1.Free.PreviousFree = (Index + 1 - LastFree) & MMWSLE_PREVIOUS_FREE_MASK;
68  Wsle[LastFree].u1.Free.NextFree = 0;
69  }
70  else
71  {
72  /* No more free entries in our array */
73  FirstFree = ULONG_MAX;
74  }
75  /* This is the new size of our array */
76  LastEntry = Index + 1;
77  /* Should we shrink the alloc? */
78  while ((LastInitializedWsle - LastEntry) > (PAGE_SIZE / sizeof(MMWSLE)))
79  {
80  PMMPTE PointerPte = MiAddressToPte(Wsle + LastInitializedWsle - 1);
81  /* We must not free ourself! */
82  ASSERT(MiPteToAddress(PointerPte) != WsList);
83 
84  PFN_NUMBER Page = PFN_FROM_PTE(PointerPte);
85 
86  {
87  ntoskrnl::MiPfnLockGuard PfnLock;
88 
89  PMMPFN Pfn = MiGetPfnEntry(Page);
90  MI_SET_PFN_DELETED(Pfn);
93  }
94 
95  PointerPte->u.Long = 0;
96 
97  KeInvalidateTlbEntry(Wsle + LastInitializedWsle - 1);
98  LastInitializedWsle -= PAGE_SIZE / sizeof(MMWSLE);
99  }
100  return;
101  }
102 
103  if (FirstFree == ULONG_MAX)
104  {
105  /* We're the first one. */
106  FirstFree = Index;
107  Wsle[FirstFree].u1.Free.PreviousFree = (LastEntry - FirstFree) & MMWSLE_PREVIOUS_FREE_MASK;
108  return;
109  }
110 
111  /* We must find where to place ourself */
112  ULONG NextFree = FirstFree;
113  ULONG PreviousFree = 0;
114  while (NextFree < Index)
115  {
116  ASSERT(Wsle[NextFree].u1.Free.MustBeZero == 0);
117  if (Wsle[NextFree].u1.Free.NextFree == 0)
118  break;
119  PreviousFree = NextFree;
120  NextFree += Wsle[NextFree].u1.Free.NextFree;
121  }
122 
123  if (NextFree < Index)
124  {
125  /* This is actually the last free entry */
126  Wsle[NextFree].u1.Free.NextFree = Index - NextFree;
127  Wsle[Index].u1.Free.PreviousFree = (Index - NextFree) & MMWSLE_PREVIOUS_FREE_MASK;
128  Wsle[FirstFree].u1.Free.PreviousFree = (LastEntry - Index) & MMWSLE_PREVIOUS_FREE_MASK;
129  return;
130  }
131 
132  if (PreviousFree == 0)
133  {
134  /* This is the first free */
135  Wsle[Index].u1.Free.NextFree = FirstFree - Index;
136  Wsle[Index].u1.Free.PreviousFree = Wsle[FirstFree].u1.Free.PreviousFree;
137  Wsle[FirstFree].u1.Free.PreviousFree = (FirstFree - Index) & MMWSLE_PREVIOUS_FREE_MASK;
138  FirstFree = Index;
139  return;
140  }
141 
142  /* Insert */
143  Wsle[PreviousFree].u1.Free.NextFree = (Index - PreviousFree);
144  Wsle[Index].u1.Free.PreviousFree = (Index - PreviousFree) & MMWSLE_PREVIOUS_FREE_MASK;
145  Wsle[Index].u1.Free.NextFree = NextFree - Index;
146  Wsle[NextFree].u1.Free.PreviousFree = (NextFree - Index) & MMWSLE_PREVIOUS_FREE_MASK;
147 }
ULONG PreviousFree
Definition: mmtypes.h:842
struct _MMWSLE MMWSLE
GLdouble u1
Definition: glext.h:8308
union _MMWSLE::@2557 u1
ULONG_PTR Long
Definition: mmtypes.h:854
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG PFN_NUMBER
Definition: ke.h:9
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1143
MMWSLE_FREE_ENTRY Free
Definition: mmtypes.h:856
PFN_NUMBER Page
Definition: section.c:4888
FORCEINLINE VOID KeInvalidateTlbEntry(IN PVOID Address)
Definition: ke.h:260
#define ASSERT(a)
Definition: mode.c:44
_In_ WDFCOLLECTION _In_ ULONG Index
ULONG LastInitializedWsle
Definition: mmtypes.h:873
#define MMWSLE_PREVIOUS_FREE_JUMP
Definition: mmtypes.h:844
LONG NextFree
Definition: mmtypes.h:845
PMMWSLE Wsle
Definition: mmtypes.h:872
Definition: mm.h:362
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
ULONG_PTR Long
Definition: mmtypes.h:215
#define MI_SET_PFN_DELETED(x)
Definition: miarm.h:194
ULONG_PTR PteFrame
Definition: mm.h:407
ULONG FirstFree
Definition: mmtypes.h:868
#define MMWSLE_PREVIOUS_FREE_MASK
Definition: mmtypes.h:843
unsigned int ULONG
Definition: retypes.h:1
FORCEINLINE PVOID MiPteToAddress(PMMPTE PointerPte)
Definition: mm.h:201
ULONG LastEntry
Definition: mmtypes.h:870
union _MMPTE::@2287 u
#define PFN_FROM_PTE(v)
Definition: mm.h:92
#define ULONG_MAX
Definition: limits.h:44
union _MMPFN::@1764 u4

Referenced by RemoveFromWsList().

◆ GetFreeWsleIndex()

static ULONG GetFreeWsleIndex ( PMMWSL  WsList)
static

Definition at line 149 of file wslist.cpp.

150 {
151  ULONG Index;
152  if (WsList->FirstFree != ULONG_MAX)
153  {
154  Index = WsList->FirstFree;
155  ASSERT(Index < WsList->LastInitializedWsle);
156  MMWSLE_FREE_ENTRY& FreeWsle = WsList->Wsle[Index].u1.Free;
157  ASSERT(FreeWsle.MustBeZero == 0);
158  if (FreeWsle.NextFree != 0)
159  {
160  WsList->FirstFree += FreeWsle.NextFree;
161  WsList->Wsle[WsList->FirstFree].u1.Free.PreviousFree = FreeWsle.PreviousFree;
162  }
163  else
164  {
165  WsList->FirstFree = ULONG_MAX;
166  }
167  }
168  else
169  {
170  Index = WsList->LastEntry++;
171  if (Index >= WsList->LastInitializedWsle)
172  {
173  /* Grow our array */
174  PMMPTE PointerPte = MiAddressToPte(&WsList->Wsle[WsList->LastInitializedWsle]);
175  ASSERT(PointerPte->u.Hard.Valid == 0);
177  {
178  ntoskrnl::MiPfnLockGuard PfnLock;
179 
182  }
183 
184  WsList->LastInitializedWsle += PAGE_SIZE / sizeof(MMWSLE);
185  }
186  }
187 
188  WsList->Wsle[Index].u1.Long = 0;
189  return Index;
190 }
ULONG PreviousFree
Definition: mmtypes.h:842
struct _MMWSLE MMWSLE
union _MMWSLE::@2557 u1
static MMPTE GetPteTemplateForWsList(PMMWSL WsList)
Definition: wslist.cpp:24
ULONG_PTR Long
Definition: mmtypes.h:854
#define MiAddressToPte(x)
Definition: mmx86.c:19
MMWSLE_FREE_ENTRY Free
Definition: mmtypes.h:856
#define ASSERT(a)
Definition: mode.c:44
_In_ WDFCOLLECTION _In_ ULONG Index
ULONG LastInitializedWsle
Definition: mmtypes.h:873
ULONG64 Valid
Definition: mmtypes.h:150
ULONG MustBeZero
Definition: mmtypes.h:836
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
LONG NextFree
Definition: mmtypes.h:845
PMMWSLE Wsle
Definition: mmtypes.h:872
#define PAGE_SIZE
Definition: env_spec_w32.h:49
PFN_NUMBER NTAPI MiRemoveAnyPage(IN ULONG Color)
Definition: pfnlist.c:477
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG FirstFree
Definition: mmtypes.h:868
VOID NTAPI MiInitializePfnAndMakePteValid(IN PFN_NUMBER PageFrameIndex, IN PMMPTE PointerPte, IN MMPTE TempPte)
Definition: pfnlist.c:1043
unsigned int ULONG
Definition: retypes.h:1
static ULONG GetNextPageColorForWsList(PMMWSL WsList)
Definition: wslist.cpp:29
ULONG LastEntry
Definition: mmtypes.h:870
union _MMPTE::@2287 u
Definition: mmtypes.h:834
#define ULONG_MAX
Definition: limits.h:44
ULONG PageFrameNumber
Definition: mmtypes.h:109

Referenced by MiInsertInWorkingSetList().

◆ GetNextPageColorForWsList()

static ULONG GetNextPageColorForWsList ( PMMWSL  WsList)
static

Definition at line 29 of file wslist.cpp.

30 {
32 }
#define MI_GET_NEXT_COLOR()
Definition: miarm.h:237
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define MI_GET_NEXT_PROCESS_COLOR(x)
Definition: miarm.h:238
PMMWSL MmSystemCacheWorkingSetList
Definition: mminit.c:174

Referenced by GetFreeWsleIndex().

◆ GetPteTemplateForWsList()

static MMPTE GetPteTemplateForWsList ( PMMWSL  WsList)
static

Definition at line 24 of file wslist.cpp.

25 {
27 }
MMPTE ValidKernelPteLocal
Definition: init.c:33
MMPTE ValidKernelPte
Definition: init.c:29
PMMWSL MmSystemCacheWorkingSetList
Definition: mminit.c:174

Referenced by GetFreeWsleIndex().

◆ MiInitializeWorkingSetList()

_Use_decl_annotations_ VOID NTAPI MiInitializeWorkingSetList ( _Inout_ PMMSUPPORT  WorkingSet)

Definition at line 369 of file wslist.cpp.

370 {
371  PMMWSL WsList = WorkingSet->VmWorkingSetList;
372 
373  /* Initialize some fields */
374  WsList->FirstFree = ULONG_MAX;
375  WsList->Wsle = reinterpret_cast<PMMWSLE>(WsList + 1);
376  WsList->LastEntry = 0;
377  /* The first page is already allocated */
378  WsList->LastInitializedWsle = (PAGE_SIZE - sizeof(*WsList)) / sizeof(MMWSLE);
379 
380  /* Insert the address we already know: our PDE base and the Working Set List */
381  if (MI_IS_PROCESS_WORKING_SET(WorkingSet))
382  {
383  ASSERT(WorkingSet->VmWorkingSetList == MmWorkingSetList);
384 #if _MI_PAGING_LEVELS == 4
385  MiInsertInWorkingSetList(WorkingSet, (PVOID)PXE_BASE, 0U);
386 #elif _MI_PAGING_LEVELS == 3
387  MiInsertInWorkingSetList(WorkingSet, (PVOID)PPE_BASE, 0U);
388 #elif _MI_PAGING_LEVELS == 2
389  MiInsertInWorkingSetList(WorkingSet, (PVOID)PDE_BASE, 0U);
390 #endif
391  }
392 
393 #if _MI_PAGING_LEVELS == 4
394  MiInsertInWorkingSetList(WorkingSet, MiAddressToPpe(WorkingSet->VmWorkingSetList), 0UL);
395 #endif
396 #if _MI_PAGING_LEVELS >= 3
397  MiInsertInWorkingSetList(WorkingSet, MiAddressToPde(WorkingSet->VmWorkingSetList), 0UL);
398 #endif
399  MiInsertInWorkingSetList(WorkingSet, (PVOID)MiAddressToPte(WorkingSet->VmWorkingSetList), 0UL);
400  MiInsertInWorkingSetList(WorkingSet, (PVOID)WorkingSet->VmWorkingSetList, 0UL);
401 
402  /* From now on, every added page can be trimmed at any time */
403  WsList->FirstDynamic = WsList->LastEntry;
404 
405  /* We can add this to our list */
406  ExInterlockedInsertTailList(&MmWorkingSetExpansionHead, &WorkingSet->WorkingSetExpansionLinks, &MmExpansionLock);
407 }
FORCEINLINE BOOLEAN MI_IS_PROCESS_WORKING_SET(PMMSUPPORT WorkingSet)
Definition: miarm.h:666
#define MiAddressToPde(x)
Definition: mmx86.c:20
ULONG FirstDynamic
Definition: mmtypes.h:869
PLIST_ENTRY NTAPI ExInterlockedInsertTailList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:140
#define U(x)
Definition: wordpad.c:45
FORCEINLINE PMMPTE MiAddressToPpe(PVOID Address)
Definition: mm.h:154
KSPIN_LOCK MmExpansionLock
Definition: session.c:32
PMMWSL MmWorkingSetList
Definition: wslist.cpp:19
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define PDE_BASE
Definition: winldr.c:21
#define ASSERT(a)
Definition: mode.c:44
ULONG LastInitializedWsle
Definition: mmtypes.h:873
#define PPE_BASE
PMMWSLE Wsle
Definition: mmtypes.h:872
#define PAGE_SIZE
Definition: env_spec_w32.h:49
LIST_ENTRY MmWorkingSetExpansionHead
Definition: session.c:30
#define PXE_BASE
ULONG FirstFree
Definition: mmtypes.h:868
_Use_decl_annotations_ VOID NTAPI MiInsertInWorkingSetList(_Inout_ PMMSUPPORT Vm, _In_ PVOID Address, _In_ ULONG Protection)
Definition: wslist.cpp:314
ULONG LastEntry
Definition: mmtypes.h:870
#define UL
Definition: tui.h:82
#define ULONG_MAX
Definition: limits.h:44

Referenced by MmInitializeProcessAddressSpace().

◆ MiInsertInWorkingSetList()

_Use_decl_annotations_ VOID NTAPI MiInsertInWorkingSetList ( _Inout_ PMMSUPPORT  Vm,
_In_ PVOID  Address,
_In_ ULONG  Protection 
)

Definition at line 314 of file wslist.cpp.

318 {
319  PMMWSL WsList = Vm->VmWorkingSetList;
320 
321  /* Make sure that we are holding the WS lock. */
323 
324  PMMPTE PointerPte = MiAddressToPte(Address);
325 
326  /* Make sure we are adding a paged-in address */
327  ASSERT(PointerPte->u.Hard.Valid == 1);
328  PMMPFN Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
330 
331  /* Shared pages not supported yet */
332  ASSERT(Pfn1->u1.WsIndex == 0);
333  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
334 
335  /* Nor are "ROS PFN" */
336  ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
337 
338  Pfn1->u1.WsIndex = GetFreeWsleIndex(WsList);
339  MMWSLENTRY& NewWsle = WsList->Wsle[Pfn1->u1.WsIndex].u1.e1;
340  NewWsle.VirtualPageNumber = reinterpret_cast<ULONG_PTR>(Address) >> PAGE_SHIFT;
341  NewWsle.Protection = Protection;
342  NewWsle.Direct = 1;
343  NewWsle.Hashed = 0;
344  NewWsle.LockedInMemory = 0;
345  NewWsle.LockedInWs = 0;
346  NewWsle.Age = 0;
347  NewWsle.Valid = 1;
348 
349  Vm->WorkingSetSize += PAGE_SIZE;
350  if (Vm->WorkingSetSize > Vm->PeakWorkingSetSize)
351  Vm->PeakWorkingSetSize = Vm->WorkingSetSize;
352 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
ULONG_PTR Age
Definition: mmtypes.h:830
MMWSLENTRY e1
Definition: mmtypes.h:855
union _MMPFN::@1761 u3
union _MMWSLE::@2557 u1
USHORT PageLocation
Definition: mm.h:354
USHORT PrototypePte
Definition: mm.h:352
MMPFNENTRY e1
Definition: mm.h:386
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
ULONG_PTR Hashed
Definition: mmtypes.h:828
static WCHAR Address[46]
Definition: ping.c:68
#define ASSERT(a)
Definition: mode.c:44
ULONG64 Valid
Definition: mmtypes.h:150
ULONG_PTR VirtualPageNumber
Definition: mmtypes.h:831
PMMWSLE Wsle
Definition: mmtypes.h:872
Definition: mm.h:362
#define PAGE_SIZE
Definition: env_spec_w32.h:49
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
ULONG_PTR Valid
Definition: mmtypes.h:824
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG_PTR LockedInMemory
Definition: mmtypes.h:826
#define MI_IS_ROS_PFN(x)
Definition: miarm.h:1108
static ULONG GetFreeWsleIndex(PMMWSL WsList)
Definition: wslist.cpp:149
FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD_EXCLUSIVE(_In_ PETHREAD Thread)
Definition: miarm.h:1070
ULONG WsIndex
Definition: mm.h:367
union _MMPFN::@1759 u1
ULONG_PTR LockedInWs
Definition: mmtypes.h:825
ULONG_PTR Protection
Definition: mmtypes.h:827
ULONG_PTR Direct
Definition: mmtypes.h:829
union _MMPTE::@2287 u
#define PFN_FROM_PTE(v)
Definition: mm.h:92

Referenced by MiInitializeWorkingSetList().

◆ MiRemoveFromWorkingSetList()

_Use_decl_annotations_ VOID NTAPI MiRemoveFromWorkingSetList ( _Inout_ PMMSUPPORT  Vm,
_In_ PVOID  Address 
)

Definition at line 357 of file wslist.cpp.

360 {
361  RemoveFromWsList(Vm->VmWorkingSetList, Address);
362 
363  Vm->WorkingSetSize -= PAGE_SIZE;
364 }
static WCHAR Address[46]
Definition: ping.c:68
static VOID RemoveFromWsList(PMMWSL WsList, PVOID Address)
Definition: wslist.cpp:194
#define PAGE_SIZE
Definition: env_spec_w32.h:49

◆ MmWorkingSetManager()

VOID NTAPI MmWorkingSetManager ( VOID  )

Definition at line 411 of file wslist.cpp.

412 {
413  PLIST_ENTRY VmListEntry;
414  PMMSUPPORT Vm = NULL;
415  KIRQL OldIrql;
416 
418 
419  for (VmListEntry = MmWorkingSetExpansionHead.Flink;
420  VmListEntry != &MmWorkingSetExpansionHead;
421  VmListEntry = VmListEntry->Flink)
422  {
425 
426  /* Don't do anything if we have plenty of free pages. */
428  break;
429 
430  Vm = CONTAINING_RECORD(VmListEntry, MMSUPPORT, WorkingSetExpansionLinks);
431 
432  /* Let the legacy Mm System space alone */
433  if (Vm == MmGetKernelAddressSpace())
434  continue;
435 
437  {
439 
440  /* Make sure the process is not terminating abd attach to it */
441  if (!ExAcquireRundownProtection(&Process->RundownProtect))
442  continue;
444  KeAttachProcess(&Process->Pcb);
445  }
446  else
447  {
448  /* FIXME: Session & system space unsupported */
449  continue;
450  }
451 
453 
454  /* Share-lock for now, we're only reading */
456 
457  if (((Vm->WorkingSetSize > Vm->MaximumWorkingSetSize) ||
458  (TrimHard && (Vm->WorkingSetSize > Vm->MinimumWorkingSetSize))) &&
460  {
461  /* We're done */
462  Vm->Flags.BeingTrimmed = 1;
463 
464  ULONG Trimmed = TrimWsList(Vm->VmWorkingSetList);
465 
466  /* We're done */
467  Vm->WorkingSetSize -= Trimmed * PAGE_SIZE;
468  Vm->Flags.BeingTrimmed = 0;
470  }
471  else
472  {
474  }
475 
476  /* Lock again */
478 
479  if (Process)
480  {
481  KeDetachProcess();
482  ExReleaseRundownProtection(&Process->RundownProtect);
483  }
484  }
485 
487 }
FORCEINLINE BOOLEAN MI_IS_PROCESS_WORKING_SET(PMMSUPPORT WorkingSet)
Definition: miarm.h:666
FORCEINLINE KIRQL MiAcquireExpansionLock(VOID)
Definition: miarm.h:1536
PFN_NUMBER MmMinimumFreePages
Definition: mminit.c:314
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
NTKERNELAPI VOID FASTCALL ExReleaseRundownProtection(_Inout_ PEX_RUNDOWN_REF RunRef)
static ULONG TrimWsList(PMMWSL WsList)
Definition: wslist.cpp:220
PMMWSL VmWorkingSetList
Definition: mmtypes.h:940
#define ExAcquireRundownProtection
Definition: ex.h:133
ULONG MinimumWorkingSetSize
Definition: mmtypes.h:938
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG BeingTrimmed
Definition: mmtypes.h:903
PFN_NUMBER MmPlentyFreePages
Definition: mminit.c:322
BOOLEAN NTAPI KeIsAttachedProcess(VOID)
Definition: procobj.c:693
unsigned char BOOLEAN
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1356
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
KIRQL OldIrql
Definition: mm.h:1502
MMSUPPORT_FLAGS Flags
Definition: mmtypes.h:930
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define ASSERT(a)
Definition: mode.c:44
MMPFNLIST MmModifiedPageListHead
Definition: pfnlist.c:45
VOID NTAPI KeDetachProcess(VOID)
Definition: procobj.c:621
FORCEINLINE VOID MiUnlockWorkingSetShared(_In_ PETHREAD Thread, _In_ PMMSUPPORT WorkingSet)
Definition: miarm.h:1394
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
LIST_ENTRY MmWorkingSetExpansionHead
Definition: session.c:30
FORCEINLINE PMMSUPPORT MmGetKernelAddressSpace(VOID)
Definition: mm.h:1640
FORCEINLINE VOID MiLockWorkingSetShared(_In_ PETHREAD Thread, _In_ PMMSUPPORT WorkingSet)
Definition: miarm.h:1311
VOID NTAPI KeAttachProcess(IN PKPROCESS Process)
Definition: procobj.c:582
PFN_NUMBER Total
Definition: mm.h:432
#define NULL
Definition: types.h:112
FORCEINLINE VOID MiReleaseExpansionLock(KIRQL OldIrql)
Definition: miarm.h:1549
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
FORCEINLINE BOOLEAN MiConvertSharedWorkingSetLockToExclusive(_In_ PETHREAD Thread, _In_ PMMSUPPORT Vm)
Definition: miarm.h:1433
unsigned int ULONG
Definition: retypes.h:1
ULONG MaximumWorkingSetSize
Definition: mmtypes.h:939
ULONG WorkingSetSize
Definition: mmtypes.h:954

◆ RemoveFromWsList()

static VOID RemoveFromWsList ( PMMWSL  WsList,
PVOID  Address 
)
static

Definition at line 194 of file wslist.cpp.

195 {
196  /* Make sure that we are holding the right locks. */
198 
199  PMMPTE PointerPte = MiAddressToPte(Address);
200 
201  /* Make sure we are removing a paged-in address */
202  ASSERT(PointerPte->u.Hard.Valid == 1);
203  PMMPFN Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));
205 
206  /* Shared pages not supported yet */
207  ASSERT(Pfn1->u3.e1.PrototypePte == 0);
208 
209  /* Nor are "ROS PFN" */
210  ASSERT(MI_IS_ROS_PFN(Pfn1) == FALSE);
211 
212  /* And we should have a valid index here */
213  ASSERT(Pfn1->u1.WsIndex != 0);
214 
215  FreeWsleIndex(WsList, Pfn1->u1.WsIndex);
216 }
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
union _MMPFN::@1761 u3
USHORT PageLocation
Definition: mm.h:354
USHORT PrototypePte
Definition: mm.h:352
MMPFNENTRY e1
Definition: mm.h:386
#define MiAddressToPte(x)
Definition: mmx86.c:19
#define FALSE
Definition: types.h:117
static WCHAR Address[46]
Definition: ping.c:68
#define ASSERT(a)
Definition: mode.c:44
ULONG64 Valid
Definition: mmtypes.h:150
static void FreeWsleIndex(PMMWSL WsList, ULONG Index)
Definition: wslist.cpp:34
Definition: mm.h:362
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
#define MI_IS_ROS_PFN(x)
Definition: miarm.h:1108
FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD_EXCLUSIVE(_In_ PETHREAD Thread)
Definition: miarm.h:1070
ULONG WsIndex
Definition: mm.h:367
union _MMPFN::@1759 u1
union _MMPTE::@2287 u
#define PFN_FROM_PTE(v)
Definition: mm.h:92

Referenced by MiRemoveFromWorkingSetList(), and TrimWsList().

◆ TrimWsList()

static ULONG TrimWsList ( PMMWSL  WsList)
static

Definition at line 220 of file wslist.cpp.

221 {
222  /* This should be done under WS lock */
224 
225  ULONG Ret = 0;
226 
227  /* Walk the array */
228  for (ULONG i = WsList->FirstDynamic; i < WsList->LastEntry; i++)
229  {
230  MMWSLE& Entry = WsList->Wsle[i];
231  if (!Entry.u1.e1.Valid)
232  continue;
233 
234  /* Only direct entries for now */
235  ASSERT(Entry.u1.e1.Direct == 1);
236 
237  /* Check the PTE */
238  PMMPTE PointerPte = MiAddressToPte(Entry.u1.VirtualAddress);
239 
240  /* This must be valid */
241  ASSERT(PointerPte->u.Hard.Valid);
242 
243  /* If the PTE was accessed, simply reset and that's the end of it */
244  if (PointerPte->u.Hard.Accessed)
245  {
246  Entry.u1.e1.Age = 0;
247  PointerPte->u.Hard.Accessed = 0;
248  KeInvalidateTlbEntry(Entry.u1.VirtualAddress);
249  continue;
250  }
251 
252  /* If the entry is not so old, just age it */
253  if (Entry.u1.e1.Age < 3)
254  {
255  Entry.u1.e1.Age++;
256  continue;
257  }
258 
259  if ((Entry.u1.e1.LockedInMemory) || (Entry.u1.e1.LockedInWs))
260  {
261  /* This one is locked. Next time, maybe... */
262  continue;
263  }
264 
265  /* FIXME: Invalidating PDEs breaks legacy MMs */
266  if (MI_IS_PAGE_TABLE_ADDRESS(Entry.u1.VirtualAddress))
267  continue;
268 
269  /* Please put yourself aside and make place for the younger ones */
270  PFN_NUMBER Page = PFN_FROM_PTE(PointerPte);
271  {
272  ntoskrnl::MiPfnLockGuard PfnLock;
273 
274  PMMPFN Pfn = MiGetPfnEntry(Page);
275 
276  /* Not supported yet */
277  ASSERT(Pfn->u3.e1.PrototypePte == 0);
278  ASSERT(!MI_IS_ROS_PFN(Pfn));
279 
280  /* FIXME: Remove this hack when possible */
281  if (Pfn->Wsle.u1.e1.LockedInMemory || (Pfn->Wsle.u1.e1.LockedInWs))
282  {
283  continue;
284  }
285 
286  /* We can remove it from the list. Save Protection first */
287  ULONG Protection = Entry.u1.e1.Protection;
288  RemoveFromWsList(WsList, Entry.u1.VirtualAddress);
289 
290  /* Dirtify the page, if needed */
291  if (PointerPte->u.Hard.Dirty)
292  Pfn->u3.e1.Modified = 1;
293 
294  /* Make this a transition PTE */
295  MI_MAKE_TRANSITION_PTE(PointerPte, Page, Protection);
297 
298  /* Drop the share count. This will take care of putting it in the standby or modified list. */
300  }
301 
302  Ret++;
303  }
304  return Ret;
305 }
#define MI_IS_PAGE_TABLE_ADDRESS(Address)
Definition: miarm.h:177
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
MMWSLENTRY e1
Definition: mmtypes.h:855
ULONG FirstDynamic
Definition: mmtypes.h:869
union _MMPFN::@1761 u3
USHORT Modified
Definition: mm.h:349
union _MMWSLE::@2557 u1
MMWSLE Wsle
Definition: mm.h:423
USHORT PrototypePte
Definition: mm.h:352
ULONG64 Dirty
Definition: mmtypes.h:164
FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
Definition: miarm.h:1057
MMPFNENTRY e1
Definition: mm.h:386
#define MiAddressToPte(x)
Definition: mmx86.c:19
ULONG PFN_NUMBER
Definition: ke.h:9
FORCEINLINE VOID MI_MAKE_TRANSITION_PTE(_Out_ PMMPTE NewPte, _In_ PFN_NUMBER Page, _In_ ULONG Protection)
Definition: miarm.h:934
VOID NTAPI MiDecrementShareCount(IN PMMPFN Pfn1, IN PFN_NUMBER PageFrameIndex)
Definition: pfnlist.c:1143
PFN_NUMBER Page
Definition: section.c:4888
FORCEINLINE VOID KeInvalidateTlbEntry(IN PVOID Address)
Definition: ke.h:260
#define ASSERT(a)
Definition: mode.c:44
ULONG64 Valid
Definition: mmtypes.h:150
static VOID RemoveFromWsList(PMMWSL WsList, PVOID Address)
Definition: wslist.cpp:194
PMMWSLE Wsle
Definition: mmtypes.h:872
Definition: mm.h:362
FORCEINLINE PMMPFN MiGetPfnEntry(IN PFN_NUMBER Pfn)
Definition: mm.h:1000
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ULONG_PTR LockedInMemory
Definition: mmtypes.h:826
#define MI_IS_ROS_PFN(x)
Definition: miarm.h:1108
unsigned int ULONG
Definition: retypes.h:1
ULONG_PTR LockedInWs
Definition: mmtypes.h:825
union _MMPTE::@2287 u
#define PFN_FROM_PTE(v)
Definition: mm.h:92
ULONG64 Accessed
Definition: mmtypes.h:163
base of all file and directory entries
Definition: entries.h:82

Referenced by MmWorkingSetManager().

Variable Documentation

◆ MmWorkingSetList

◆ MmWorkingSetManagerEvent

KEVENT MmWorkingSetManagerEvent

Definition at line 20 of file wslist.cpp.