KiSwapThread

VOID __fastcall KiSwapThread(_ETHREAD *OldThread, _KPRCB *CurrentPrcb){
  void *volatile *v2; 
  unsigned __int64 v5; 
  unsigned __int64 v6; 
  unsigned __int64 v7; 
  unsigned __int64 v8; 
  _THREAD_ENERGY_VALUES *EnergyValues; 
  _PROC_PERF_DOMAIN *Domain; 
  _PROC_PERF_CONSTRAINT *Constraint; 
  unsigned int LatestFrequencyPercent; 
  unsigned int v13; 
  __int64 ArchitecturalEfficiencyClass; 
  __int64 v15; 
  __int64 v16; 
  unsigned __int64 v17; 
  unsigned __int64 *v18; 
  unsigned int v19; 
  unsigned int EndTime; 
  unsigned int v21; 
  unsigned int v22; 
  struct _KPRCB *v23; 
  _KSCHEDULING_GROUP *volatile v24; 
  _KSCHEDULING_GROUP *v25; 
  _ETHREAD *NextThread; 
  _RTL_BALANCED_NODE *Min; 
  unsigned __int64 v28; 
  int v29; 
  _KNODE *ParentNode; 
  int v31; 
  int IdleState; 
  _BYTE *v33; 
  int v34; 
  unsigned __int64 v35; 
  _ETHREAD *IdleThread; 
  char Priority; 
  int v39; 
  _KNODE *v40; 
  unsigned __int64 v41; 
  unsigned __int8 GroupIndex; 
  int Group; 
  unsigned __int64 Mask; 
  unsigned __int64 SharedReadyQueueMask; 
  unsigned __int64 v46; 
  unsigned __int64 v47; 
  struct _KPRCB *v48; 
  char v49; 
  unsigned __int64 WaitIrql; 
  char v51; 
  bool v52; 
  bool v53; 
  unsigned __int64 v54; 
  int v55; 
  unsigned __int64 v56; 
  __int64 v57; 
  __int64 v58; 
  unsigned __int64 v59; 
  int v60; 
  unsigned __int64 v61; 
  int v62; 
  unsigned __int64 v63; 
  __int64 v64; 
  char v65; 
  _BYTE *v66; 
  unsigned __int64 v67; 
  _KSCHEDULING_GROUP *volatile SchedulingGroup; 
  _QWORD *i; 
  char v70; 
  unsigned int v71; 
  _KSCB *v72; 
  int v73; 
  _DWORD *v74; 
  UINT8 v75; 
  unsigned __int64 v76; 
  _DWORD *v77; 
  UINT8 v78; 
  struct _KPRCB *v79; 
  UINT8 v80; 
  _BYTE *SchedulerAssist; 
  unsigned __int64 v82; 
  unsigned __int64 GroupSetMember; 
  unsigned __int64 CoreProcessorSet; 
  unsigned __int64 v85; 
  unsigned __int64 v86; 
  __int64 v87; 
  __int64 v88; 
  _DWORD *v89; 
  int v90; 
  UINT8 IsThreadRankNonZero; 
  INT64 v92; 
  INT64 v93; 
  int v94; 
  struct _KPRCB *v95; 
  _DWORD *v96; 
  int v97; 
  INT64 v98; 
  INT64 v99; 
  PVOID v100; 
  int v101; 
  int v102; 
  int v103; 
  unsigned __int64 v104; 
  UINT64 v105; 
  UINT64 v106; 
  UINT64 SpinCount; 
  UINT64 v108; 
  _KSCHEDULING_GROUP *volatile v109; 
  _SINGLE_LIST_ENTRY ReadyList; 
  unsigned __int8 v111; 
  _TIMELINE_BITMAP v112; 
  void *volatile *v113; 
  int v114; 

  v113 = v2;
  if( CurrentPrcb->DeferredReadyListHead.Next )
    KiProcessThreadWaitList(CurrentPrcb, AdjustUnwait, 0i64, 2ui64);
  KiAbProcessContextSwitch(&OldThread->Tcb, 0i64);
  _disable();
  CurrentPrcb->NestingLevel = 1;
  v5 = __rdtsc();
  v6 = v5 - CurrentPrcb->StartCycles;
  v7 = v6 + OldThread->Tcb.CurrentRunTime;
  OldThread->Tcb.CycleTime += v6;
  if( v7 > 0xFFFFFFFF )
    LODWORD(v7) = -1;
  CurrentPrcb->StartCycles = v5;
  v8 = (unsigned __int8)OldThread->Tcb.gap0[2];
  OldThread->Tcb.CurrentRunTime = v7;
  if( (v8 & 0x3E) != 0 )
  {
    if( (v8 & 0x10) != 0 )
    {
      CurrentPrcb->TaggedCycles[OldThread->Tcb.Tag] += CurrentPrcb->StartCycles - CurrentPrcb->TaggedCyclesStart;
      LOBYTE(v8) = v8 & 0xEF;
      CurrentPrcb->TaggedCyclesStart = 0i64;
    }
    if( (v8 & 0x20) != 0 )
    {
      EnergyValues = OldThread->EnergyValues;
      if( EnergyValues )
      {
        Domain = CurrentPrcb->PowerState.CheckContext.Domain;
        Constraint = CurrentPrcb->PowerState.CheckContext.Constraint;
        if( Domain && Constraint )
        {
          if( Constraint->Selection.Autonomous )
          {
            LatestFrequencyPercent = Constraint->LatestFrequencyPercent;
          }
          else
          {
            LatestFrequencyPercent = Constraint->Selection.SelectedPercent;
            if( LatestFrequencyPercent >= Domain->GuaranteedPercent )
              LatestFrequencyPercent = Domain->GuaranteedPercent;
          }
        }
        else
        {
          LatestFrequencyPercent = 100;
        }
        if( LatestFrequencyPercent < 0x4B )
          v13 = LatestFrequencyPercent / 0x19;
        else
          v13 = 3;
        ArchitecturalEfficiencyClass = CurrentPrcb->PowerState.ArchitecturalEfficiencyClass;
        v15 = v13;
        v16 = ArchitecturalEfficiencyClass + 2i64 * v13;
        v17 = EnergyValues->Cycles[0][v16];
        v18 = (unsigned __int64 *)((char *)EnergyValues + 8 * v16);
        v19 = KiTimelineBitmapTime;
        *v18 = v6 + v17;
        EndTime = EnergyValues->CpuTimeline.EndTime;
        if( v19 > EndTime )
        {
          v112.EndTime = v19;
          if( v19 - EndTime >= 0x20 )
            v112.Bitmap = 1;
          else
            v112.Bitmap = (EnergyValues->CpuTimeline.Bitmap << (v19 - EndTime)) | 1;
          EnergyValues->CpuTimeline = v112;
        }
        else
        {
          v21 = EndTime - v19;
          if( v21 < 0x20 )
            EnergyValues->CpuTimeline.Bitmap |= 1 << v21;
        }
        if( !KiEfficiencyClassSystem && (unsigned __int8)OldThread->Tcb.ThreadFlags2 == 2 )
          EnergyValues->Cycles[v15][1] += v6;
        if( OldThread->WorkOnBehalfThread )
        {
          EnergyValues->WorkOnBehalfCycles[v15][ArchitecturalEfficiencyClass] += v6;
          _InterlockedExchangeAdd64(
            (volatile signed __int64 *)(*((_QWORD *)OldThread->WorkOnBehalfThread + 191)
                                      + 8 * (ArchitecturalEfficiencyClass + 8 + 2 * v15)),
            v6);
        }
      }
      LOBYTE(v8) = v8 & 0xDF;
    }
    if( (v8 & 0x40) != 0 )
    {
      SchedulerAssist = OldThread->Tcb.SchedulerAssist;
      if( SchedulerAssist )
        SchedulerAssist[64] = 0;
      LOBYTE(v8) = v8 & 0xBF;
    }
    if( (v8 & 0x3E) != 0 )
    {
      SchedulingGroup = OldThread->Tcb.SchedulingGroup;
      if( SchedulingGroup )
      {
        for( i = (_QWORD *)((char *)&SchedulingGroup->Policy + CurrentPrcb->ScbOffset); i; i = (_QWORD *)i[51] )
          *i += v6;
      }
      if( (OldThread->Tcb.gap0[2] & 8) != 0
        && (OldThread->Tcb.Affinity.Mask & CurrentPrcb->ParentNode->Affinity.Mask) != CurrentPrcb->ParentNode->Affinity.Mask )
      {
        CurrentPrcb->AffinitizedCycles += v6;
      }
      if( OldThread->Tcb.SystemHeteroCpuPolicy )
      {
        if( (unsigned __int8)OldThread->Tcb.ThreadFlags2 == 2 )
          CurrentPrcb->UnimportantCycles += v6;
        else
          CurrentPrcb->ImportantCycles += v6;
      }
      if( OldThread->Tcb.WaitBlock[0].SparePtr )
        KiEndCounterAccumulation(&OldThread->Tcb);
    }
  }
  _enable();
  v22 = (OldThread->Tcb.CurrentRunTime >> 1) + (OldThread->Tcb.ExpectedRunTime >> 1);
  OldThread->Tcb.CurrentRunTime = 0;
  OldThread->Tcb.ExpectedRunTime = v22;
  v23 = KeGetCurrentPrcb();
  LODWORD(v105) = 0;
  while( _interlockedbittestandset64((volatile signed __int32 *)&CurrentPrcb->PrcbLock, 0i64) )
  {
    do
      KeYieldProcessorEx(&v105);
    while( CurrentPrcb->PrcbLock );
    v77 = v23->SchedulerAssist;
    if( v77 && v23->NestingLevel <= 1u )
      ++v77[6];
  }
  v24 = OldThread->Tcb.SchedulingGroup;
  v109 = v24;
  v25 = v24;
  if( v24 )
  {
    v72 = (_KSCB *)((char *)v24 + CurrentPrcb->ScbOffset);
    if( v72 )
    {
      v73 = 0;
      while( 1 )
      {
        if( (*((_BYTE *)v72 + 112) & 4) != 0 )
        {
          if( KiCheckMaxOverQuotaTransition(v72, v25) )
          {
            if( (*((_BYTE *)v72 + 112) & 1) != 0 )
              KiRemoveSchedulingGroupQueue(CurrentPrcb, v72, 1u);
          }
          else if( v72->GenerationCycles >= v72->RankCycleTarget && (*((_BYTE *)v72 + 112) & 2) == 0 )
          {
            KiRecomputeGroupSchedulingRank(v25, v72, CurrentPrcb);
          }
        }
        else
        {
          KiComputeGroupSchedulingRank(v25, CurrentPrcb, v72);
        }
        v73 += v72->Rank;
        v72 = v72->Parent;
        if( !v72 )
          break;
        v25 = (_KSCHEDULING_GROUP *)((char *)v72 - CurrentPrcb->ScbOffset);
        v109 = v25;
      }
    }
  }
  NextThread = CurrentPrcb->NextThread;
  if( NextThread )
  {
LABEL_126:
    CurrentPrcb->NextThread = 0i64;
    CurrentPrcb->CurrentThread = NextThread;
    if( NextThread->Tcb.WaitBlockFill6[68] == 1 )
      goto LABEL_133;
    goto LABEL_127;
  }
  while( 1 )
  {
    NextThread = (_ETHREAD *)KiSelectReadyThread(1i64, CurrentPrcb);
    if( NextThread )
      goto LABEL_128;
    HIDWORD(v105) = 0;
    if( !KiPerfIsoEnabled
      || (v82 = CurrentPrcb->ParentNode->IdleNonParkedCpuSet
              - ((CurrentPrcb->ParentNode->IdleNonParkedCpuSet >> 1) & 0x5555555555555555i64),
          (unsigned int)((0x101010101010101i64
                        * (((v82 & 0x3333333333333333i64)
                          + ((v82 >> 2) & 0x3333333333333333i64)
                          + (((v82 & 0x3333333333333333i64) + ((v82 >> 2) & 0x3333333333333333i64)) >> 4)) & 0xF0F0F0F0F0F0F0Fi64)) >> 32) >> 24 >= KiPerfIsoEnabled)
      && ((GroupSetMember = CurrentPrcb->GroupSetMember,
           CoreProcessorSet = CurrentPrcb->CoreProcessorSet,
           GroupSetMember == CoreProcessorSet)
       || (v85 = CoreProcessorSet & ~GroupSetMember, (CurrentPrcb->ParentNode->IdleCpuSet & v85) != 0)
       || (_BitScanForward64(&v86, v85),
           v87 = (unsigned int)KiProcessorNumberToIndexMappingTable[64 * CurrentPrcb->Group + (int)v86],
           HIDWORD(v105) = v87,
           ((*(&KiProcessorBlock + v87))->PrcbFlags._bf_0 & 0x400) != 0)) )
    {
      NextThread = 0i64;
      Min = CurrentPrcb->ScbQueue.Min;
      if( ((unsigned __int8)Min & 1) == 0 )
      {
        v28 = (unsigned __int64)CurrentPrcb->ScbQueue.Min;
        goto LABEL_36;
      }
      if( Min != (_RTL_BALANCED_NODE *)1 )
      {
        v28 = (unsigned __int64)Min ^ ((unsigned __int64)&CurrentPrcb->ScbQueue | 1);
LABEL_36:
        while( v28 )
        {
          v76 = v28 - 88;
          NextThread = KiSelectThreadFromSchedulingGroup(CurrentPrcb, (_KSCB *)(v28 - 88), 0i64);
          if( NextThread )
            break;
          v88 = *(_QWORD *)(v76 + 400);
          if( (v88 & 1) != 0 )
          {
            if( v88 == 1 )
              goto LABEL_38;
            v28 = v88 ^ ((v76 + 392) | 1);
          }
          else
          {
            v28 = *(_QWORD *)(v76 + 400);
          }
        }
        if( NextThread )
          goto LABEL_128;
      }
    }
LABEL_38:
    NextThread = (_ETHREAD *)KiSelectReadyThread(0i64, CurrentPrcb);
    if( !NextThread )
    {
      v29 = 0;
      ParentNode = CurrentPrcb->ParentNode;
      v31 = 1;
      IdleState = CurrentPrcb->IdleState;
      v33 = CurrentPrcb->SchedulerAssist;
      if( CurrentPrcb->IdleState == 7 )
        v29 = 1;
      if( v33 )
        v33[16] = 1;
      CurrentPrcb->IdleSchedule = 0;
      if( (IdleState & 1) != 0 )
      {
        v34 = IdleState - 1;
        CurrentPrcb->IdleState = v34;
        if( !v34 )
          _interlockedbittestandset64((volatile signed __int32 *)ParentNode, CurrentPrcb->GroupIndex);
        _interlockedbittestandset64((volatile signed __int32 *)&ParentNode->IdleCpuSet, CurrentPrcb->GroupIndex);
        v35 = CurrentPrcb->CoreProcessorSet;
        if( (v35 & ParentNode->IdleCpuSet) == v35 )
        {
          _InterlockedOr64((volatile signed __int64 *)&ParentNode->IdleSmtSet, v35);
        }
        else
        {
          v67 = CurrentPrcb->CoreProcessorSet & ~ParentNode->IdleCpuSet;
          if( ((v67 - 1) & v67) == 0 )
            _InterlockedOr64((volatile signed __int64 *)&ParentNode->NonPairedSmtSet, v67);
        }
        _interlockedbittestandreset64((volatile signed __int32 *)&ParentNode->NonPairedSmtSet, CurrentPrcb->GroupIndex);
      }
      IdleThread = CurrentPrcb->IdleThread;
      if( (IdleThread->Tcb.gap0[2] & 4) != 0 )
      {
        IsThreadRankNonZero = KiIsThreadRankNonZero(&CurrentPrcb->IdleThread->Tcb, CurrentPrcb, (_KPRCB *)v8);
        Priority = 1;
        if( !IsThreadRankNonZero )
          Priority = IdleThread->Tcb.Priority;
        v31 = 1;
      }
      else
      {
        Priority = IdleThread->Tcb.Priority;
      }
      *CurrentPrcb->PriorityState = Priority;
      if( CurrentPrcb->SchedulerAssist )
      {
        v92 = (unsigned int)KiVpThreadSystemWorkPriority;
        if( IdleThread != CurrentPrcb->IdleThread )
          v92 = (unsigned int)Priority;
        KiSetSchedulerAssistPriority((INT32 *)CurrentPrcb->SchedulerAssist, v92, 0);
      }
      v39 = 0;
      if( (CurrentPrcb->IdleState & 2) != 0 )
        v39 = v31;
      _InterlockedAnd64((volatile signed __int64 *)&CurrentPrcb->PrcbLock, 0i64);
      if( !v39 || v29 )
      {
        v40 = CurrentPrcb->ParentNode;
        v103 = 0;
        LODWORD(v41) = v40->SiblingMask;
        HIDWORD(v106) = v40->Affinity.Reserved[0];
LABEL_56:
        GroupIndex = CurrentPrcb->GroupIndex;
        Group = CurrentPrcb->Group;
        Mask = v40->Affinity.Mask;
        SharedReadyQueueMask = v40->SharedReadyQueueMask;
        v46 = Mask;
        v111 = GroupIndex;
        v114 = Group;
        v104 = SharedReadyQueueMask;
        if( v40 == CurrentPrcb->ParentNode )
        {
          SharedReadyQueueMask ^= CurrentPrcb->SharedReadyQueueMask;
          Mask ^= CurrentPrcb->GroupSetMember;
          v104 = SharedReadyQueueMask;
          if( (KiCacheAwareScheduling & 2) != 0 )
            v46 &= CurrentPrcb->LLCMask;
        }
        v47 = ~v40->IdleCpuSet & Mask;
        while( 1 )
        {
          if( !v47 && !SharedReadyQueueMask )
          {
            v41 = (unsigned int)v41 & (unsigned __int64)~(1i64 << v40->Affinity.Reserved[0]);
            if( (_DWORD)v41 )
            {
              v8 = (unsigned __int16)KeNumberNodes;
              while( 1 )
              {
                v62 = v103 + 1;
                v103 = v62;
                if( v62 == (unsigned __int16)KeNumberNodes )
                  break;
                v63 = *(unsigned int *)(*(&stru_140C4DB30 + 21)
                                      + 4i64 * ((unsigned int)(unsigned __int16)KeNumberNodes * HIDWORD(v106) + v62));
                if( (_DWORD)v63 == -1 )
                  break;
                v64 = (unsigned int)v41;
                if( _bittest64(&v64, v63) )
                {
                  v40 = (_KNODE *)KeNodeBlock[v63];
                  goto LABEL_56;
                }
              }
            }
            goto LABEL_63;
          }
          if( (SharedReadyQueueMask & v46) != 0 )
            break;
LABEL_89:
          if( (v47 & v46) != 0 )
          {
            v59 = __ROR8__(v47 & v46, GroupIndex);
            v60 = Group << 6;
            v102 = v60;
            do
            {
              _BitScanForward64(&v61, v59);
              v59 ^= 1i64 << v61;
              NextThread = (_ETHREAD *)KiSearchForNewThreadOnProcessor(
                                         CurrentPrcb,
                                         *(&KiProcessorBlock
                                         + (unsigned int)KiProcessorNumberToIndexMappingTable[v60
                                                                                            + (((_BYTE)v61 + GroupIndex) & 0x3F)]),
                                         0i64);
              if( NextThread )
                goto LABEL_73;
              v60 = v102;
              GroupIndex = v111;
            }
            while( v59 );
          }
          SharedReadyQueueMask = v104;
          GroupIndex = v111;
          v47 &= ~v46;
          v46 = v40->Affinity.Mask;
          Group = v114;
        }
        v54 = __ROR8__(SharedReadyQueueMask & v46, GroupIndex);
        v55 = Group << 6;
        v101 = v55;
        while( 1 )
        {
          _BitScanForward64(&v56, v54);
          v57 = (__int64)*(&KiProcessorBlock
                         + (unsigned int)KiProcessorNumberToIndexMappingTable[v55 + ((GroupIndex + (_BYTE)v56) & 0x3F)]);
          v58 = *(_QWORD *)(v57 + 33856);
          v104 = ~v58 & SharedReadyQueueMask;
          v54 &= __ROR8__(~v58, GroupIndex);
          NextThread = (_ETHREAD *)KiSearchForNewThreadOnProcessor(
                                     CurrentPrcb,
                                     0i64,
                                     *(_KSHARED_READY_QUEUE **)(v57 + 33864));
          if( NextThread )
            goto LABEL_73;
          SharedReadyQueueMask = v104;
          v55 = v101;
          GroupIndex = v111;
          if( !v54 )
          {
            Group = v114;
            goto LABEL_89;
          }
        }
      }
LABEL_63:
      v48 = KeGetCurrentPrcb();
      LODWORD(SpinCount) = 0;
      while( _interlockedbittestandset64((volatile signed __int32 *)&CurrentPrcb->PrcbLock, 0i64) )
      {
        do
          KeYieldProcessorEx(&SpinCount);
        while( CurrentPrcb->PrcbLock );
        v74 = v48->SchedulerAssist;
        if( v74 && v48->NestingLevel <= 1u )
        {
          v94 = v74[6] + 1;
          v74[6] = v94;
        }
      }
      NextThread = CurrentPrcb->NextThread;
      if( !NextThread )
      {
        NextThread = CurrentPrcb->IdleThread;
        if( !KeHeteroSystem || KeHeteroSystemVirtual )
          goto LABEL_67;
        _InterlockedAnd64((volatile signed __int64 *)&CurrentPrcb->PrcbLock, 0i64);
        KiSendHeteroRescheduleIntRequest(CurrentPrcb);
        v95 = KeGetCurrentPrcb();
        HIDWORD(SpinCount) = 0;
        while( _interlockedbittestandset64((volatile signed __int32 *)&CurrentPrcb->PrcbLock, 0i64) )
        {
          do
            KeYieldProcessorEx((UINT64 *)((char *)&SpinCount + 4));
          while( CurrentPrcb->PrcbLock );
          v96 = v95->SchedulerAssist;
          if( v96 && v95->NestingLevel <= 1u )
          {
            v97 = v96[6] + 1;
            v96[6] = v97;
          }
        }
        if( !CurrentPrcb->NextThread )
          goto LABEL_67;
        NextThread = CurrentPrcb->NextThread;
      }
      CurrentPrcb->NextThread = 0i64;
LABEL_67:
      if( (NextThread->Tcb.gap0[2] & 4) == 0
        || (v78 = KiIsThreadRankNonZero(&NextThread->Tcb, CurrentPrcb, (_KPRCB *)v8), v49 = 1, !v78) )
      {
        v49 = NextThread->Tcb.Priority;
      }
      *CurrentPrcb->PriorityState = v49;
      if( CurrentPrcb->SchedulerAssist )
      {
        v98 = (unsigned int)KiVpThreadSystemWorkPriority;
        if( NextThread != CurrentPrcb->IdleThread )
          v98 = (unsigned int)v49;
        KiSetSchedulerAssistPriority((INT32 *)CurrentPrcb->SchedulerAssist, v98, 0);
      }
      CurrentPrcb->CurrentThread = NextThread;
      if( NextThread->Tcb.WaitBlockFill6[68] == 1 )
        NextThread->Tcb.ReadyTime = NextThread->Tcb.ReadyTime
                                  - NextThread->Tcb.WaitBlock[2].SpareLong
                                  + KUSER_SHARED_DATA.TickCount.LowPart;
      NextThread->Tcb.WaitBlockFill6[68] = 2;
      goto LABEL_73;
    }
LABEL_128:
    if( NextThread->Tcb.AffinityVersion == KiCpuSetSequence || (NextThread->Tcb._bf_0 & 8) != 0 )
      break;
    KiEnterDeferredReadyState((INT64)NextThread);
    _InterlockedAnd64((volatile signed __int64 *)&CurrentPrcb->PrcbLock, 0i64);
    *(_QWORD *)NextThread->Tcb.gapD8 = 0i64;
    ReadyList.Next = (_SINGLE_LIST_ENTRY *)NextThread->Tcb.gapD8;
    KiReadyDeferredReadyList(CurrentPrcb, &ReadyList);
    v79 = KeGetCurrentPrcb();
    LODWORD(v106) = 0;
    while( _interlockedbittestandset64((volatile signed __int32 *)&CurrentPrcb->PrcbLock, 0i64) )
    {
      do
        KeYieldProcessorEx(&v106);
      while( CurrentPrcb->PrcbLock );
      v89 = v79->SchedulerAssist;
      if( v89 && v79->NestingLevel <= 1u )
      {
        v90 = v89[6] + 1;
        v89[6] = v90;
      }
    }
    NextThread = CurrentPrcb->NextThread;
    if( NextThread )
      goto LABEL_126;
  }
  if( (NextThread->Tcb.gap0[2] & 4) == 0
    || (v75 = KiIsThreadRankNonZero(&NextThread->Tcb, CurrentPrcb, (_KPRCB *)v8), v70 = 1, !v75) )
  {
    v70 = NextThread->Tcb.Priority;
  }
  *CurrentPrcb->PriorityState = v70;
  if( CurrentPrcb->SchedulerAssist )
  {
    v93 = (unsigned int)KiVpThreadSystemWorkPriority;
    if( NextThread != CurrentPrcb->IdleThread )
      v93 = (unsigned int)v70;
    KiSetSchedulerAssistPriority((INT32 *)CurrentPrcb->SchedulerAssist, v93, 0);
  }
  CurrentPrcb->CurrentThread = NextThread;
  if( NextThread->Tcb.WaitBlockFill6[68] == 1 )
  {
LABEL_133:
    v71 = NextThread->Tcb.ReadyTime - NextThread->Tcb.WaitBlock[2].SpareLong + KUSER_SHARED_DATA.TickCount.LowPart;
    NextThread->Tcb.ReadyTime = v71;
  }
LABEL_127:
  NextThread->Tcb.WaitBlockFill6[68] = 2;
LABEL_73:
  if( NextThread != CurrentPrcb->IdleThread && NextThread != OldThread && NextThread->Tcb.Running )
  {
    if( (NextThread->Tcb.gap0[2] & 4) == 0
      || (v80 = KiIsThreadRankNonZero(&NextThread->Tcb, CurrentPrcb, (_KPRCB *)v8), v65 = 1, !v80) )
    {
      v65 = NextThread->Tcb.Priority;
    }
    *CurrentPrcb->PriorityState = v65;
    v66 = CurrentPrcb->SchedulerAssist;
    if( v66 )
    {
      v99 = (unsigned int)KiVpThreadSystemWorkPriority;
      if( NextThread != CurrentPrcb->IdleThread )
        v99 = (unsigned int)v65;
      KiSetSchedulerAssistPriority((INT32 *)CurrentPrcb->SchedulerAssist, v99, 0);
      v66 = CurrentPrcb->SchedulerAssist;
    }
    CurrentPrcb->NextThread = NextThread;
    if( v66 )
      v66[16] = NextThread == CurrentPrcb->IdleThread;
    if( NextThread->Tcb.WaitBlockFill6[68] == 1 )
      NextThread->Tcb.ReadyTime = NextThread->Tcb.ReadyTime
                                - NextThread->Tcb.WaitBlock[2].SpareLong
                                + KUSER_SHARED_DATA.TickCount.LowPart;
    NextThread->Tcb.WaitBlockFill6[68] = 3;
    NextThread = CurrentPrcb->IdleThread;
    CurrentPrcb->CurrentThread = NextThread;
    if( NextThread->Tcb.WaitBlockFill6[68] == 1 )
      NextThread->Tcb.ReadyTime = NextThread->Tcb.ReadyTime
                                - NextThread->Tcb.WaitBlock[2].SpareLong
                                + KUSER_SHARED_DATA.TickCount.LowPart;
    NextThread->Tcb.WaitBlockFill6[68] = 2;
  }
  _InterlockedAnd64((volatile signed __int64 *)&CurrentPrcb->PrcbLock, 0i64);
  KiSetVpThreadSpinLockCount();
  WaitIrql = OldThread->Tcb.WaitIrql;
  if( OldThread == NextThread )
  {
    v53 = NextThread->Tcb.ApcState.KernelApcPending && !NextThread->Tcb.SpecialApcDisable && !(_BYTE)WaitIrql;
    _disable();
    KiStartThreadCycleAccumulation(CurrentPrcb, &NextThread->Tcb, 0);
    _enable();
    if( (*(&NextThread->Tcb.MiscFlags + 1) & 0x800) != 0 )
    {
      _interlockedbittestandreset((volatile signed __int32 *)&NextThread->Tcb.116 + 1, 0xBu);
      KiInsertDeferredPreemptionApc(CurrentPrcb, &NextThread->Tcb, 0);
    }
  }
  else
  {
    v51 = 0;
    if( (*(&OldThread->Tcb.MiscFlags + 1) & 0x400000) != 0
      && OldThread->Tcb.WaitBlockFill6[68] == 5
      && OldThread->Tcb.AbWaitEntryCount )
    {
      LODWORD(v108) = 0;
      while( 1 )
      {
        KiSetVpThreadSpinLockCount();
        if( !_interlockedbittestandset64((volatile signed __int32 *)&OldThread->Tcb.ThreadLock, 0i64) )
          break;
        KiSetVpThreadSpinLockCount();
        do
          KeYieldProcessorEx(&v108);
        while( OldThread->Tcb.ThreadLock );
      }
      if( (*(&OldThread->Tcb.MiscFlags + 1) & 0x400000) != 0 && OldThread->Tcb.WaitBlockFill6[68] == 5 )
      {
        KiUpdateVpBackingRequiresPriorityKickState((INT64)OldThread, 1);
        KiUpdateVPBackingThreadPriority(v100);
        v51 = 1;
      }
      KiReleaseThreadLockSafe((INT64)OldThread);
    }
    KiSwapContext();
    v53 = v52;
    if( v51 )
      KiUpdateVpBackingRequiresPriorityKickState((INT64)OldThread, 0);
  }
  if( _bittestandreset((signed __int32 *)&OldThread->Tcb.116, 9u) && !KiCancelTimer(&OldThread->Tcb.Timer, 1u) )
  {
    OldThread->Tcb.WaitBlockFill7[161] = 4;
    *(_QWORD *)&OldThread->Tcb.Timer.gap0[8] = &OldThread->Tcb.WaitBlock[3];
    *(_QWORD *)&OldThread->Tcb.Timer.gap0[16] = &OldThread->Tcb.WaitBlock[3];
  }
  if( v113 )
    *v113 = OldThread->Tcb.AbWaitObject;
  if( v53 )
  {
    __writecr8(1ui64);
    KiDeliverApc(0, 0i64, 0i64);
  }
  __writecr8(WaitIrql);
}

Referenced by:

KeTerminateThread
KiCommitThreadWait
KiInSwapSingleProcess