ReactOS 0.4.16-dev-747-gbc52d5f
balance.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include "ARM3/miarm.h"
Include dependency graph for balance.c:

Go to the source code of this file.

Classes

struct  _MM_ALLOCATION_REQUEST
 

Macros

#define NDEBUG
 

Typedefs

typedef struct _MM_ALLOCATION_REQUEST MM_ALLOCATION_REQUEST
 
typedef struct _MM_ALLOCATION_REQUESTPMM_ALLOCATION_REQUEST
 

Functions

VOID NTAPI MmInitializeBalancer (ULONG NrAvailablePages, ULONG NrSystemPages)
 
VOID NTAPI MmInitializeMemoryConsumer (ULONG Consumer, NTSTATUS(*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed))
 
VOID NTAPI MiZeroPhysicalPage (IN PFN_NUMBER PageFrameIndex)
 
NTSTATUS NTAPI MmReleasePageMemoryConsumer (ULONG Consumer, PFN_NUMBER Page)
 
ULONG NTAPI MiTrimMemoryConsumer (ULONG Consumer, ULONG InitialTarget)
 
NTSTATUS MmTrimUserMemory (ULONG Target, ULONG Priority, PULONG NrFreedPages)
 
VOID NTAPI MmRebalanceMemoryConsumers (VOID)
 
VOID NTAPI MmRebalanceMemoryConsumersAndWait (VOID)
 
NTSTATUS NTAPI MmRequestPageMemoryConsumer (ULONG Consumer, BOOLEAN CanWait, PPFN_NUMBER AllocatedPage)
 
VOID CcRosTrimCache (_In_ ULONG Target, _Out_ PULONG NrFreed)
 
VOID NTAPI MiBalancerThread (PVOID Unused)
 
VOID NTAPI MiInitBalancerThread (VOID)
 

Variables

MM_MEMORY_CONSUMER MiMemoryConsumers [MC_MAXIMUM]
 
static ULONG MiMinimumAvailablePages
 
static ULONG MiMinimumPagesPerRun
 
static CLIENT_ID MiBalancerThreadId
 
static HANDLE MiBalancerThreadHandle = NULL
 
static KEVENT MiBalancerEvent
 
static KEVENT MiBalancerDoneEvent
 
static KTIMER MiBalancerTimer
 
static LONG PageOutThreadActive
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file balance.c.

Typedef Documentation

◆ MM_ALLOCATION_REQUEST

◆ PMM_ALLOCATION_REQUEST

Function Documentation

◆ CcRosTrimCache()

VOID CcRosTrimCache ( _In_ ULONG  Target,
_Out_ PULONG  NrFreed 
)

Definition at line 456 of file view.c.

