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