KeSetAffinityThread

NTSTATUS __fastcall KeSetAffinityThread(INT64 a1, INT64 a2){
  __int64 v2; 
  __int64 v4; 
  unsigned __int8 CurrentIrql; 
  struct _KPRCB *CurrentPrcb; 
  __int64 v8; 
  NTSTATUS result; 
  _ETHREAD *CurrentThread; 
  bool v11; 
  INT64 v12; 
  _ETHREAD *NextThread; 
  char v14; 
  INT64 v15; 
  INT64 v16; 
  INT64 v17; 
  UINT64 SpinCount; 
  _SINGLE_LIST_ENTRY ReadyList; 

  v2 = *(unsigned __int16 *)(a2 + 8);
  v4 = *(_QWORD *)(a1 + 544);
  ReadyList.Next = 0i64;
  CurrentIrql = KeGetCurrentIrql();
  __writecr8(2ui64);
  CurrentPrcb = KeGetCurrentPrcb();
  ExAcquireSpinLockExclusiveAtDpcLevel((INT64 *)(v4 + 64));
  v8 = *(_QWORD *)(v4 + 8 * v2 + 88);
  if( !v8 || (v8 & *(_QWORD *)a2) != *(_QWORD *)a2 )
    KiExtendProcessAffinity((_KPROCESS *)v4, (unsigned __int16)v2);
  if( !*(_QWORD *)a2 )
    *(_QWORD *)a2 = *(_QWORD *)(v4 + 8 * v2 + 88);
  KiSetAffinityThread((_KTHREAD *)a1, &ReadyList, (_GROUP_AFFINITY *)a2);
  ExReleaseSpinLockExclusiveFromDpcLevel((INT64 *)(v4 + 64));
  KiReadyDeferredReadyList(CurrentPrcb, &ReadyList);
  if( CurrentIrql >= 2u )
  {
    if( CurrentPrcb->NextThread )
    {
      LOBYTE(result) = CurrentPrcb->DpcRoutineActive;
      if( !(_BYTE)result )
        KiRequestSoftwareInterrupt(CurrentPrcb, 2);
    }
  }
  else
  {
    CurrentThread = CurrentPrcb->CurrentThread;
    if( CurrentPrcb->NextThread )
    {
      KiAbProcessContextSwitch(&CurrentPrcb->CurrentThread->Tcb, 0i64);
      LODWORD(SpinCount) = 0;
      while( _interlockedbittestandset64((volatile signed __int32 *)&CurrentPrcb->PrcbLock, 0i64) )
      {
        do
          KeYieldProcessorEx(&SpinCount);
        while( CurrentPrcb->PrcbLock );
      }
      NextThread = CurrentPrcb->NextThread;
      CurrentPrcb->NextThread = 0i64;
      _disable();
      KiEndThreadCycleAccumulation((INT64)CurrentPrcb, (INT64)CurrentThread, 0i64, v12, v15, v16, v17);
      _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();
      v11 = v14 == 0;
    }
    else
    {
      v11 = (CurrentThread->Tcb._bf_0 & 0x40) == 0;
    }
    if( !v11 )
    {
      __writecr8(1ui64);
      CurrentThread->Tcb._bf_0 &= ~0x40u;
      KiDeliverApc(0, 0i64, 0i64);
    }
    result = CurrentIrql;
    __writecr8(CurrentIrql);
  }
  return result;
}

Referenced by:

ExpWorkQueueManagerThread
ExpWorkerThread
NtSetInformationThread