466{
467 PLIST_ENTRY current_entry;
469 ULONG PagesFreed;
470 KIRQL oldIrql;
471 LIST_ENTRY FreeList;
472 BOOLEAN FlushedPages = FALSE;
473
474 DPRINT("CcRosTrimCache(Target %lu)\n", Target);
475
476 InitializeListHead(&FreeList);
477
478 *NrFreed = 0;
479
480retry:
482
483 current_entry = VacbLruListHead.Flink;
484 while (current_entry != &VacbLruListHead)
485 {
486 ULONG Refs;
487
488 current = CONTAINING_RECORD(current_entry,
489 ROS_VACB,
490 VacbLruListEntry);
491
492 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
493
494 /* Reference the VACB */
496
497 /* Check if it's mapped and not dirty */
498 if (InterlockedCompareExchange((PLONG)&current->MappedCount, 0, 0) > 0 && !current->Dirty)
499 {
500 /* This code is never executed. It is left for reference only. */
501#if 1
502 DPRINT1("MmPageOutPhysicalAddress unexpectedly called\n");
503 ASSERT(FALSE);
504#else
505 ULONG i;
507
508 /* We have to break these locks to call MmPageOutPhysicalAddress */
509 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
511
512 /* Page out the VACB */
513 for (i = 0; i < VACB_MAPPING_GRANULARITY / PAGE_SIZE; i++)
514 {
516
518 }
519
520 /* Reacquire the locks */
522 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock);
523#endif
524 }
525
526 /* Only keep iterating though the loop while the lock is held */
527 current_entry = current_entry->Flink;
528
529 /* Dereference the VACB */
531
532 /* Check if we can free this entry now */
533 if (Refs < 2)
534 {
535 ASSERT(!current->Dirty);
536 ASSERT(!current->MappedCount);
537 ASSERT(Refs == 1);
538
539 RemoveEntryList(&current->CacheMapVacbListEntry);
540 RemoveEntryList(&current->VacbLruListEntry);
541 InitializeListHead(&current->VacbLruListEntry);
542 InsertHeadList(&FreeList, &current->CacheMapVacbListEntry);
543
544 /* Calculate how many pages we freed for Mm */
546 Target -= PagesFreed;
547 (*NrFreed) += PagesFreed;
548 }
549
550 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock);
551 }
552
554
555 /* Try flushing pages if we haven't met our target */
556 if ((Target > 0) && !FlushedPages)
557 {
558 /* Flush dirty pages to disk */
559 CcRosFlushDirtyPages(Target, &PagesFreed, FALSE, FALSE);
560 FlushedPages = TRUE;
561
562 /* We can only swap as many pages as we flushed */
563 if (PagesFreed < Target) Target = PagesFreed;
564
565 /* Check if we flushed anything */
566 if (PagesFreed != 0)
567 {
568 /* Try again after flushing dirty pages */
569 DPRINT("Flushed %lu dirty cache pages to disk\n", PagesFreed);
570 goto retry;
571 }
572 }
573
574 while (!IsListEmpty(&FreeList))
575 {
576 ULONG Refs;
577
578 current_entry = RemoveHeadList(&FreeList);
579 current = CONTAINING_RECORD(current_entry,
580 ROS_VACB,
581 CacheMapVacbListEntry);
582 InitializeListHead(&current->CacheMapVacbListEntry);
584 ASSERT(Refs == 0);
585 }
586
587 DPRINT("Evicted %lu cache pages\n", (*NrFreed));
588}
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
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
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define ASSERT(a)
Definition: mode.c:44
struct task_struct * current
Definition: linux.c:32
#define min(a, b)
Definition: monoChain.cc:55
static LIST_ENTRY VacbLruListHead
Definition: view.c:42
NTSTATUS CcRosFlushDirtyPages(ULONG Target, PULONG Count, BOOLEAN Wait, BOOLEAN CalledFromLazy)
Definition: view.c:308
#define CcRosVacbIncRefCount(vacb)
Definition: cc.h:496
FORCEINLINE ULONG CcRosVacbDecRefCount(PROS_VACB vacb)
Definition: cc.h:499
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1313
NTSTATUS NTAPI MmPageOutPhysicalAddress(PFN_NUMBER Page)
Definition: rmap.c:51
PHYSICAL_ADDRESS NTAPI MmGetPhysicalAddress(IN PVOID Address)
Definition: stubs.c:685
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
ULONG PFN_NUMBER
Definition: ke.h:9
#define DPRINT
Definition: sndvol32.h:73
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: cc.h:208
int32_t * PLONG
Definition: typedefs.h:58
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
#define VACB_MAPPING_GRANULARITY
@ LockQueueMasterLock
Definition: ketypes.h:663

Referenced by MiBalancerThread().

◆ MiBalancerThread()

VOID NTAPI MiBalancerThread ( PVOID  Unused)

Definition at line 354 of file balance.c.

