PpmIdlePrepare
UINT64 __stdcall PpmIdlePrepare(
_KPRCB *Prcb,
UINT8 *DeepSleepEnabled,
UINT64 *EnterTime,
UINT64 *InterruptTime,
UINT64 *GlobalHintFloor,
_KAFFINITY_EX *WakeMask){
int v6;
__int64 v7;
_KPRCB *v8;
_PPM_IDLE_STATES *IdleStates;
_PPM_IDLE_STATES *v11;
unsigned __int64 TimeUpdateLock;
unsigned __int64 BaselineInterruptTimeQpc;
__int64 v14;
UINT64 PerformanceCounter;
UINT64 v16;
__int64 v17;
unsigned __int64 v18;
UINT64 *v19;
UINT64 v20;
int OverrideIndex;
unsigned __int8 v22;
UINT64 v23;
unsigned __int8 ClockOwner;
_PPM_IDLE_STATES *v25;
unsigned __int64 v26;
unsigned __int64 v27;
_PPM_IDLE_STATES *v28;
char v29;
unsigned __int8 PlatformIdle;
unsigned __int64 v31;
int v32;
unsigned __int64 v33;
UINT64 v34;
unsigned __int64 v35;
unsigned int InterruptRate;
unsigned int v37;
unsigned int i;
unsigned int v39;
__int64 v40;
__int64 v41;
unsigned int v42;
_PROC_IDLE_ACCOUNTING *IdleAccounting;
bool v44;
int v45;
char v46;
unsigned int *v47;
UINT8 v48;
struct _KPRCB *CurrentPrcb;
_KNODE *ParentNode;
unsigned int v52;
NTSTATUS NextNode;
signed __int64 v55;
unsigned __int64 v56;
int v57;
_KPRCB *v58;
unsigned __int64 IdleTimeExpiration;
_KAFFINITY_EX *v60;
__int64 v61;
char v62;
unsigned __int64 ExpectedIdleDuration;
__int64 v64;
UINT64 *NextDueTime;
int DeepSleepEnableda;
UINT64 InterruptTimea;
UINT64 ProcIndex;
_PPM_IDLE_STATES *v69;
_KEXPECTED_WAKE_REASON ExpectedWakeReason[2];
UINT64 LookupIndex;
_PROCESSOR_IDLE_PREPARE_INFO *p_PrepareInfo;
unsigned __int64 v73;
_KPRCB *Prcba;
__int64 v75;
UINT64 *v76;
UINT64 *v77;
_KAFFINITY_EX *Affinity;
__int64 v79;
UINT8 *v80;
UINT64 *v81;
_KAFFINITY_ENUMERATION_CONTEXT Context;
_KAFFINITY_EX IdleConstrainedMask;
v7 = 0i64;
v8 = Prcb;
v81 = GlobalHintFloor;
LOBYTE(v6) = 0;
Affinity = WakeMask;
Prcba = Prcb;
IdleStates = Prcb->PowerState.IdleStates;
HIDWORD(LookupIndex) = PpmDripsStateIndex;
v76 = InterruptTime;
v77 = EnterTime;
v80 = DeepSleepEnabled;
p_PrepareInfo = &IdleStates->PrepareInfo;
HIDWORD(ProcIndex) = 0;
DeepSleepEnableda = v6;
v69 = IdleStates;
v79 = PpmPlatformStates;
v73 = 0i64;
if( v8->ClockOwner )
{
if( *(&PopIrpWorkerControlEvent + 192) && *(&PopIrpWorkerControlEvent + 193) && !*(&PopIrpWorkerControlEvent + 144) )
{
if( PpmPlatformStates )
LODWORD(v17) = 1;
else
LODWORD(v17) = IdleStates->ProcessorIdleCount > 1;
goto LABEL_81;
}
}
while( 1 )
{
v11 = v8->PowerState.IdleStates;
while( 1 )
{
TimeUpdateLock = KUSER_SHARED_DATA.TimeUpdateLock;
if( (KUSER_SHARED_DATA.TimeUpdateLock & 1) == 0 )
{
BaselineInterruptTimeQpc = KUSER_SHARED_DATA.BaselineInterruptTimeQpc;
v14 = *(_QWORD *)&KUSER_SHARED_DATA.InterruptTime.LowPart;
PerformanceCounter = KeQueryPerformanceCounter(0i64);
if( KUSER_SHARED_DATA.TimeUpdateLock == TimeUpdateLock )
break;
}
_mm_pause();
}
v8 = Prcba;
v16 = PerformanceCounter;
LODWORD(v17) = DeepSleepEnableda;
if( PerformanceCounter > BaselineInterruptTimeQpc )
{
v75 = 0i64;
v18 = -1i64 - BaselineInterruptTimeQpc + PerformanceCounter;
if( KUSER_SHARED_DATA.QpcInterruptTimeIncrementShift )
v18 <<= KUSER_SHARED_DATA.QpcInterruptTimeIncrementShift;
v7 = (v18 * (unsigned __int128)KUSER_SHARED_DATA.QpcInterruptTimeIncrement) >> 64;
v75 = v7;
}
v19 = v76;
v20 = v7 + v14;
v7 = 0i64;
*v76 = v20;
v11->PrepareInfo.Constraints.TotalTime = v16;
v11->PrepareInfo.Constraints.IdleTime = v8->PowerState.IdleTimeTotal + v8->PowerState.PerfFeedback.StallTime;
v11->PrepareInfo.Constraints.Parked = v8->PowerState.Parked;
v11->PrepareInfo.Constraints.PromotePercent = v8->PowerState.IdlePolicy.PromotePercent;
v11->PrepareInfo.Constraints.DemotePercent = v8->PowerState.IdlePolicy.DemotePercent;
v11->PrepareInfo.Constraints.Interruptible = 1;
if( v8->ClockOwner
&& (CurrentPrcb = KeGetCurrentPrcb(),
LODWORD(LookupIndex) = 0,
ParentNode = CurrentPrcb->ParentNode,
v52 = ParentNode->Affinity.Reserved[0],
(ParentNode->DeepIdleSet & ~(1i64 << CurrentPrcb->GroupIndex)) == (ParentNode->Affinity.Mask & ~(1i64 << (KiProcessorIndexToNumberMappingTable[CurrentPrcb->Number] & 0x3F)))) )
{
while( 1 )
{
NextNode = MmGetNextNode(v52, &LookupIndex);
if( NextNode == -1 )
break;
if( *(_QWORD *)(KeNodeBlock[NextNode] + 64) != *(_QWORD *)(KeNodeBlock[NextNode] + 136) )
goto LABEL_12;
}
v11->PrepareInfo.Constraints.PlatformIdle = 1;
v11->ReasonFlags |= 0x80u;
}
else
{
LABEL_12:
v11->PrepareInfo.Constraints.PlatformIdle = 0;
}
if( v11->IdleOverride )
{
v11->ReasonFlags |= 0x100u;
OverrideIndex = v11->OverrideIndex;
}
else
{
OverrideIndex = -1;
}
v11->PrepareInfo.Constraints.OverrideState = OverrideIndex;
if( PpmIdleRespectIdleStateMax )
{
v22 = *(_BYTE *)(2736i64 * *(&stru_140C23628 + 441) + *(&stru_140C00F40 + 365) + 198);
v11->PrepareInfo.Constraints.IdleStateMax = v22;
if( v22 )
v11->ReasonFlags |= 0x4000u;
}
else
{
v11->PrepareInfo.Constraints.IdleStateMax = 0;
}
*v77 = v16;
if( (_BYTE)DeepSleepEnableda && !v69->PrepareInfo.Constraints.PlatformIdle )
{
v69->ReasonFlags = 0;
LOBYTE(v17) = 0;
goto LABEL_81;
}
v23 = *v19;
ClockOwner = v8->ClockOwner;
v25 = v8->PowerState.IdleStates;
InterruptTimea = v23;
if( ClockOwner || !KiSerializeTimerExpiration )
{
v26 = 0i64;
v28 = v8->PowerState.IdleStates;
}
else
{
v26 = 0i64;
_m_prefetchw((char *)&stru_140CF2E80 + 5032);
v27 = *(&stru_140CF2E80 + 629);
if( *(&stru_140CF2E80 + 2516) )
{
while( 1 )
{
v55 = _InterlockedCompareExchange64(
(_QWORD *)&stru_140CF2E80 + 629,
v27 ^ (unsigned __int16)(v27 ^ (v27 - 1)),
v27);
if( v27 == v55 )
break;
v27 = v55;
_mm_pause();
if( !(_WORD)v55 )
goto LABEL_22;
}
v26 = v27 >> 16;
}
LABEL_22:
v28 = v8->PowerState.IdleStates;
ClockOwner = v8->ClockOwner;
}
memset(&Context, 0, sizeof(Context));
memset(&IdleConstrainedMask, 0i64, sizeof(IdleConstrainedMask));
v29 = DeepSleepEnableda;
PlatformIdle = v28->PrepareInfo.Constraints.PlatformIdle;
v31 = -1i64;
LODWORD(ProcIndex) = 0;
v32 = ClockOwner != 0 ? 8 : 0;
if( (_BYTE)DeepSleepEnableda )
LOWORD(v32) = v32 | 4;
v33 = KiClockTimerNextTickTime;
*(_QWORD *)ExpectedWakeReason = 0i64;
if( v8->ClockOwner )
{
if( !PlatformIdle || (_BYTE)KiDynamicTickDisableReason || KiClockState )
{
v34 = InterruptTimea;
}
else
{
LOBYTE(NextDueTime) = 0;
KiGetNextTimerExpirationDueTime(v8, 1u, InterruptTimea, DeepSleepEnableda, NextDueTime, ExpectedWakeReason);
v34 = InterruptTimea;
v29 = DeepSleepEnableda;
if( InterruptTimea + (unsigned int)KiLastRequestedTimeIncrement < *(_QWORD *)ExpectedWakeReason )
v33 = *(_QWORD *)ExpectedWakeReason;
}
}
else
{
LOBYTE(NextDueTime) = 0;
KiGetNextTimerExpirationDueTime(v8, 0, InterruptTimea, DeepSleepEnableda, NextDueTime, ExpectedWakeReason);
v34 = InterruptTimea;
v29 = DeepSleepEnableda;
if( v33 <= *(_QWORD *)ExpectedWakeReason )
v33 = *(_QWORD *)ExpectedWakeReason;
}
if( v33 == -1i64 )
{
v35 = -1i64;
}
else
{
v35 = 0i64;
if( v33 > v34 )
v35 = v33 - v34;
}
InterruptRate = v8->InterruptRate;
v37 = 0;
for( i = InterruptRate; i; i >>= 4 )
v37 += KeMaximumIncrement;
if( !v29 && InterruptRate )
{
v39 = (unsigned int)KeMaximumIncrement / (InterruptRate + 1);
if( !v39 )
v39 = 1;
v31 = v39;
}
if( v35 <= v31 )
{
v31 = v35;
}
else
{
LOWORD(v32) = v32 | 1;
if( v35 >= v37 )
v35 = v37;
}
if( PpmIdleDurationExpirationTimeout && v8->ClockOwner && PpmGetIdleConstrainedMask(&IdleConstrainedMask) )
{
v56 = 0i64;
Context.CurrentMask = IdleConstrainedMask.Bitmap[0];
Context.Affinity = &IdleConstrainedMask;
while( 1 )
{
KeEnumerateNextProcessor(&ProcIndex, &Context);
if( v57 )
break;
v58 = KeGetPrcb((unsigned int)ProcIndex);
IdleTimeExpiration = v58->PowerState.IdleTimeExpiration;
if( IdleTimeExpiration != -1i64 && IdleTimeExpiration > v56 )
v56 = v58->PowerState.IdleTimeExpiration;
}
if( v56 && v35 + InterruptTimea > v56 )
{
LOWORD(v32) = v32 | 0x2000;
v35 = v56 > InterruptTimea ? (unsigned int)(v56 - InterruptTimea) : 1i64;
if( v35 < v31 )
v31 = v35;
}
}
if( v31 < v26 )
{
v31 = v26;
v35 = v26;
LOWORD(v32) = v32 | 0x1000;
}
v25->ReasonFlags |= v32;
v40 = (__int64)p_PrepareInfo;
v25->PrepareInfo.Constraints.ExpectedWakeReason = 2;
v41 = (__int64)v69;
v25->PrepareInfo.Constraints.MaxIdleDuration = v35;
v25->PrepareInfo.Constraints.ExpectedIdleDuration = v31;
(*(void(__fastcall **)(__int64))(v41 + 408))(v40);
v42 = *(_DWORD *)(v40 + 76);
v17 = *(unsigned int *)(v40 + 72);
if( v42 == -2 || v42 == -1 )
break;
IdleAccounting = v8->PowerState.IdleAccounting;
v44 = !_BitScanForward((unsigned int *)&v45, *(_DWORD *)(v40 + 80));
HIDWORD(ProcIndex) = v45;
if( !v44 )
{
do
{
*(_DWORD *)(v40 + 80) &= *(_DWORD *)(v40 + 80) - 1;
++IdleAccounting->State[v45].FailureCount;
v44 = !_BitScanForward((unsigned int *)&v45, *(_DWORD *)(v40 + 80));
}
while( !v44 );
HIDWORD(ProcIndex) = v45;
}
v46 = 0;
v47 = *(unsigned int **)(v40 + 64);
if( *(_DWORD *)(v40 + 60) )
{
v60 = Affinity;
v61 = *(unsigned int *)(v40 + 60);
do
{
if( *((_BYTE *)v47 + 4) == 0xFF )
{
v62 = v46;
if( !v46 )
v62 = 1;
v46 = v62;
KeAddProcessorAffinityEx(&v60->Count, *v47);
}
v47 += 2;
--v61;
}
while( v61 );
v8 = Prcba;
v40 = (__int64)p_PrepareInfo;
if( v46 && p_PrepareInfo->Constraints.PlatformIdle )
{
ExpectedIdleDuration = v73;
if( v73 < p_PrepareInfo->Constraints.ExpectedIdleDuration )
ExpectedIdleDuration = p_PrepareInfo->Constraints.ExpectedIdleDuration;
v73 = ExpectedIdleDuration;
}
}
v48 = DeepSleepEnableda;
if( !(_BYTE)DeepSleepEnableda )
goto LABEL_48;
v64 = v79;
if( v79 )
{
if( (_DWORD)v17 != -1 && (unsigned int)v17 >= HIDWORD(LookupIndex) )
goto LABEL_48;
}
else if( v42 == v69->ProcessorIdleCount - 1 )
{
goto LABEL_48;
}
v69->IdleCancel(*(void **)v40, 0);
++IdleAccounting->State[v42].CancelCount;
if( (_DWORD)v17 != -1 && v64 )
++*(_DWORD *)(1008 * v17 + *(_QWORD *)(v64 + 48) + 24);
LOBYTE(v17) = 0;
v7 = 0i64;
v69->ReasonFlags = 2;
LABEL_81:
DeepSleepEnableda = v17;
}
v48 = 0;
LABEL_48:
*v80 = v48;
*v81 = v73;
return v42;
}Referenced by:
PoIdle