KiSetHeteroPolicyThread
_KHETERO_CPU_POLICY __stdcall KiSetHeteroPolicyThread(
_ETHREAD *Thread,
_KHETERO_CPU_POLICY NewPolicy,
UINT64 SetUserPolicy,
UINT64 Set){
int v4;
int v5;
unsigned __int8 CurrentIrql;
__int64 IdealProcessor;
unsigned int UserIdealProcessor;
int SystemHeteroCpuPolicy;
char v12;
bool v13;
NTSTATUS v14;
__int64 v15;
char v16;
unsigned __int64 v17;
char v18;
unsigned int v19;
int v20;
unsigned __int8 v21;
_KPRCB *v22;
_KPRCB *v23;
int v24;
int v25;
UINT64 Number;
struct _KPRCB *CurrentPrcb;
_ETHREAD *CurrentThread;
INT64 v29;
_ETHREAD *NextThread;
char v31;
bool v32;
UINT64 *PreferredSetOut;
UINT64 *AvailableSetOut;
_KPRCB *ControlPrcb;
_SINGLE_LIST_ENTRY ReadyList;
int v38;
int v39;
UINT64 v40;
UINT64 v41;
_KSHARED_READY_QUEUE *ControlReadyQueue;
UINT64 IdealSetOut;
UINT64 v44;
UINT64 SpinCount;
v41 = 0i64;
v4 = Set;
IdealSetOut = 0i64;
v5 = SetUserPolicy;
ControlPrcb = 0i64;
v44 = 0i64;
ReadyList.Next = 0i64;
ControlReadyQueue = 0i64;
CurrentIrql = KeGetCurrentIrql();
__writecr8(2ui64);
LODWORD(SpinCount) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)&Thread->Tcb.ThreadLock, 0i64) )
{
do
KeYieldProcessorEx(&SpinCount);
while( Thread->Tcb.ThreadLock );
}
IdealProcessor = Thread->Tcb.IdealProcessor;
UserIdealProcessor = Thread->Tcb.UserIdealProcessor;
v38 = Thread->Tcb.IdealProcessor;
v39 = UserIdealProcessor;
if( v5 )
{
SystemHeteroCpuPolicy = Thread->Tcb.SystemHeteroCpuPolicy;
v12 = (Thread->Tcb._bf_0 ^ NewPolicy) & 0x7F;
v13 = ((v12 ^ Thread->Tcb._bf_0) & 0x80u) != 0;
Thread->Tcb._bf_0 ^= v12;
if( v13 )
goto LABEL_8;
goto LABEL_7;
}
if( v4 )
{
LABEL_7:
SystemHeteroCpuPolicy = NewPolicy;
goto LABEL_8;
}
SystemHeteroCpuPolicy = Thread->Tcb._bf_0 & 0x7F;
Thread->Tcb._bf_0 &= ~0x80u;
LABEL_8:
if( SystemHeteroCpuPolicy == 8 )
SystemHeteroCpuPolicy = KiDefaultHeteroCpuPolicy;
if( !KeHeteroSystem )
{
SystemHeteroCpuPolicy = 0;
Thread->Tcb._bf_0 &= ~0x80u;
}
if( Thread->Tcb.SystemHeteroCpuPolicy == SystemHeteroCpuPolicy )
{
KiReleaseThreadLockSafe((INT64)Thread);
__writecr8(CurrentIrql);
}
else
{
v14 = SystemHeteroCpuPolicy;
v15 = (__int64)*(&KiProcessorBlock + IdealProcessor);
if( SystemHeteroCpuPolicy >= 5 )
v14 = KiConvertDynamicHeteroPolicy(Thread, NewPolicy, *(&KiProcessorBlock + IdealProcessor));
KiGenerateHeteroSets(
*(_KNODE **)(v15 + 192),
Thread->Tcb.Affinity.Mask,
(_KHETERO_CPU_POLICY)v14,
&IdealSetOut,
&v44,
&v41);
if( (IdealSetOut & *(_QWORD *)(v15 + 200)) == 0 )
{
v16 = *(_BYTE *)(v15 + 209);
_BitScanForward64(&v17, __ROR8__(IdealSetOut, v16));
v18 = v17 + v16;
LODWORD(v17) = Thread->Tcb._bf_0;
v19 = KiProcessorNumberToIndexMappingTable[64 * *(unsigned __int8 *)(v15 + 208) + (v18 & 0x3F)];
Thread->Tcb.IdealProcessor = v19;
if( (v17 & 8) == 0 )
Thread->Tcb.UserIdealProcessor = v19;
}
v20 = 0;
KiAcquireThreadStateLock(Thread, &ControlPrcb, &ControlReadyQueue);
v22 = ControlPrcb;
Thread->Tcb.SystemHeteroCpuPolicy = SystemHeteroCpuPolicy;
if( v21 == 1 )
{
KiRemoveThreadFromAnyReadyQueue(v22, ControlReadyQueue, (__int64)Thread, (unsigned int)Thread->Tcb.Priority);
KiPrepareReadyThreadForRescheduling(&Thread->Tcb, (unsigned int)Thread->Tcb.Priority, &ReadyList);
}
else
{
v23 = (_KPRCB *)((unsigned int)v21 - 2);
if( v21 == 2 )
{
if( (v22->GroupSetMember & v41) == 0 )
{
if( Thread->Tcb.WaitBlockFill6[68] == 2 )
{
_interlockedbittestandset((volatile signed __int32 *)&Thread->Tcb.116 + 1, 0xCu);
v22 = ControlPrcb;
if( !ControlPrcb->NextThread )
{
KiSelectNextThread(ControlPrcb, &ReadyList);
v20 = 1;
}
}
else
{
Thread->Tcb.WaitRegister.Flags |= 8u;
v22 = ControlPrcb;
}
}
}
else if( v21 == 3 && (v22->GroupSetMember & v41) == 0 )
{
KiSelectNextThread(v22, &ReadyList);
KiInsertDeferredReadyList((INT64)&ReadyList, (INT64)Thread);
}
}
v24 = Thread->Tcb.IdealProcessor;
v25 = Thread->Tcb.UserIdealProcessor;
KiReleaseThreadStateLock(v23, (_KSHARED_READY_QUEUE *)v22);
KiReleaseThreadLockSafe((INT64)Thread);
if( v20 )
{
Number = ControlPrcb->Number;
if( KeGetPcr()->Prcb.Number != (_DWORD)Number )
KiSendSoftwareInterrupt(Number, 2u);
}
if( (xmmword_140CFB490 & 0x8000000) != 0 )
{
EtwTraceIdealProcessor((__int64)Thread, 0x546u, v38, v24);
if( (xmmword_140CFB490 & 0x8000000) != 0 )
EtwTraceIdealProcessor((__int64)Thread, 0x547u, v39, v25);
}
CurrentPrcb = KeGetCurrentPrcb();
KiReadyDeferredReadyList(CurrentPrcb, &ReadyList);
if( CurrentIrql >= 2u )
{
if( CurrentPrcb->NextThread && !CurrentPrcb->DpcRoutineActive )
KiRequestSoftwareInterrupt(CurrentPrcb, 2);
}
else
{
CurrentThread = CurrentPrcb->CurrentThread;
if( CurrentPrcb->NextThread )
{
KiAbProcessContextSwitch(&CurrentPrcb->CurrentThread->Tcb, 0i64);
LODWORD(v40) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)&CurrentPrcb->PrcbLock, 0i64) )
{
do
KeYieldProcessorEx(&v40);
while( CurrentPrcb->PrcbLock );
}
NextThread = CurrentPrcb->NextThread;
CurrentPrcb->NextThread = 0i64;
_disable();
KiEndThreadCycleAccumulation(
(INT64)CurrentPrcb,
(INT64)CurrentThread,
0i64,
v29,
(INT64)PreferredSetOut,
(INT64)AvailableSetOut,
(INT64)ControlPrcb);
_enable();
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;
CurrentThread->Tcb.WaitReason = 32;
CurrentThread->Tcb.WaitIrql = CurrentIrql;
KiQueueReadyThread(CurrentPrcb, &CurrentThread->Tcb);
KiSwapContext();
v32 = v31 == 0;
}
else
{
v32 = (CurrentThread->Tcb._bf_0 & 0x40) == 0;
}
if( !v32 )
{
__writecr8(1ui64);
CurrentThread->Tcb._bf_0 &= ~0x40u;
KiDeliverApc(0, 0i64, 0i64);
}
__writecr8(CurrentIrql);
}
}
return SystemHeteroCpuPolicy;
}Referenced by:
KeSetHeteroCpuPolicyThread
KeSetUserHeteroCpuPolicyThread
PopUpdateSingleThreadHeteroPolicies