355{
356 PVOID WaitObjects[2];
358
359 WaitObjects[0] = &MiBalancerEvent;
360 WaitObjects[1] = &MiBalancerTimer;
361
362 while (TRUE)
363 {
366 WaitObjects,
367 WaitAny,
368 Executive,
370 FALSE,
371 NULL,
372 NULL);
373
375 {
376 ULONG InitialTarget = 0;
378 ULONG NrFreedPages;
379
380 do
381 {
382 ULONG OldTarget = InitialTarget;
383
384 /* Trim each consumer */
385 for (ULONG i = 0; i < MC_MAXIMUM; i++)
386 {
387 InitialTarget = MiTrimMemoryConsumer(i, InitialTarget);
388 }
389
390 /* Trim cache */
392 if (Target)
393 {
394 CcRosTrimCache(Target, &NrFreedPages);
395 InitialTarget -= min(NrFreedPages, InitialTarget);
396 }
397
398 /* No pages left to swap! */
399 if (InitialTarget != 0 &&
400 InitialTarget == OldTarget)
401 {
402 /* Game over */
403 KeBugCheck(NO_PAGES_AVAILABLE);
404 }
405 }
406 while (InitialTarget != 0);
407
408 if (Status == STATUS_WAIT_0)
409 {
411 ASSERT(Active == 1);
413 }
414 }
415 else
416 {
417 DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
418 KeBugCheck(MEMORY_MANAGEMENT);
419 }
420 }
421}
#define InterlockedExchange
Definition: armddk.h:54
LONG NTSTATUS
Definition: precomp.h:26
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1434
#define NULL
Definition: types.h:112
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define abs(i)
Definition: fconv.c:206
Status
Definition: gdiplustypes.h:25
#define KernelMode
Definition: asm.h:38
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:327
@ WaitAny
PFN_NUMBER MmAvailablePages
Definition: freelist.c:26
#define MC_MAXIMUM
Definition: mm.h:116
NTSTATUS NTAPI KeWaitForMultipleObjects(IN ULONG Count, IN PVOID Object[], IN WAIT_TYPE WaitType, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PKWAIT_BLOCK WaitBlockArray OPTIONAL)
Definition: wait.c:586
static KTIMER MiBalancerTimer
Definition: balance.c:35
static KEVENT MiBalancerDoneEvent
Definition: balance.c:34
static ULONG MiMinimumAvailablePages
Definition: balance.c:29
static KEVENT MiBalancerEvent
Definition: balance.c:33
ULONG NTAPI MiTrimMemoryConsumer(ULONG Consumer, ULONG InitialTarget)
Definition: balance.c:96
VOID CcRosTrimCache(_In_ ULONG Target, _Out_ PULONG NrFreed)
Definition: view.c:456
static LONG PageOutThreadActive
Definition: balance.c:37
#define STATUS_WAIT_0
Definition: ntstatus.h:237
#define STATUS_WAIT_1
Definition: ntstatus.h:71
long LONG
Definition: pedump.c:60
#define _countof(array)
Definition: sndvol32.h:70
#define max(a, b)
Definition: svc.c:63
#define IO_NO_INCREMENT
Definition: iotypes.h:598
@ Executive
Definition: ketypes.h:415
_In_ ULONG _In_ BOOLEAN Active
Definition: potypes.h:561

Referenced by MiInitBalancerThread().

◆ MiInitBalancerThread()

VOID NTAPI MiInitBalancerThread ( VOID  )

Definition at line 426 of file balance.c.

