KeSetAffinityThread

VOID __stdcall KeSetAffinityThread(_ETHREAD *Thread, _GROUP_AFFINITY *Affinity){
  __int64 Group; 
  __int64 v4; 
  unsigned __int8 CurrentIrql; 
  struct _KPRCB *CurrentPrcb; 
  __int64 v8; 
  ULONG_PTR v9; 
  bool v10; 
  __int64 v11; 
  __int64 v12; 
  UINT64 SpinCount; 
  _SINGLE_LIST_ENTRY ReadyList; 
  Group = Affinity->Group;
  v4 = *((_QWORD *)Thread + 68);
  ReadyList.Next = 0i64;
  CurrentIrql = KeGetCurrentIrql();
  __writecr8(2ui64);
  CurrentPrcb = KeGetCurrentPrcb();
  ExAcquireSpinLockExclusiveAtDpcLevel((INT64 *)(v4 + 64));
  v8 = *(_QWORD *)(v4 + 8 * Group + 88);
  if( !v8 || (v8 & Affinity->Mask) != Affinity->Mask )
    KiExtendProcessAffinity(v4, Group);
  if( !Affinity->Mask )
    Affinity->Mask = *(_QWORD *)(v4 + 8 * Group + 88);
  KiSetAffinityThread(Thread, &ReadyList, Affinity);
  ExReleaseSpinLockExclusiveFromDpcLevel((INT64 *)(v4 + 64));
  KiReadyDeferredReadyList(CurrentPrcb, &ReadyList);
  if( CurrentIrql >= 2u )
  {
    if( *((_QWORD *)CurrentPrcb + 2) && !*((_BYTE *)CurrentPrcb + 12586) )
      KiRequestSoftwareInterrupt(CurrentPrcb, 2);
  }
  else
  {
    v9 = *((_QWORD *)CurrentPrcb + 1);
    if( *((_QWORD *)CurrentPrcb + 2) )
    {
      KiAbProcessContextSwitch(*((_KTHREAD **)CurrentPrcb + 1), 0i64);
      LODWORD(SpinCount) = 0;
      while( _interlockedbittestandset64((volatile signed __int32 *)CurrentPrcb + 12, 0i64) )
      {
        do
          KeYieldProcessorEx(&SpinCount);
        while( *((_QWORD *)CurrentPrcb + 6) );
      }
      v11 = *((_QWORD *)CurrentPrcb + 2);
      *((_QWORD *)CurrentPrcb + 2) = 0i64;
      _disable();
      KiEndThreadCycleAccumulation(CurrentPrcb, (_KTHREAD *)v9, 0i64);
      _enable();
      *((_QWORD *)CurrentPrcb + 1) = v11;
      if( *(_BYTE *)(v11 + 388) == 1 )
      {
        v12 = (unsigned int)(*(_DWORD *)(v11 + 132) - *(_DWORD *)(v11 + 436));
        *(_DWORD *)(v11 + 132) = v12 + KUSER_SHARED_DATA.TickCount.LowPart;
      }
      *(_BYTE *)(v11 + 388) = 2;
      *(_BYTE *)(v9 + 643) = 32;
      *(_BYTE *)(v9 + 390) = CurrentIrql;
      KiQueueReadyThread((__int64)CurrentPrcb, v9, v12);
      v10 = !KiSwapContext((PKTHREAD)v9, (PKTHREAD)v11);
    }
    else
    {
      v10 = (*(_DWORD *)(v9 + 116) & 0x40) == 0;
    }
    if( !v10 )
    {
      __writecr8(1ui64);
      *(_DWORD *)(v9 + 116) &= ~0x40u;
      KiDeliverApc(0, 0i64, 0i64);
    }
    __writecr8(CurrentIrql);
  }
}

Referenced by:

ExpWorkQueueManagerThread
ExpWorkerThread
NtSetInformationThread