KiSearchForNewThread

_KTHREAD *__stdcall KiSearchForNewThread(_KPRCB *CurrentPrcb, UINT8 IdleScan){
  _ETHREAD *NextThread; 
  _ETHREAD *v5; 
  _RTL_RB_TREE *i; 
  _RTL_BALANCED_NODE *Min; 
  __int64 v8; 
  unsigned __int8 IdleState; 
  char v10; 
  _KNODE *ParentNode; 
  unsigned int v12; 
  unsigned __int64 v13; 
  _ETHREAD *result; 
  unsigned int NextNode; 
  unsigned __int64 v16; 
  __int64 v17; 
  _ETHREAD *v18; 
  _KPRCB *v19; 
  char Priority; 
  UINT8 IsThreadRankNonZero; 
  __int64 v22; 
  unsigned __int64 v23; 
  unsigned __int64 GroupSetMember; 
  unsigned __int64 CoreProcessorSet; 
  unsigned __int64 v26; 
  unsigned __int64 v27; 
  _KPRCB *v28; 
  _ETHREAD *IdleThread; 
  UINT8 v30; 
  char v31; 
  INT64 v32; 
  INT64 v33; 
  _SINGLE_LIST_ENTRY ReadyList; 
  UINT64 SpinCount; 
  UINT64 LookupIndex; 

  LODWORD(LookupIndex) = 0;
  NextThread = CurrentPrcb->NextThread;
  if( NextThread )
  {
LABEL_31:
    CurrentPrcb->NextThread = 0i64;
    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;
    return &NextThread->Tcb;
  }
  while( 1 )
  {
    v5 = (_ETHREAD *)KiSelectReadyThread(1i64, CurrentPrcb);
    if( !v5 )
    {
      if( KiPerfIsoEnabled )
      {
        v23 = CurrentPrcb->ParentNode->IdleNonParkedCpuSet
            - ((CurrentPrcb->ParentNode->IdleNonParkedCpuSet >> 1) & 0x5555555555555555i64);
        if( (unsigned int)((0x101010101010101i64
                           * (((v23 & 0x3333333333333333i64)
                             + ((v23 >> 2) & 0x3333333333333333i64)
                             + (((v23 & 0x3333333333333333i64) + ((v23 >> 2) & 0x3333333333333333i64)) >> 4)) & 0xF0F0F0F0F0F0F0Fi64)) >> 32) >> 24 < KiPerfIsoEnabled )
          break;
        GroupSetMember = CurrentPrcb->GroupSetMember;
        CoreProcessorSet = CurrentPrcb->CoreProcessorSet;
        if( GroupSetMember != CoreProcessorSet )
        {
          v26 = CoreProcessorSet & ~GroupSetMember;
          if( (CurrentPrcb->ParentNode->IdleCpuSet & v26) == 0 )
          {
            _BitScanForward64(&v27, v26);
            if( ((*(&KiProcessorBlock
                   + (unsigned int)KiProcessorNumberToIndexMappingTable[64 * CurrentPrcb->Group + (unsigned int)v27]))->PrcbFlags._bf_0 & 0x400) == 0 )
              break;
          }
        }
      }
      v5 = 0i64;
      for( i = &CurrentPrcb->ScbQueue; ; i = (_RTL_RB_TREE *)(v22 + 392) )
      {
        Min = i->Min;
        if( ((unsigned __int8)Min & 1) != 0 )
        {
          if( Min == (_RTL_BALANCED_NODE *)1 )
            goto LABEL_9;
          v8 = (unsigned __int64)Min ^ ((unsigned __int64)i | 1);
        }
        else
        {
          v8 = (__int64)i->Min;
        }
        if( !v8 )
          break;
        v22 = v8 - 88;
        v5 = KiSelectThreadFromSchedulingGroup(CurrentPrcb, (_KSCB *)(v8 - 88), 0i64);
        if( v5 )
          break;
      }
      if( !v5 )
        break;
    }
LABEL_22:
    if( (unsigned int)KiCheckThreadAffinity(&v5->Tcb) )
    {
      if( (v5->Tcb.gap0[2] & 4) == 0
        || (IsThreadRankNonZero = KiIsThreadRankNonZero(&v18->Tcb, CurrentPrcb, v19), Priority = 1, !IsThreadRankNonZero) )
      {
        Priority = v5->Tcb.Priority;
      }
      *CurrentPrcb->PriorityState = Priority;
      if( CurrentPrcb->SchedulerAssist )
      {
        v33 = (unsigned int)KiVpThreadSystemWorkPriority;
        if( v5 != CurrentPrcb->IdleThread )
          v33 = (unsigned int)Priority;
        KiSetSchedulerAssistPriority((INT32 *)CurrentPrcb->SchedulerAssist, v33, 0);
      }
      CurrentPrcb->CurrentThread = v5;
      if( v5->Tcb.WaitBlockFill6[68] == 1 )
        v5->Tcb.ReadyTime = v5->Tcb.ReadyTime - v5->Tcb.WaitBlock[2].SpareLong + KUSER_SHARED_DATA.TickCount.LowPart;
      v5->Tcb.WaitBlockFill6[68] = 2;
      if( IdleScan )
        KiSetProcessorIdle(CurrentPrcb, 0i64, 0i64);
      return &v5->Tcb;
    }
    KiEnterDeferredReadyState((INT64)v18);
    _InterlockedAnd64((volatile signed __int64 *)&CurrentPrcb->PrcbLock, 0i64);
    *(_QWORD *)v5->Tcb.gapD8 = 0i64;
    ReadyList.Next = (_SINGLE_LIST_ENTRY *)v5->Tcb.gapD8;
    KiReadyDeferredReadyList(CurrentPrcb, &ReadyList);
    LODWORD(SpinCount) = 0;
    while( _interlockedbittestandset64((volatile signed __int32 *)&CurrentPrcb->PrcbLock, 0i64) )
    {
      do
        KeYieldProcessorEx(&SpinCount);
      while( CurrentPrcb->PrcbLock );
    }
    if( IdleScan && CurrentPrcb->NextThread == CurrentPrcb->IdleThread )
      CurrentPrcb->NextThread = 0i64;
    NextThread = CurrentPrcb->NextThread;
    if( NextThread )
      goto LABEL_31;
  }
LABEL_9:
  v5 = (_ETHREAD *)KiSelectReadyThread(0i64, CurrentPrcb);
  if( v5 )
    goto LABEL_22;
  IdleState = CurrentPrcb->IdleState;
  if( !IdleScan )
  {
    KiSetProcessorIdle(CurrentPrcb, 1ui64, 0i64);
    IdleThread = CurrentPrcb->IdleThread;
    if( (IdleThread->Tcb.gap0[2] & 4) == 0
      || (v30 = KiIsThreadRankNonZero(&CurrentPrcb->IdleThread->Tcb, CurrentPrcb, v28), v31 = 1, !v30) )
    {
      v31 = IdleThread->Tcb.Priority;
    }
    *CurrentPrcb->PriorityState = v31;
    if( CurrentPrcb->SchedulerAssist )
    {
      v32 = (unsigned int)KiVpThreadSystemWorkPriority;
      if( IdleThread != CurrentPrcb->IdleThread )
        v32 = (unsigned int)v31;
      KiSetSchedulerAssistPriority((INT32 *)CurrentPrcb->SchedulerAssist, v32, 0);
    }
  }
  v10 = CurrentPrcb->IdleState & 2;
  _InterlockedAnd64((volatile signed __int64 *)&CurrentPrcb->PrcbLock, 0i64);
  if( v10 && IdleState != 7 )
    return 0i64;
  ParentNode = CurrentPrcb->ParentNode;
  v12 = ParentNode->Affinity.Reserved[0];
  LODWORD(v13) = ParentNode->SiblingMask;
LABEL_13:
  result = (_ETHREAD *)KiSearchForNewThreadOnNode(CurrentPrcb, ParentNode);
  if( !result )
  {
    v13 = (unsigned int)v13 & (unsigned __int64)~(1i64 << ParentNode->Affinity.Reserved[0]);
    if( (_DWORD)v13 )
    {
      while( 1 )
      {
        NextNode = MmGetNextNode(v12, &LookupIndex);
        v16 = NextNode;
        if( NextNode == -1 )
          break;
        v17 = (unsigned int)v13;
        if( _bittest64(&v17, v16) )
        {
          ParentNode = (_KNODE *)KeNodeBlock[v16];
          goto LABEL_13;
        }
      }
    }
    return 0i64;
  }
  return &result->Tcb;
}

Referenced by:

No references.