427{
431
435
436 Timeout.QuadPart = -20000000; /* 2 sec */
438 Timeout,
439 2000, /* 2 sec */
440 NULL);
441
444 NULL,
445 NULL,
448 NULL);
449 if (!NT_SUCCESS(Status))
450 {
451 KeBugCheck(MEMORY_MANAGEMENT);
452 }
453
457 &Priority,
458 sizeof(Priority));
459
460}
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
@ ThreadPriority
Definition: compat.h:937
LONG KPRIORITY
Definition: compat.h:803
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define LOW_REALTIME_PRIORITY
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1339
@ SynchronizationEvent
@ SynchronizationTimer
static HANDLE MiBalancerThreadHandle
Definition: balance.c:32
static CLIENT_ID MiBalancerThreadId
Definition: balance.c:31
VOID NTAPI MiBalancerThread(PVOID Unused)
Definition: balance.c:354
NTSTATUS NTAPI NtSetInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength)
Definition: query.c:2067
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
static ULONG Timeout
Definition: ping.c:61
BOOLEAN NTAPI KeSetTimerEx(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN LONG Period, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:294
VOID NTAPI KeInitializeTimerEx(OUT PKTIMER Timer, IN TIMER_TYPE Type)
Definition: timerobj.c:244
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY _In_ WDF_INTERRUPT_PRIORITY Priority
Definition: wdfinterrupt.h:655

Referenced by MmInitSystem().

◆ MiTrimMemoryConsumer()

ULONG NTAPI MiTrimMemoryConsumer ( ULONG  Consumer,
ULONG  InitialTarget 
)

Definition at line 96 of file balance.c.

97{
98 ULONG Target = InitialTarget;
99 ULONG NrFreedPages = 0;
101
102 /* Make sure we can trim this consumer */
103 if (!MiMemoryConsumers[Consumer].Trim)
104 {
105 /* Return the unmodified initial target */
106 return InitialTarget;
107 }
108
110 {
111 /* Global page limit exceeded */
113 }
114 else if (MiMemoryConsumers[Consumer].PagesUsed > MiMemoryConsumers[Consumer].PagesTarget)
115 {
116 /* Consumer page limit exceeded */
117 Target = max(Target, MiMemoryConsumers[Consumer].PagesUsed - MiMemoryConsumers[Consumer].PagesTarget);
118 }
119
120 if (Target)
121 {
122 /* Now swap the pages out */
124
125 DPRINT("Trimming consumer %lu: Freed %lu pages with a target of %lu pages\n", Consumer, NrFreedPages, Target);
126
127 if (!NT_SUCCESS(Status))
128 {
129 KeBugCheck(MEMORY_MANAGEMENT);
130 }
131 }
132
133 /* Return the page count needed to be freed to meet the initial target */
134 return (InitialTarget > NrFreedPages) ? (InitialTarget - NrFreedPages) : 0;
135}
MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM]
Definition: balance.c:28
NTSTATUS(* Trim)(ULONG Target, ULONG Priority, PULONG NrFreed)
Definition: mm.h:466

Referenced by MiBalancerThread().

◆ MiZeroPhysicalPage()

VOID NTAPI MiZeroPhysicalPage ( IN PFN_NUMBER  PageFrameIndex)

Definition at line 122 of file pfnlist.c.

123{
127
128 /* Map in hyperspace, then wipe it using XMMI or MEMSET */
133}
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: cpu.c:56
VOID NTAPI MiUnmapPageInHyperSpace(IN PEPROCESS Process, IN PVOID Address, IN KIRQL OldIrql)
Definition: hypermap.c:91
PVOID NTAPI MiMapPageInHyperSpace(IN PEPROCESS Process, IN PFN_NUMBER Page, IN PKIRQL OldIrql)
Definition: hypermap.c:28
_Must_inspect_result_ _In_ WDFDMATRANSACTION _In_ PFN_WDF_PROGRAM_DMA _In_ WDF_DMA_DIRECTION _In_ PMDL _In_ PVOID VirtualAddress
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
#define PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by MiRemoveZeroPage().

◆ MmInitializeBalancer()

VOID NTAPI MmInitializeBalancer ( ULONG  NrAvailablePages,
ULONG  NrSystemPages 
)

Definition at line 44 of file balance.c.

45{
47
48 /* Set up targets. */
51 MiMemoryConsumers[MC_USER].PagesTarget = NrAvailablePages / 2;
52}
#define MC_USER
Definition: mm.h:114
static ULONG MiMinimumPagesPerRun
Definition: balance.c:30
#define memset(x, y, z)
Definition: compat.h:39
ULONG PagesTarget
Definition: mm.h:465

