KiBeginThreadWait
VOID __stdcall KiBeginThreadWait(_ETHREAD *Thread, CHAR WaitMode, _KWAIT_REASON WaitReason, UINT8 Alertable){
unsigned __int8 WaitIrql;
__int64 v6;
struct _KPRCB *CurrentPrcb;
unsigned __int8 v9;
_DWORD *SchedulerAssist;
UINT64 SpinCount;
_KWAIT_REASON v12;
v12 = WaitReason;
WaitIrql = Thread->Tcb.WaitIrql;
v6 = WaitMode;
while( 1 )
{
Thread->Tcb._bf_0 &= ~0x10u;
Thread->Tcb.WaitRegister.Flags = 0;
Thread->Tcb.WaitMode = v6;
if( Alertable )
Thread->Tcb._bf_0 |= 0x10u;
CurrentPrcb = KeGetCurrentPrcb();
LODWORD(SpinCount) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)&Thread->Tcb.ThreadLock, 0i64) )
{
do
KeYieldProcessorEx(&SpinCount);
while( Thread->Tcb.ThreadLock );
SchedulerAssist = CurrentPrcb->SchedulerAssist;
if( SchedulerAssist && CurrentPrcb->NestingLevel <= 1u )
++SchedulerAssist[6];
}
if( !Thread->Tcb.ApcState.KernelApcPending || Thread->Tcb.SpecialApcDisable || WaitIrql )
break;
KiReleaseThreadLockSafe((INT64)Thread);
__writecr8(1ui64);
KiDeliverApc(0, 0i64, 0i64);
KeGetCurrentIrql();
__writecr8(2ui64);
Thread->Tcb.WaitIrql = 0;
}
v9 = v12;
if( Alertable )
{
if( Thread->Tcb.Alerted[v6] )
{
Thread->Tcb.Alerted[v6] = 0;
}
else if( (_BYTE)v6 && (unsigned __int8 *)Thread->Tcb.ApcState.ApcListHead[1].Flink != &Thread->Tcb.ApcStateFill[16] )
{
Thread->Tcb.ApcState.UserApcPendingAll |= 2u;
}
else
{
if( !Thread->Tcb.Alerted[0] )
{
LABEL_9:
Thread->Tcb.WaitBlockFill6[68] = 5;
Thread->Tcb.WaitReason = v9;
Thread->Tcb.WaitBlock[2].SpareLong = KUSER_SHARED_DATA.TickCount.LowPart;
Thread->Tcb.ThreadLock = 0i64;
return;
}
Thread->Tcb.Alerted[0] = 0;
}
}
else if( (Thread->Tcb.ApcState.UserApcPendingAll & 2) == 0 || !(_BYTE)v6 )
{
goto LABEL_9;
}
KiReleaseThreadLockSafe((INT64)Thread);
KiCheckForThreadDispatch(KeGetCurrentPrcb(), WaitIrql);
}Referenced by:
KeDelayExecutionThread
KeRemovePriQueue
KeWaitForAlertByThreadId
KeWaitForGate
KiWaitForAllObjects