KiCommitThreadWait

VOID __fastcall KiCommitThreadWait(
        _ETHREAD *Thread,
        _KWAIT_BLOCK *WaitBlockList,
        _KDUE_TIME_TYPE TimeoutType,
        UINT64 DueTime){
  int v5; 
  char v6; 
  _KWAIT_BLOCK *v7; 
  struct _KPRCB *CurrentPrcb; 
  _BOOL4 v10; 
  struct _KPRCB *v11; 
  _KWAIT_STATUS_REGISTER v12; 
  int v13; 
  unsigned __int16 v14; 
  _DISPATCHER_HEADER *volatile Queue; 
  __int64 v16; 
  char v17; 
  _ETHREAD *v18; 
  _QWORD *v19; 
  char *v20; 
  struct _KPRCB *v21; 
  _LIST_ENTRY *Blink; 
  _LIST_ENTRY *v23; 
  __int64 ThreadTimerDelay; 
  volatile signed __int32 *p_Timer; 
  _ULARGE_INTEGER v26; 
  bool v27; 
  _EPROCESS *Process; 
  char v29; 
  __int64 v30; 
  _QWORD *v31; 
  char v32; 
  __int64 QueuePriority; 
  _DWORD *SchedulerAssist; 
  volatile __int64 WaitStatus; 
  _KWAIT_BLOCK *v36; 
  VOID *Object; 
  _LIST_ENTRY *Flink; 
  _LIST_ENTRY *v39; 
  _DWORD *v40; 
  volatile __int64 v41; 
  struct _KPRCB *v42; 
  __int64 WaitMode; 
  _DISPATCHER_HEADER *v44; 
  __int64 v45; 
  _DWORD *v46; 
  int v47; 
  UINT64 v48; 
  _LARGE_INTEGER Interval; 
  __int128 v50; 
  __int64 v51; 
  UINT64 Hand; 
  UINT64 SpinCount; 
  char v54; 
  void *volatile *v55; 

  Interval.QuadPart = DueTime;
  v54 = 0;
  v50 = 0i64;
  v51 = 0i64;
  v5 = 0;
  LODWORD(Hand) = 0;
  v6 = 0;
  v7 = WaitBlockList;
  _m_prefetchw(&Thread->Tcb.WaitRegister);
  if( TimeoutType )
  {
    Thread->Tcb._bf_0 |= 0x200u;
    *(_DWORD *)Thread->Tcb.Timer.gap0 |= 0x40000080u;
  }
  CurrentPrcb = KeGetCurrentPrcb();
  Thread->Tcb.WaitBlockList = WaitBlockList;
  v10 = Thread->Tcb.WaitMode && (*(&Thread->Tcb.MiscFlags + 1) & 0x40) != 0 && Thread->Tcb.Priority < 25;
  v11 = KeGetCurrentPrcb();
  LODWORD(SpinCount) = 0;
  while( _interlockedbittestandset64((volatile signed __int32 *)&Thread->Tcb.ThreadLock, 0i64) )
  {
    do
      KeYieldProcessorEx(&SpinCount);
    while( Thread->Tcb.ThreadLock );
    SchedulerAssist = v11->SchedulerAssist;
    if( SchedulerAssist && v11->NestingLevel <= 1u )
      ++SchedulerAssist[6];
  }
  v12.Flags = (unsigned __int8)Thread->Tcb.WaitRegister;
  if( (v12.Flags & 0xE7) == 0 )
  {
    Thread->Tcb.WaitRegister.Flags = v12.Flags & 0xF8 | 1;
    if( v10 )
    {
      v21 = KeGetCurrentPrcb();
      LODWORD(v48) = 0;
      while( _interlockedbittestandset64((volatile signed __int32 *)&CurrentPrcb->WaitLock, 0i64) )
      {
        do
          KeYieldProcessorEx(&v48);
        while( CurrentPrcb->WaitLock );
        v40 = v21->SchedulerAssist;
        if( v40 && v21->NestingLevel <= 1u )
          ++v40[6];
      }
      Blink = CurrentPrcb->WaitListHead.Blink;
      v23 = (_LIST_ENTRY *)Thread->Tcb.gapD8;
      if( Blink->Flink != &CurrentPrcb->WaitListHead )
        goto LABEL_82;
      v23->Flink = &CurrentPrcb->WaitListHead;
      *(_QWORD *)&Thread->Tcb.gapD8[8] = Blink;
      Blink->Flink = v23;
      CurrentPrcb->WaitListHead.Blink = v23;
      Thread->Tcb.SchedulerApc.SystemArgument1 = CurrentPrcb;
      _InterlockedAnd64((volatile signed __int64 *)&CurrentPrcb->WaitLock, 0i64);
    }
    v13 = *(&Thread->Tcb.MiscFlags + 1);
    if( (v13 & 0x1000) != 0 )
    {
      _interlockedbittestandreset((volatile signed __int32 *)&Thread->Tcb.116 + 1, 0xCu);
      v13 = *(&Thread->Tcb.MiscFlags + 1);
    }
    v14 = 1;
    if( (_bittest((const signed __int32 *)&Thread->Tcb.116, 0x13u) & ((v13 & 0x4000) != 0)) != 0
      && !_interlockedbittestandset((volatile signed __int32 *)&Thread->Tcb.116 + 1, 0x14u) )
    {
      v5 = 1;
    }
    if( TimeoutType == DueTimeRelative )
    {
      ThreadTimerDelay = Thread->Tcb.ThreadTimerDelay;
      if( Thread->Tcb.WaitMode )
      {
        if( !Thread->Tcb.WaitBlock[3].SpareLong && !Thread->Tcb.WaitIrql && !Thread->Tcb.ApcState.InProgressFlags )
        {
          v54 = 1;
          if( (_DWORD)ThreadTimerDelay )
            Interval.QuadPart += ThreadTimerDelay;
        }
      }
    }
    if( Thread->Tcb.WaitReason == 15 || (Queue = Thread->Tcb.Queue) == 0i64 )
    {
      Thread->Tcb.ThreadLock = 0i64;
      goto LABEL_16;
    }
    _m_prefetchw(Queue);
    if( (*(_BYTE *)Queue & 0x7F) == 21 )
    {
      QueuePriority = (unsigned __int8)Thread->Tcb.QueuePriority;
      v16 = 4 * QueuePriority + 536;
      Thread->Tcb.QueuePriority = QueuePriority | 0x100;
    }
    else
    {
      v16 = 40i64;
    }
    _InterlockedDecrement((volatile signed __int32 *)((char *)Queue + v16));
    if( _interlockedbittestandset((volatile signed __int32 *)Queue, 7u) )
      v17 = 0;
    else
      v17 = 1;
    Thread->Tcb.ThreadLock = 0i64;
    v18 = (_ETHREAD *)KeGetCurrentPrcb()->SchedulerAssist;
    if( v17 )
    {
      if( (*(_BYTE *)Queue & 0x7F) != 21 )
      {
        if( *((_DWORD *)Queue + 10) >= *((_DWORD *)Queue + 11) )
          goto LABEL_28;
        v19 = (_QWORD *)*((_QWORD *)Queue + 3);
        v20 = (char *)Queue + 24;
        if( v19 == (_QWORD *)((char *)Queue + 24)
          || *((_DISPATCHER_HEADER *volatile *)Queue + 1) == (_DISPATCHER_HEADER *volatile)((char *)Queue + 8) )
        {
          goto LABEL_28;
        }
        v30 = *v19;
        v31 = (_QWORD *)v19[1];
        if( *(_QWORD **)(*v19 + 8i64) == v19 && (_QWORD *)*v31 == v19 )
        {
          *v31 = v30;
          *(_QWORD *)(v30 + 8) = v31;
          *v19 = 0i64;
          KiWakeQueueWaiter(KeGetCurrentPrcb(), (_KQUEUE *)Queue, (INT64)v19);
          if( v32 )
          {
            --*((_DWORD *)Queue + 1);
            _InterlockedAnd((volatile signed __int32 *)Queue, 0xFFFFFF7F);
            goto LABEL_16;
          }
          v45 = *(_QWORD *)v20;
          if( *(char **)(*(_QWORD *)v20 + 8i64) == v20 )
          {
            *v19 = v45;
            v19[1] = v20;
            *(_QWORD *)(v45 + 8) = v19;
            *(_QWORD *)v20 = v19;
LABEL_28:
            _InterlockedAnd((volatile signed __int32 *)Queue, 0xFFFFFF7F);
            goto LABEL_16;
          }
        }
LABEL_82:
        __fastfail(3u);
      }
      KiActivateWaiterPriQueue((ULONG_PTR)Queue, v18);
    }
    else
    {
      KiActivateWaiterQueueWithNoLocks(&Thread->Tcb, Queue, 0i64);
    }
LABEL_16:
    if( v5 )
      KiDecrementProcessStackCount(&Thread->Tcb.ApcState.Process->Pcb);
    Thread->Tcb.Preempted = 0;
    if( TimeoutType == DueTimeNone )
      goto LABEL_19;
    p_Timer = (volatile signed __int32 *)&Thread->Tcb.Timer;
    if( TimeoutType == DueTimeRelative )
    {
      v26.QuadPart = Interval.QuadPart + KUSER_SHARED_DATA.InterruptTimeBias + Thread->Tcb.RelativeTimerBias;
      Thread->Tcb.Timer.DueTime = v26;
      v26.QuadPart >>= 18;
      LODWORD(Hand) = LOBYTE(v26.QuadPart);
      LODWORD(v50) = *p_Timer;
      BYTE1(v50) &= ~1u;
      v27 = v54 == 0;
      BYTE2(v50) = v26.LowPart;
      *p_Timer = v50;
      if( !v27 )
        _InterlockedIncrement((volatile signed __int32 *)&Thread->Tcb.Process->ThreadTimerSets);
    }
    else if( !(unsigned int)KiComputeDueTime(&Thread->Tcb.Timer, Interval, 0, &Hand) )
    {
      goto LABEL_101;
    }
    if( (KiVelocityFlags & 0x2000) == 0
      || ((Process = Thread->Tcb.Process, (Process->Flags & 0x1000) == 0) || (Process->Flags3 & 0x4000000) != 0 ? (v29 = 0) : (v29 = 1),
          v29) )
    {
      v14 = 0;
    }
    Thread->Tcb.Timer.TimerType = v14;
    if( KiInsertTimerTable(CurrentPrcb, &Thread->Tcb.Timer, 0i64, (unsigned int)Hand, 0i64) )
    {
      _InterlockedAnd(p_Timer, 0xFFFFFF7F);
LABEL_19:
      KiSwapThread(Thread, CurrentPrcb);
      return;
    }
LABEL_101:
    KiTimerWaitTest(CurrentPrcb, &Thread->Tcb.Timer, 0i64);
    goto LABEL_19;
  }
  if( (v12.Flags & 7) == 0 )
  {
    if( (v12.Flags & 0x20) != 0 )
    {
      Thread->Tcb.WaitStatus = 256i64;
      Thread->Tcb.AbWaitObject = 0i64;
    }
    else
    {
      v6 = 1;
      if( (v12.Flags & 0x40) != 0 )
        v41 = 192i64;
      else
        v41 = 257i64;
      Thread->Tcb.WaitStatus = v41;
      Thread->Tcb.AbWaitObject = 0i64;
    }
  }
  Thread->Tcb.WaitBlockFill6[68] = 2;
  if( Thread->Tcb.WaitReason == 15 )
  {
    v44 = Thread->Tcb.Queue;
    if( v44 )
      KiIncrementConcurrencyCount(v44, &Thread->Tcb);
  }
  KiReleaseThreadLockSafe((INT64)Thread);
  if( TimeoutType )
    Thread->Tcb._bf_0 &= ~0x200u;
  WaitStatus = Thread->Tcb.WaitStatus;
  if( v55 )
    *v55 = Thread->Tcb.AbWaitObject;
  if( v6 )
  {
    v42 = KeGetCurrentPrcb();
    WaitMode = Thread->Tcb.WaitMode;
    HIDWORD(v48) = 0;
    while( _interlockedbittestandset64((volatile signed __int32 *)&Thread->Tcb.ThreadLock, 0i64) )
    {
      do
        KeYieldProcessorEx((UINT64 *)((char *)&v48 + 4));
      while( Thread->Tcb.ThreadLock );
      v46 = v42->SchedulerAssist;
      if( v46 && v42->NestingLevel <= 1u )
      {
        v47 = v46[6] + 1;
        v46[6] = v47;
      }
    }
    if( WaitStatus == 257 )
    {
      if( (Thread->Tcb._bf_0 & 0x10) != 0 )
      {
        if( Thread->Tcb.Alerted[WaitMode] )
        {
          Thread->Tcb.Alerted[WaitMode] = 0;
        }
        else if( (_BYTE)WaitMode )
        {
          Thread->Tcb.Alerted[0] = 0;
        }
      }
      else
      {
        _interlockedbittestandreset((volatile signed __int32 *)&Thread->Tcb.116 + 1, 4u);
      }
    }
    else if( (unsigned __int8 *)Thread->Tcb.ApcState.ApcListHead[1].Flink != &Thread->Tcb.ApcStateFill[16] )
    {
      Thread->Tcb.ApcState.UserApcPendingAll |= 2u;
    }
    KiReleaseThreadLockSafe((INT64)Thread);
  }
  v36 = &v7[Thread->Tcb.WaitBlockCount];
  do
  {
    if( v7->BlockState < 5u )
    {
      Object = v7->Object;
      KiAcquireKobjectLockSafe(Object);
      if( v7->BlockState == 4 )
      {
        Flink = v7->WaitListEntry.Flink;
        v39 = v7->WaitListEntry.Blink;
        if( (_KWAIT_BLOCK *)v7->WaitListEntry.Flink->Blink != v7 || (_KWAIT_BLOCK *)v39->Flink != v7 )
          goto LABEL_82;
        v39->Flink = Flink;
        Flink->Blink = v39;
      }
      _InterlockedAnd((volatile signed __int32 *)Object, 0xFFFFFF7F);
    }
    ++v7;
  }
  while( v7 != v36 );
  if( CurrentPrcb->DeferredReadyListHead.Next )
    KiProcessThreadWaitList(CurrentPrcb, AdjustUnwait, 0i64, 0i64);
  KiExitThreadWait(CurrentPrcb, &Thread->Tcb, 1u);
}

Referenced by:

KeDelayExecutionThread
KeRemovePriQueue
KeRemoveQueueEx
KeWaitForAlertByThreadId
KeWaitForGate
KeWaitForMultipleObjects
KeWaitForSingleObject
KiWaitForAllObjects