MiTrimOrAgeWorkingSet
VOID __fastcall MiTrimOrAgeWorkingSet(
_MMSUPPORT_INSTANCE *VmSupport,
_MMWS_TRIM_CRITERIA *TrimCriteria,
UINT64 WorkingSetRequestFlags){
__int16 v3;
__int8 bf_0;
__int64 v6;
char v7;
char *v8;
void *v9;
_ETHREAD *CurrentThread;
struct _KPRCB *CurrentPrcb;
$A184FAFDEBB902F1E6D1F235B14D565F *v12;
_LIST_ENTRY *Flink;
_LIST_ENTRY *v14;
struct _KPRCB *v15;
_EPROCESS *Process;
unsigned __int64 GroupIndex;
__int64 v18;
unsigned __int64 v19;
unsigned __int64 v20;
_MMSUPPORT_INSTANCE *v21;
unsigned __int8 v22;
_MMSUPPORT_INSTANCE *v23;
UINT8 v24;
int v25;
unsigned int v26;
int v27;
NTSTATUS v28;
_MMWS_TRIM_CRITERIA *v29;
volatile unsigned __int64 TickCountQuad;
char v31;
UINT8 v32;
char v33;
_MMSUPPORT_INSTANCE *v34;
_MMSUPPORT_INSTANCE *v35;
volatile __int64 *v36;
struct _KPRCB *v37;
_MM_PAGE_ACCESS_INFO_HEADER *v38;
_SINGLE_LIST_ENTRY *Next;
_SINGLE_LIST_ENTRY *i;
_KSPIN_LOCK_QUEUE *v41;
_MMSUPPORT_FLAGS Flags;
char v43;
_MM_PAGE_ACCESS_INFO_HEADER *v44;
UINT64 v45;
NTSTATUS v46;
NTSTATUS v47;
_MM_PAGE_ACCESS_INFO_HEADER *v48;
_DWORD *SchedulerAssist;
_LIST_ENTRY *Blink;
_LIST_ENTRY *v51;
unsigned __int64 v52;
unsigned __int64 v53;
UINT64 v54;
__int64 v55;
PVOID BugCheckParameter4;
UINT8 CurrentIrql;
UINT8 v59;
_EPROCESS *v60;
INT64 v61[2];
__int64 v62;
UINT64 SpinCount;
__int64 v64;
_KAPC_STATE SavedApcState;
v3 = WorkingSetRequestFlags;
if( VmSupport->Flags.MemoryPriority == 2 && (VmSupport->Flags._bf_0 & 7) == 0 )
PfLogForegroundProcess(VmSupport);
bf_0 = VmSupport->Flags._bf_0;
v6 = *(_QWORD *)(*(_QWORD *)(*(&stru_140C4DB30 + 267) + 8i64 * VmSupport->PartitionId) + 6848i64);
v64 = v6;
v7 = bf_0 & 7;
if( v7 )
{
if( v7 == 1 )
MiAttachSession((_MM_SESSION_SPACE *)&VmSupport[-2].WorkingSetLeafPrivateSize);
}
else
{
v8 = (char *)&VmSupport[-9].AgeDistribution[3];
if( (unsigned __int64 *)KeGetCurrentThread()->Process != &VmSupport[-9].AgeDistribution[3] )
{
memset(&SavedApcState, 0, sizeof(SavedApcState));
WorkingSetRequestFlags = (UINT64)KeGetCurrentThread();
v9 = (void *)*(unsigned __int8 *)(WorkingSetRequestFlags + 586);
if( (_BYTE)v9 )
KeBugCheckEx(5u, &VmSupport[-9].AgeDistribution[3], *(PVOID *)(WorkingSetRequestFlags + 184), v9, 0i64);
CurrentThread = (_ETHREAD *)KeGetCurrentThread();
if( (KeGetPcr()->Prcb._bf_0 & 0x10001) != 0 || (*((_DWORD *)v8 + 158) & 0x400) != 0 )
KeBugCheckEx(
5u,
&VmSupport[-9].AgeDistribution[3],
CurrentThread->Tcb.ApcState.Process,
(PVOID)CurrentThread->Tcb.ApcStateIndex,
(PVOID)(KeGetPcr()->Prcb._bf_0 & 0x10001));
if( (char *)CurrentThread->Tcb.ApcState.Process == v8 )
{
SavedApcState.Process = (_EPROCESS *)1;
}
else
{
CurrentIrql = KeGetCurrentIrql();
__writecr8(2ui64);
CurrentPrcb = KeGetCurrentPrcb();
LODWORD(SpinCount) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)&CurrentThread->Tcb.ThreadLock, 0i64) )
{
do
KeYieldProcessorEx(&SpinCount);
while( CurrentThread->Tcb.ThreadLock );
SchedulerAssist = CurrentPrcb->SchedulerAssist;
if( SchedulerAssist && CurrentPrcb->NestingLevel <= 1u )
++SchedulerAssist[6];
}
if( CurrentThread->Tcb.ApcStateIndex )
{
KiAttachProcess(
&CurrentThread->Tcb,
(_KPROCESS *)&VmSupport[-9].AgeDistribution[3],
CurrentIrql,
1ui64,
&SavedApcState);
}
else
{
v12 = &CurrentThread->Tcb.600;
CurrentThread->Tcb.SavedApcState.Process = CurrentThread->Tcb.ApcState.Process;
CurrentThread->Tcb.SavedApcState.InProgressFlags = CurrentThread->Tcb.ApcState.InProgressFlags;
CurrentThread->Tcb.SavedApcState.KernelApcPending = CurrentThread->Tcb.ApcState.KernelApcPending;
CurrentThread->Tcb.SavedApcState.UserApcPendingAll = CurrentThread->Tcb.ApcState.UserApcPendingAll;
Flink = CurrentThread->Tcb.ApcState.ApcListHead[0].Flink;
if( Flink == (_LIST_ENTRY *)&CurrentThread->Tcb.152 )
{
CurrentThread->Tcb.SavedApcState.ApcListHead[0].Blink = CurrentThread->Tcb.SavedApcState.ApcListHead;
v12->SavedApcState.ApcListHead[0].Flink = (_LIST_ENTRY *)v12;
CurrentThread->Tcb.SavedApcState.KernelApcPending = 0;
}
else
{
Blink = CurrentThread->Tcb.ApcState.ApcListHead[0].Blink;
v12->SavedApcState.ApcListHead[0].Flink = Flink;
CurrentThread->Tcb.SavedApcState.ApcListHead[0].Blink = Blink;
Flink->Blink = (_LIST_ENTRY *)v12;
Blink->Flink = (_LIST_ENTRY *)v12;
}
WorkingSetRequestFlags = (UINT64)CurrentThread->Tcb.ApcState.ApcListHead[1].Flink;
v14 = &CurrentThread->Tcb.SavedApcState.ApcListHead[1];
if( (unsigned __int8 *)WorkingSetRequestFlags == &CurrentThread->Tcb.ApcStateFill[16] )
{
CurrentThread->Tcb.SavedApcState.ApcListHead[1].Blink = &CurrentThread->Tcb.SavedApcState.ApcListHead[1];
v14->Flink = v14;
CurrentThread->Tcb.SavedApcState.UserApcPendingAll = 0;
}
else
{
v51 = CurrentThread->Tcb.ApcState.ApcListHead[1].Blink;
v14->Flink = (_LIST_ENTRY *)WorkingSetRequestFlags;
CurrentThread->Tcb.SavedApcState.ApcListHead[1].Blink = v51;
*(_QWORD *)(WorkingSetRequestFlags + 8) = v14;
v51->Flink = v14;
}
CurrentThread->Tcb.ApcState.ApcListHead[0].Blink = CurrentThread->Tcb.ApcState.ApcListHead;
CurrentThread->Tcb.ApcState.ApcListHead[1].Blink = &CurrentThread->Tcb.ApcState.ApcListHead[1];
CurrentThread->Tcb.ApcState.ApcListHead[1].Flink = &CurrentThread->Tcb.ApcState.ApcListHead[1];
CurrentThread->Tcb.ApcState.ApcListHead[0].Flink = CurrentThread->Tcb.ApcState.ApcListHead;
CurrentThread->Tcb._bf_0 |= 0x800u;
CurrentThread->Tcb.ApcStateIndex = 1;
*(_WORD *)&CurrentThread->Tcb.ApcStateFill[40] = 0;
CurrentThread->Tcb.ApcState.UserApcPendingAll = 0;
CurrentThread->Tcb.ApcState.Process = (_EPROCESS *)v8;
CurrentThread->Tcb.ThreadLock = 0i64;
v15 = KeGetCurrentPrcb();
Process = CurrentThread->Tcb.SavedApcState.Process;
v60 = Process;
GroupIndex = v15->GroupIndex;
v18 = 8i64 * v15->Group + 376;
_interlockedbittestandset64((volatile signed __int32 *)&v8[v18], GroupIndex);
v19 = *((_QWORD *)v8 + 5);
if( KiKvaShadow )
{
v20 = *((_QWORD *)v8 + 5);
if( (v19 & 2) != 0 )
v20 = v19 | 0x8000000000000000ui64;
__writegsqword(0x9000u, v20);
KiSetAddressPolicy(v8[912]);
Process = v60;
}
__writecr3(v19);
if( !KiFlushPcid && KiKvaShadow )
{
v52 = __readcr4();
if( (v52 & 0x20080) != 0 )
{
__writecr4(v52 ^ 0x80);
__writecr4(v52);
}
else
{
v53 = __readcr3();
__writecr3(v53);
}
}
_interlockedbittestandreset64((volatile signed __int32 *)&Process->Pcb.gap0[v18], GroupIndex);
CurrentThread->Tcb._bf_0 &= ~0x800u;
__writecr8(CurrentIrql);
v6 = v64;
}
}
}
}
if( (v3 & 4) != 0 )
MiEmptyWorkingSetInitiate((INT64)VmSupport, 0, 0i64, -1i64);
v21 = (_MMSUPPORT_INSTANCE *)((char *)&stru_140C4DB30 + 6544);
v22 = VmSupport->Flags._bf_0 & 7;
if( v22 >= 6u )
{
v24 = KeGetCurrentIrql();
v59 = v24;
__writecr8(2ui64);
}
else
{
if( v22 == 2 )
v23 = (_MMSUPPORT_INSTANCE *)((char *)&stru_140C4DB30 + 6544);
else
v23 = VmSupport + 1;
v24 = KeGetCurrentIrql();
__writecr8(2ui64);
_m_prefetchw(v23);
v25 = v23->NextPageColor & 0x7FFFFFFF;
if( v25 != _InterlockedCompareExchange((volatile signed __int32 *)v23, v25 + 1, v25) )
{
KiSetVpThreadSpinLockCount();
ExpWaitForSpinLockSharedAndAcquire((INT64 *)v23, v24);
}
if( v23->PageFaultCount )
_InterlockedExchange((volatile __int32 *)&v23->PageFaultCount, 0);
v59 = v24;
}
if( (v3 & 0x20) != 0 && (VmSupport->Flags._bf_0 & 7) == 0 )
{
LODWORD(BugCheckParameter4) = 2;
MiTrimWorkingSet(VmSupport, VmSupport->WorkingSetSize, v24, 0i64, (UINT64)BugCheckParameter4);
}
if( (v3 & 0x100) != 0 )
{
LODWORD(BugCheckParameter4) = 4;
MiTrimWorkingSet(VmSupport, VmSupport->WorkingSetSize, v24, 0i64, (UINT64)BugCheckParameter4);
}
v26 = *(unsigned __int16 *)(v6 + 2346);
v27 = 0;
v28 = 0;
if( (v3 & 1) == 0 )
{
if( (v3 & 2) != 0 )
{
v27 = 1;
v28 = MiAgeWorkingSet(VmSupport, v24, 1ui64, v26);
if( !v28 && *(_BYTE *)(v64 + 55) == 1 && v26 - 1 <= 8 )
v28 = MiAgeWorkingSet(VmSupport, v24, 2ui64, 0xAui64);
v29 = TrimCriteria;
goto LABEL_41;
}
if( (v3 & 0x40) != 0 )
{
v47 = MiAgeWorkingSet(VmSupport, v24, 1ui64, v26);
v29 = TrimCriteria;
v28 = v47;
v27 = 1;
goto LABEL_41;
}
if( (v3 & 0x80u) == 0 )
{
v29 = TrimCriteria;
goto LABEL_41;
}
v45 = 2i64;
LABEL_84:
v46 = MiAgeWorkingSet(VmSupport, v24, v45, v26);
v29 = TrimCriteria;
v27 = 1;
v28 = v46;
goto LABEL_41;
}
TrimCriteria->TrimAge = *((_BYTE *)MiTrimPassToAge + (TrimCriteria->_bf_0 & 0x7F));
LODWORD(v54) = MiComputeTrimAmount(TrimCriteria, VmSupport, WorkingSetRequestFlags);
if( v54 )
{
LODWORD(BugCheckParameter4) = 17;
LODWORD(v55) = MiTrimWorkingSet(VmSupport, v54, v24, TrimCriteria->TrimAge, (UINT64)BugCheckParameter4);
v29 = TrimCriteria;
*(_QWORD *)&TrimCriteria[1].PagesToTrim += v55;
}
else
{
v29 = TrimCriteria;
}
v45 = 0i64;
if( ((v29->_bf_0 & 0x7F) == 0 && v29->_bf_0 >= 0 || (v29->_bf_0 & 0x7F) == 4) && *(_WORD *)(v64 + 2346) )
v45 = 1i64;
if( v29->AgingPolicy == 1 )
goto LABEL_84;
LABEL_41:
TickCountQuad = 0i64;
if( v28 == 1 )
{
v32 = v59;
}
else
{
if( v27 == 1 )
{
v31 = 3;
if( VmSupport->Flags.MemoryPriority != 2 )
v31 = 1;
*(_QWORD *)v29->ClaimDistribution += VmSupport->AgeDistribution[0] >> v31;
*(_QWORD *)&v29->ClaimDistribution[2] += VmSupport->AgeDistribution[1] >> v31;
*(_QWORD *)&v29->ClaimDistribution[4] += VmSupport->AgeDistribution[2] >> v31;
*(_QWORD *)&v29->ClaimDistribution[6] += VmSupport->AgeDistribution[3] >> v31;
*(_QWORD *)&v29->PagesToTrim += VmSupport->AgeDistribution[4] >> v31;
*(_QWORD *)&v29->PagesTrimmed += VmSupport->AgeDistribution[5] >> v31;
*(_QWORD *)&v29[1]._bf_0 += VmSupport->AgeDistribution[6] >> v31;
*(_QWORD *)v29[1].ClaimDistribution += VmSupport->AgeDistribution[7] >> v31;
}
if( (v3 & 0x10) != 0 || (v3 & 8) != 0 )
{
v32 = v59;
MiCaptureAndResetWorkingSetAccessBits(VmSupport, v59);
}
else
{
v32 = v59;
}
TickCountQuad = KUSER_SHARED_DATA.TickCountQuad;
v33 = VmSupport->Flags._bf_0 & 7;
v62 = 0i64;
v34 = VmSupport + 1;
*(_OWORD *)v61 = 0i64;
if( v33 == 2 )
v35 = (_MMSUPPORT_INSTANCE *)((char *)&stru_140C4DB30 + 6544);
else
v35 = VmSupport + 1;
if( v35->AgeDistribution[0] )
{
v61[0] = 0i64;
if( v33 == 2 )
v34 = (_MMSUPPORT_INSTANCE *)((char *)&stru_140C4DB30 + 6544);
v36 = (volatile __int64 *)&v34->AgeDistribution[3];
v61[1] = (INT64)&v34->AgeDistribution[3];
v37 = KeGetCurrentPrcb();
if( v37->SchedulerAssist && v37->NestingLevel <= 1u && v37->NestingLevel == 1 )
v36 = (volatile __int64 *)&v34->AgeDistribution[3];
if( _InterlockedExchange64(v36, (__int64)v61) )
KxWaitForLockOwnerShip((INT64)v61);
v38 = (_MM_PAGE_ACCESS_INFO_HEADER *)v35->AgeDistribution[0];
if( v38 )
{
Next = v38->Link.Next;
for( i = (_SINGLE_LIST_ENTRY *)v35->AgeDistribution[0]; Next; Next = Next->Next )
i = Next;
if( TickCountQuad - (unsigned __int64)i[2].Next > PfKernelGlobals.AccessBufferAgeThreshold )
{
MiEmptyPageAccessLog(v38);
v35->AgeDistribution[0] = 0i64;
}
}
_m_prefetchw(v61);
v41 = (_KSPIN_LOCK_QUEUE *)v61[0];
if( !v61[0] )
{
if( (INT64 *)_InterlockedCompareExchange64((volatile signed __int64 *)v61[1], 0i64, (signed __int64)v61) == v61 )
goto LABEL_63;
v41 = KxWaitForLockChainValid((_KSPIN_LOCK_QUEUE *)v61);
}
v61[0] = 0i64;
_InterlockedXor64((volatile signed __int64 *)&v41->Lock, 1ui64);
}
}
LABEL_63:
if( (VmSupport->Flags._bf_0 & 7u) < 6 )
{
Flags = VmSupport->Flags;
if( (Flags.$2436257948A9E417F8C1432C685A007E::$56A022E0416FA8F0D143F219D5D8FA21::_bf_0 & 8) != 0
|| (Flags.$2436257948A9E417F8C1432C685A007E::$56A022E0416FA8F0D143F219D5D8FA21::_bf_0 & 4) != 0
|| (Flags.$2436257948A9E417F8C1432C685A007E::$56A022E0416FA8F0D143F219D5D8FA21::_bf_0 & 0x10) != 0 )
{
MiPreUnlockWorkingSetShared(VmSupport, v32);
Flags.$9F51E323906620A7CE080F79FB124AD0::$3F85127412E45D453B47E0230FB8DC78::_bf_0 = VmSupport->Flags._bf_0;
}
if( (Flags.$9F51E323906620A7CE080F79FB124AD0::$3F85127412E45D453B47E0230FB8DC78::_bf_0 & 7) != 2 )
v21 = VmSupport + 1;
MiCheckProcessShadow();
_InterlockedAnd((volatile signed __int32 *)v21, 0xBFFFFFFF);
_InterlockedDecrement((volatile signed __int32 *)v21);
}
__writecr8(v32);
v43 = VmSupport->Flags._bf_0 & 7;
if( v43 )
{
if( v43 == 1 )
MiDetachProcessFromSession(1ui64);
}
else if( (unsigned __int64 *)KeGetCurrentThread()->Process != &VmSupport[-9].AgeDistribution[3] )
{
KiDetachProcess(&KeGetCurrentThread()->SavedApcState, 1ui64);
}
if( !v28 )
{
if( *(&stru_140C4DB30 + 322) )
{
v44 = (_MM_PAGE_ACCESS_INFO_HEADER *)_InterlockedExchange64((_QWORD *)&stru_140C4DB30 + 322, 0i64);
if( v44 )
{
if( TickCountQuad - v44->CreateTime > PfKernelGlobals.AccessBufferAgeThreshold || (v3 & 0x18) != 0 )
{
v48 = v44;
}
else
{
if( !*(&stru_140C4DB30 + 322)
&& !_InterlockedCompareExchange64((_QWORD *)&stru_140C4DB30 + 322, (signed __int64)v44, 0i64) )
{
return;
}
v48 = v44;
if( (_MM_PAGE_ACCESS_INFO_HEADER *)v44->PageEntry == &v44[1] )
{
MmFreeAccessPfnBuffer(v44, 1u);
return;
}
}
MiQueuePageAccessLog(v48);
}
}
}
}Referenced by:
MiProcessWorkingSets