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