Referenced by MiInitMachineDependent().

◆ MmInitializeMemoryConsumer()

VOID NTAPI MmInitializeMemoryConsumer ( ULONG  Consumer,
NTSTATUS(*)(ULONG Target, ULONG Priority, PULONG NrFreed)  Trim 
)

Definition at line 57 of file balance.c.

60{
61 MiMemoryConsumers[Consumer].Trim = Trim;
62}

Referenced by MmInitSystem().

◆ MmRebalanceMemoryConsumers()

VOID NTAPI MmRebalanceMemoryConsumers ( VOID  )

Definition at line 290 of file balance.c.

291{
293 {
295 }
296}

Referenced by MiDecrementAvailablePages(), and MmRebalanceMemoryConsumersAndWait().

◆ MmRebalanceMemoryConsumersAndWait()

VOID NTAPI MmRebalanceMemoryConsumersAndWait ( VOID  )

Definition at line 300 of file balance.c.

301{
302 ASSERT(PsGetCurrentProcess()->AddressCreationLock.Owner != KeGetCurrentThread());
305
309}
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
LONG NTAPI KeResetEvent(IN PKEVENT Event)
Definition: eventobj.c:133
#define KeGetCurrentThread
Definition: hal.h:55
FORCEINLINE BOOLEAN MM_ANY_WS_LOCK_HELD(IN PETHREAD Thread)
Definition: miarm.h:1065
VOID NTAPI MmRebalanceMemoryConsumers(VOID)
Definition: balance.c:290

Referenced by MmAccessFault(), and MmArmAccessFault().

◆ MmReleasePageMemoryConsumer()

NTSTATUS NTAPI MmReleasePageMemoryConsumer ( ULONG  Consumer,
PFN_NUMBER  Page 
)

Definition at line 72 of file balance.c.

73{
75
76 if (Page == 0)
77 {
78 DPRINT1("Tried to release page zero.\n");
79 KeBugCheck(MEMORY_MANAGEMENT);
80 }
81
82 (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
84
85 OldIrql = MiAcquirePfnLock();
86
88
89 MiReleasePfnLock(OldIrql);
90
91 return(STATUS_SUCCESS);
92}
#define InterlockedDecrementUL(Addend)
Definition: ex.h:1541
VOID NTAPI MmDereferencePage(PFN_NUMBER Page)
Definition: freelist.c:566
FORCEINLINE VOID UpdateTotalCommittedPages(LONG Delta)
Definition: mm.h:878
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by FreeSegmentPage(), if(), MiFreeSegmentPage(), MiGetOnePage(), MiPurgeImageSegment(), MiReadFilePage(), MmCreateProcessAddressSpace(), MmDeleteVirtualMapping(), MmFinalizeSectionPageOut(), MmFreeCacheSectionPage(), MmFreePageTable(), MmFreeSectionPage(), MmGetPageTableForProcess(), MmGetPageTableForProcessForPAE(), MmMakeSegmentResident(), MmPageOutCacheSection(), MmPageOutPhysicalAddress(), MmpFreePageFileSegment(), MmPurgeSegment(), and MmUnsharePageEntrySectionSegment().

◆ MmRequestPageMemoryConsumer()

NTSTATUS NTAPI MmRequestPageMemoryConsumer ( ULONG  Consumer,
BOOLEAN  CanWait,
PPFN_NUMBER  AllocatedPage 
)

Definition at line 313 of file balance.c.

315{
317
318 /* Delay some requests for the Memory Manager to recover pages (CORE-17624).
319 * FIXME: This is suboptimal.
320 */
321 static INT i = 0;
322 static LARGE_INTEGER TinyTime = {{-1L, -1L}};
323 if (i++ >= 100)
324 {
326 i = 0;
327 }
328
329 /*
330 * Actually allocate the page.
331 */
332 Page = MmAllocPage(Consumer);
333 if (Page == 0)
334 {
335 *AllocatedPage = 0;
336 return STATUS_NO_MEMORY;
337 }
338 *AllocatedPage = Page;
339
340 /* Update the target */
341 InterlockedIncrementUL(&MiMemoryConsumers[Consumer].PagesUsed);
343
344 return(STATUS_SUCCESS);
345}
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1544
PFN_NUMBER NTAPI MmAllocPage(ULONG Consumer)
Definition: freelist.c:602
static LARGE_INTEGER TinyTime
Definition: section.c:63
int32_t INT
Definition: typedefs.h:58

Referenced by CcInitCacheZeroPage(), MiGetOnePage(), MiGetPageTableForProcess(), MiReadFilePage(), MiSwapInPage(), MmAccessFaultSectionView(), MmCreateProcessAddressSpace(), MmGetPageTableForProcess(), MmGetPageTableForProcessForPAE(), MmMakeSegmentResident(), and MmNotPresentFaultSectionView().

◆ MmTrimUserMemory()

NTSTATUS MmTrimUserMemory ( ULONG  Target,
ULONG  Priority,
PULONG  NrFreedPages 
)

Definition at line 138 of file balance.c.

139{
140 PFN_NUMBER FirstPage, CurrentPage;
142
143 (*NrFreedPages) = 0;
144
145 DPRINT("MM BALANCER: %s\n", Priority ? "Paging out!" : "Removing access bit!");
146
147 FirstPage = MmGetLRUFirstUserPage();
148 CurrentPage = FirstPage;
149 while (CurrentPage != 0 && Target > 0)
150 {
151 if (Priority)
152 {
153 Status = MmPageOutPhysicalAddress(CurrentPage);
154 if (NT_SUCCESS(Status))
155 {
156 DPRINT("Succeeded\n");
157 Target--;
158 (*NrFreedPages)++;
159 if (CurrentPage == FirstPage)
160 {
161 FirstPage = 0;
162 }
163 }
164 }
165 else
166 {
167 /* When not paging-out agressively, just reset the accessed bit */
170 BOOLEAN Accessed = FALSE;
171
172 /*
173 * We have a lock-ordering problem here. We cant lock the PFN DB before the Process address space.
174 * So we must use circonvoluted loops.
175 * Well...
176 */
177 while (TRUE)
178 {
180 KIRQL OldIrql = MiAcquirePfnLock();
182 while (Entry)
183 {
184 if (RMAP_IS_SEGMENT(Entry->Address))
185 {
186 Entry = Entry->Next;
187 continue;
188 }
189
190 /* Check that we didn't treat this entry before */
191 if (Entry->Address < Address)
192 {
193 Entry = Entry->Next;
194 continue;
195 }
196
197 if ((Entry->Address == Address) && (Entry->Process <= Process))
198 {
199 Entry = Entry->Next;
200 continue;
201 }
202
203 break;
204 }
205
206 if (!Entry)
207 {
208 MiReleasePfnLock(OldIrql);
209 break;
210 }
211
212 Process = Entry->Process;
213 Address = Entry->Address;
214
216
217 if (!ExAcquireRundownProtection(&Process->RundownProtect))
218 {
220 MiReleasePfnLock(OldIrql);
221 continue;
222 }
223
224 MiReleasePfnLock(OldIrql);
225
228
229 /* Be sure this is still valid. */
231 {
233 Accessed = Accessed || Pte->u.Hard.Accessed;
234 Pte->u.Hard.Accessed = 0;
235
236 /* There is no need to invalidate, the balancer thread is never on a user process */
237 //KeInvalidateTlbEntry(Address);
238 }
239
241
243 ExReleaseRundownProtection(&Process->RundownProtect);
245 }
246
247 if (!Accessed)
248 {
249 /* Nobody accessed this page since the last time we check. Time to clean up */
250
251 Status = MmPageOutPhysicalAddress(CurrentPage);
252 if (NT_SUCCESS(Status))
253 {
254 if (CurrentPage == FirstPage)
255 {
256 FirstPage = 0;
257 }
258 }
259 // DPRINT1("Paged-out one page: %s\n", NT_SUCCESS(Status) ? "Yes" : "No");
260 }
261
262 /* Done for this page. */
263 Target--;
264 }
265
266 CurrentPage = MmGetLRUNextUserPage(CurrentPage, TRUE);
267 if (FirstPage == 0)
268 {
269 FirstPage = CurrentPage;
270 }
271 else if (CurrentPage == FirstPage)
272 {
273 DPRINT1("We are back at the start, abort!\n");
274 return STATUS_SUCCESS;
275 }
276 }
277
278 if (CurrentPage)
279 {
280 KIRQL OldIrql = MiAcquirePfnLock();
281 MmDereferencePage(CurrentPage);
282 MiReleasePfnLock(OldIrql);
283 }
284
285 return STATUS_SUCCESS;
286}
#define ExReleaseRundownProtection
Definition: ex.h:139
#define ExAcquireRundownProtection
Definition: ex.h:138
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1207
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1137
BOOLEAN NTAPI MmIsAddressValid(IN PVOID VirtualAddress)
Definition: mmsup.c:174
#define MiAddressToPte(x)
Definition: mmx86.c:19
struct _MM_RMAP_ENTRY *NTAPI MmGetRmapListHeadPage(PFN_NUMBER Page)
Definition: freelist.c:459
#define RMAP_IS_SEGMENT(x)
Definition: mm.h:947
PFN_NUMBER NTAPI MmGetLRUFirstUserPage(VOID)
Definition: freelist.c:45
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1772
PFN_NUMBER NTAPI MmGetLRUNextUserPage(PFN_NUMBER PreviousPage, BOOLEAN MoveToLast)
Definition: freelist.c:125
static WCHAR Address[46]
Definition: ping.c:68
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
base of all file and directory entries
Definition: entries.h:83
ULONG64 Accessed
Definition: mmtypes.h:163
union _MMPTE::@2342 u
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
Definition: mm.h:273
KAPC_STATE
Definition: ketypes.h:1409
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by MmInitSystem().

Variable Documentation

◆ MiBalancerDoneEvent

KEVENT MiBalancerDoneEvent
static

◆ MiBalancerEvent

KEVENT MiBalancerEvent
static

Definition at line 33 of file balance.c.

Referenced by MiBalancerThread(), MiInitBalancerThread(), and MmRebalanceMemoryConsumers().

◆ MiBalancerThreadHandle

HANDLE MiBalancerThreadHandle = NULL
static

Definition at line 32 of file balance.c.

Referenced by MiInitBalancerThread().

◆ MiBalancerThreadId

CLIENT_ID MiBalancerThreadId
static

Definition at line 31 of file balance.c.

Referenced by MiInitBalancerThread().

◆ MiBalancerTimer

KTIMER MiBalancerTimer
static

Definition at line 35 of file balance.c.

Referenced by MiBalancerThread(), and MiInitBalancerThread().

◆ MiMemoryConsumers

◆ MiMinimumAvailablePages

ULONG MiMinimumAvailablePages
static

Definition at line 29 of file balance.c.

Referenced by MiBalancerThread(), MiTrimMemoryConsumer(), and MmInitializeBalancer().

◆ MiMinimumPagesPerRun

ULONG MiMinimumPagesPerRun
static

Definition at line 30 of file balance.c.

Referenced by MmInitializeBalancer().

◆ PageOutThreadActive

LONG PageOutThreadActive
static

Definition at line 37 of file balance.c.

Referenced by MiBalancerThread(), and MmRebalanceMemoryConsumers().