KThread.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. using ChocolArm64;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using static Ryujinx.HLE.HOS.ErrorCode;
  6. namespace Ryujinx.HLE.HOS.Kernel
  7. {
  8. class KThread : KSynchronizationObject, IKFutureSchedulerObject
  9. {
  10. public AThread Context { get; private set; }
  11. public long AffinityMask { get; set; }
  12. public int ThreadId { get; private set; }
  13. public KSynchronizationObject SignaledObj;
  14. public long CondVarAddress { get; set; }
  15. public long MutexAddress { get; set; }
  16. public Process Owner { get; private set; }
  17. public long LastScheduledTicks { get; set; }
  18. public LinkedListNode<KThread>[] SiblingsPerCore { get; private set; }
  19. private LinkedListNode<KThread> WithholderNode;
  20. private LinkedList<KThread> MutexWaiters;
  21. private LinkedListNode<KThread> MutexWaiterNode;
  22. public KThread MutexOwner { get; private set; }
  23. public int ThreadHandleForUserMutex { get; set; }
  24. private ThreadSchedState ForcePauseFlags;
  25. public int ObjSyncResult { get; set; }
  26. public int DynamicPriority { get; set; }
  27. public int CurrentCore { get; set; }
  28. public int BasePriority { get; set; }
  29. public int PreferredCore { get; set; }
  30. private long AffinityMaskOverride;
  31. private int PreferredCoreOverride;
  32. private int AffinityOverrideCount;
  33. public ThreadSchedState SchedFlags { get; private set; }
  34. public bool ShallBeTerminated { get; private set; }
  35. public bool SyncCancelled { get; set; }
  36. public bool WaitingSync { get; set; }
  37. private bool HasExited;
  38. public bool WaitingInArbitration { get; set; }
  39. private KScheduler Scheduler;
  40. private KSchedulingData SchedulingData;
  41. public long LastPc { get; set; }
  42. public KThread(
  43. AThread Thread,
  44. Process Process,
  45. Horizon System,
  46. int ProcessorId,
  47. int Priority,
  48. int ThreadId) : base(System)
  49. {
  50. this.ThreadId = ThreadId;
  51. Context = Thread;
  52. Owner = Process;
  53. PreferredCore = ProcessorId;
  54. Scheduler = System.Scheduler;
  55. SchedulingData = System.Scheduler.SchedulingData;
  56. SiblingsPerCore = new LinkedListNode<KThread>[KScheduler.CpuCoresCount];
  57. MutexWaiters = new LinkedList<KThread>();
  58. AffinityMask = 1 << ProcessorId;
  59. DynamicPriority = BasePriority = Priority;
  60. CurrentCore = PreferredCore;
  61. }
  62. public long Start()
  63. {
  64. long Result = MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating);
  65. System.CriticalSectionLock.Lock();
  66. if (!ShallBeTerminated)
  67. {
  68. KThread CurrentThread = System.Scheduler.GetCurrentThread();
  69. while (SchedFlags != ThreadSchedState.TerminationPending &&
  70. CurrentThread.SchedFlags != ThreadSchedState.TerminationPending &&
  71. !CurrentThread.ShallBeTerminated)
  72. {
  73. if ((SchedFlags & ThreadSchedState.LowNibbleMask) != ThreadSchedState.None)
  74. {
  75. Result = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
  76. break;
  77. }
  78. if (CurrentThread.ForcePauseFlags == ThreadSchedState.None)
  79. {
  80. if (Owner != null && ForcePauseFlags != ThreadSchedState.None)
  81. {
  82. CombineForcePauseFlags();
  83. }
  84. SetNewSchedFlags(ThreadSchedState.Running);
  85. Result = 0;
  86. break;
  87. }
  88. else
  89. {
  90. CurrentThread.CombineForcePauseFlags();
  91. System.CriticalSectionLock.Unlock();
  92. System.CriticalSectionLock.Lock();
  93. if (CurrentThread.ShallBeTerminated)
  94. {
  95. break;
  96. }
  97. }
  98. }
  99. }
  100. System.CriticalSectionLock.Unlock();
  101. return Result;
  102. }
  103. public void Exit()
  104. {
  105. System.CriticalSectionLock.Lock();
  106. ForcePauseFlags &= ~ThreadSchedState.ExceptionalMask;
  107. ExitImpl();
  108. System.CriticalSectionLock.Unlock();
  109. }
  110. private void ExitImpl()
  111. {
  112. System.CriticalSectionLock.Lock();
  113. SetNewSchedFlags(ThreadSchedState.TerminationPending);
  114. HasExited = true;
  115. Signal();
  116. System.CriticalSectionLock.Unlock();
  117. }
  118. public long Sleep(long Timeout)
  119. {
  120. System.CriticalSectionLock.Lock();
  121. if (ShallBeTerminated || SchedFlags == ThreadSchedState.TerminationPending)
  122. {
  123. System.CriticalSectionLock.Unlock();
  124. return MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating);
  125. }
  126. SetNewSchedFlags(ThreadSchedState.Paused);
  127. if (Timeout > 0)
  128. {
  129. System.TimeManager.ScheduleFutureInvocation(this, Timeout);
  130. }
  131. System.CriticalSectionLock.Unlock();
  132. if (Timeout > 0)
  133. {
  134. System.TimeManager.UnscheduleFutureInvocation(this);
  135. }
  136. return 0;
  137. }
  138. public void Yield()
  139. {
  140. System.CriticalSectionLock.Lock();
  141. if (SchedFlags != ThreadSchedState.Running)
  142. {
  143. System.CriticalSectionLock.Unlock();
  144. System.Scheduler.ContextSwitch();
  145. return;
  146. }
  147. if (DynamicPriority < KScheduler.PrioritiesCount)
  148. {
  149. //Move current thread to the end of the queue.
  150. SchedulingData.Reschedule(DynamicPriority, CurrentCore, this);
  151. }
  152. Scheduler.ThreadReselectionRequested = true;
  153. System.CriticalSectionLock.Unlock();
  154. System.Scheduler.ContextSwitch();
  155. }
  156. public void YieldWithLoadBalancing()
  157. {
  158. int Prio = DynamicPriority;
  159. int Core = CurrentCore;
  160. System.CriticalSectionLock.Lock();
  161. if (SchedFlags != ThreadSchedState.Running)
  162. {
  163. System.CriticalSectionLock.Unlock();
  164. System.Scheduler.ContextSwitch();
  165. return;
  166. }
  167. KThread NextThreadOnCurrentQueue = null;
  168. if (DynamicPriority < KScheduler.PrioritiesCount)
  169. {
  170. //Move current thread to the end of the queue.
  171. SchedulingData.Reschedule(Prio, Core, this);
  172. Func<KThread, bool> Predicate = x => x.DynamicPriority == Prio;
  173. NextThreadOnCurrentQueue = SchedulingData.ScheduledThreads(Core).FirstOrDefault(Predicate);
  174. }
  175. IEnumerable<KThread> SuitableCandidates()
  176. {
  177. foreach (KThread Thread in SchedulingData.SuggestedThreads(Core))
  178. {
  179. int SrcCore = Thread.CurrentCore;
  180. if (SrcCore >= 0)
  181. {
  182. KThread SelectedSrcCore = Scheduler.CoreContexts[SrcCore].SelectedThread;
  183. if (SelectedSrcCore == Thread || ((SelectedSrcCore?.DynamicPriority ?? 2) < 2))
  184. {
  185. continue;
  186. }
  187. }
  188. //If the candidate was scheduled after the current thread, then it's not worth it,
  189. //unless the priority is higher than the current one.
  190. if (NextThreadOnCurrentQueue.LastScheduledTicks >= Thread.LastScheduledTicks ||
  191. NextThreadOnCurrentQueue.DynamicPriority < Thread.DynamicPriority)
  192. {
  193. yield return Thread;
  194. }
  195. }
  196. }
  197. KThread Dst = SuitableCandidates().FirstOrDefault(x => x.DynamicPriority <= Prio);
  198. if (Dst != null)
  199. {
  200. SchedulingData.TransferToCore(Dst.DynamicPriority, Core, Dst);
  201. Scheduler.ThreadReselectionRequested = true;
  202. }
  203. if (this != NextThreadOnCurrentQueue)
  204. {
  205. Scheduler.ThreadReselectionRequested = true;
  206. }
  207. System.CriticalSectionLock.Unlock();
  208. System.Scheduler.ContextSwitch();
  209. }
  210. public void YieldAndWaitForLoadBalancing()
  211. {
  212. System.CriticalSectionLock.Lock();
  213. if (SchedFlags != ThreadSchedState.Running)
  214. {
  215. System.CriticalSectionLock.Unlock();
  216. System.Scheduler.ContextSwitch();
  217. return;
  218. }
  219. int Core = CurrentCore;
  220. SchedulingData.TransferToCore(DynamicPriority, -1, this);
  221. KThread SelectedThread = null;
  222. if (!SchedulingData.ScheduledThreads(Core).Any())
  223. {
  224. foreach (KThread Thread in SchedulingData.SuggestedThreads(Core))
  225. {
  226. if (Thread.CurrentCore < 0)
  227. {
  228. continue;
  229. }
  230. KThread FirstCandidate = SchedulingData.ScheduledThreads(Thread.CurrentCore).FirstOrDefault();
  231. if (FirstCandidate == Thread)
  232. {
  233. continue;
  234. }
  235. if (FirstCandidate == null || FirstCandidate.DynamicPriority >= 2)
  236. {
  237. SchedulingData.TransferToCore(Thread.DynamicPriority, Core, Thread);
  238. SelectedThread = Thread;
  239. }
  240. break;
  241. }
  242. }
  243. if (SelectedThread != this)
  244. {
  245. Scheduler.ThreadReselectionRequested = true;
  246. }
  247. System.CriticalSectionLock.Unlock();
  248. System.Scheduler.ContextSwitch();
  249. }
  250. public void SetPriority(int Priority)
  251. {
  252. System.CriticalSectionLock.Lock();
  253. BasePriority = Priority;
  254. UpdatePriorityInheritance();
  255. System.CriticalSectionLock.Unlock();
  256. }
  257. public long SetActivity(bool Pause)
  258. {
  259. long Result = 0;
  260. System.CriticalSectionLock.Lock();
  261. ThreadSchedState LowNibble = SchedFlags & ThreadSchedState.LowNibbleMask;
  262. if (LowNibble != ThreadSchedState.Paused && LowNibble != ThreadSchedState.Running)
  263. {
  264. System.CriticalSectionLock.Unlock();
  265. return MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
  266. }
  267. System.CriticalSectionLock.Lock();
  268. if (!ShallBeTerminated && SchedFlags != ThreadSchedState.TerminationPending)
  269. {
  270. if (Pause)
  271. {
  272. //Pause, the force pause flag should be clear (thread is NOT paused).
  273. if ((ForcePauseFlags & ThreadSchedState.ForcePauseFlag) == 0)
  274. {
  275. ForcePauseFlags |= ThreadSchedState.ForcePauseFlag;
  276. CombineForcePauseFlags();
  277. }
  278. else
  279. {
  280. Result = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
  281. }
  282. }
  283. else
  284. {
  285. //Unpause, the force pause flag should be set (thread is paused).
  286. if ((ForcePauseFlags & ThreadSchedState.ForcePauseFlag) != 0)
  287. {
  288. ThreadSchedState OldForcePauseFlags = ForcePauseFlags;
  289. ForcePauseFlags &= ~ThreadSchedState.ForcePauseFlag;
  290. if ((OldForcePauseFlags & ~ThreadSchedState.ForcePauseFlag) == ThreadSchedState.None)
  291. {
  292. ThreadSchedState OldSchedFlags = SchedFlags;
  293. SchedFlags &= ThreadSchedState.LowNibbleMask;
  294. AdjustScheduling(OldSchedFlags);
  295. }
  296. }
  297. else
  298. {
  299. Result = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
  300. }
  301. }
  302. }
  303. System.CriticalSectionLock.Unlock();
  304. System.CriticalSectionLock.Unlock();
  305. return Result;
  306. }
  307. public void CancelSynchronization()
  308. {
  309. System.CriticalSectionLock.Lock();
  310. if ((SchedFlags & ThreadSchedState.LowNibbleMask) != ThreadSchedState.Paused || !WaitingSync)
  311. {
  312. SyncCancelled = true;
  313. }
  314. else if (WithholderNode != null)
  315. {
  316. System.Withholders.Remove(WithholderNode);
  317. SetNewSchedFlags(ThreadSchedState.Running);
  318. WithholderNode = null;
  319. SyncCancelled = true;
  320. }
  321. else
  322. {
  323. SignaledObj = null;
  324. ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Cancelled);
  325. SetNewSchedFlags(ThreadSchedState.Running);
  326. SyncCancelled = false;
  327. }
  328. System.CriticalSectionLock.Unlock();
  329. }
  330. public long SetCoreAndAffinityMask(int NewCore, long NewAffinityMask)
  331. {
  332. System.CriticalSectionLock.Lock();
  333. bool UseOverride = AffinityOverrideCount != 0;
  334. //The value -3 is "do not change the preferred core".
  335. if (NewCore == -3)
  336. {
  337. NewCore = UseOverride ? PreferredCoreOverride : PreferredCore;
  338. if ((NewAffinityMask & (1 << NewCore)) == 0)
  339. {
  340. System.CriticalSectionLock.Unlock();
  341. return MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue);
  342. }
  343. }
  344. if (UseOverride)
  345. {
  346. PreferredCoreOverride = NewCore;
  347. AffinityMaskOverride = NewAffinityMask;
  348. }
  349. else
  350. {
  351. long OldAffinityMask = AffinityMask;
  352. PreferredCore = NewCore;
  353. AffinityMask = NewAffinityMask;
  354. if (OldAffinityMask != NewAffinityMask)
  355. {
  356. int OldCore = CurrentCore;
  357. if (CurrentCore >= 0 && ((AffinityMask >> CurrentCore) & 1) == 0)
  358. {
  359. if (PreferredCore < 0)
  360. {
  361. CurrentCore = HighestSetCore(AffinityMask);
  362. }
  363. else
  364. {
  365. CurrentCore = PreferredCore;
  366. }
  367. }
  368. AdjustSchedulingForNewAffinity(OldAffinityMask, OldCore);
  369. }
  370. }
  371. System.CriticalSectionLock.Unlock();
  372. return 0;
  373. }
  374. private static int HighestSetCore(long Mask)
  375. {
  376. for (int Core = KScheduler.CpuCoresCount - 1; Core >= 0; Core--)
  377. {
  378. if (((Mask >> Core) & 1) != 0)
  379. {
  380. return Core;
  381. }
  382. }
  383. return -1;
  384. }
  385. private void CombineForcePauseFlags()
  386. {
  387. ThreadSchedState OldFlags = SchedFlags;
  388. ThreadSchedState LowNibble = SchedFlags & ThreadSchedState.LowNibbleMask;
  389. SchedFlags = LowNibble | ForcePauseFlags;
  390. AdjustScheduling(OldFlags);
  391. }
  392. private void SetNewSchedFlags(ThreadSchedState NewFlags)
  393. {
  394. System.CriticalSectionLock.Lock();
  395. ThreadSchedState OldFlags = SchedFlags;
  396. SchedFlags = (OldFlags & ThreadSchedState.HighNibbleMask) | NewFlags;
  397. if ((OldFlags & ThreadSchedState.LowNibbleMask) != NewFlags)
  398. {
  399. AdjustScheduling(OldFlags);
  400. }
  401. System.CriticalSectionLock.Unlock();
  402. }
  403. public void ReleaseAndResume()
  404. {
  405. System.CriticalSectionLock.Lock();
  406. if ((SchedFlags & ThreadSchedState.LowNibbleMask) == ThreadSchedState.Paused)
  407. {
  408. if (WithholderNode != null)
  409. {
  410. System.Withholders.Remove(WithholderNode);
  411. SetNewSchedFlags(ThreadSchedState.Running);
  412. WithholderNode = null;
  413. }
  414. else
  415. {
  416. SetNewSchedFlags(ThreadSchedState.Running);
  417. }
  418. }
  419. System.CriticalSectionLock.Unlock();
  420. }
  421. public void Reschedule(ThreadSchedState NewFlags)
  422. {
  423. System.CriticalSectionLock.Lock();
  424. ThreadSchedState OldFlags = SchedFlags;
  425. SchedFlags = (OldFlags & ThreadSchedState.HighNibbleMask) |
  426. (NewFlags & ThreadSchedState.LowNibbleMask);
  427. AdjustScheduling(OldFlags);
  428. System.CriticalSectionLock.Unlock();
  429. }
  430. public void AddMutexWaiter(KThread Requester)
  431. {
  432. AddToMutexWaitersList(Requester);
  433. Requester.MutexOwner = this;
  434. UpdatePriorityInheritance();
  435. }
  436. public void RemoveMutexWaiter(KThread Thread)
  437. {
  438. if (Thread.MutexWaiterNode?.List != null)
  439. {
  440. MutexWaiters.Remove(Thread.MutexWaiterNode);
  441. }
  442. Thread.MutexOwner = null;
  443. UpdatePriorityInheritance();
  444. }
  445. public KThread RelinquishMutex(long MutexAddress, out int Count)
  446. {
  447. Count = 0;
  448. if (MutexWaiters.First == null)
  449. {
  450. return null;
  451. }
  452. KThread NewMutexOwner = null;
  453. LinkedListNode<KThread> CurrentNode = MutexWaiters.First;
  454. do
  455. {
  456. //Skip all threads that are not waiting for this mutex.
  457. while (CurrentNode != null && CurrentNode.Value.MutexAddress != MutexAddress)
  458. {
  459. CurrentNode = CurrentNode.Next;
  460. }
  461. if (CurrentNode == null)
  462. {
  463. break;
  464. }
  465. LinkedListNode<KThread> NextNode = CurrentNode.Next;
  466. MutexWaiters.Remove(CurrentNode);
  467. CurrentNode.Value.MutexOwner = NewMutexOwner;
  468. if (NewMutexOwner != null)
  469. {
  470. //New owner was already selected, re-insert on new owner list.
  471. NewMutexOwner.AddToMutexWaitersList(CurrentNode.Value);
  472. }
  473. else
  474. {
  475. //New owner not selected yet, use current thread.
  476. NewMutexOwner = CurrentNode.Value;
  477. }
  478. Count++;
  479. CurrentNode = NextNode;
  480. }
  481. while (CurrentNode != null);
  482. if (NewMutexOwner != null)
  483. {
  484. UpdatePriorityInheritance();
  485. NewMutexOwner.UpdatePriorityInheritance();
  486. }
  487. return NewMutexOwner;
  488. }
  489. private void UpdatePriorityInheritance()
  490. {
  491. //If any of the threads waiting for the mutex has
  492. //higher priority than the current thread, then
  493. //the current thread inherits that priority.
  494. int HighestPriority = BasePriority;
  495. if (MutexWaiters.First != null)
  496. {
  497. int WaitingDynamicPriority = MutexWaiters.First.Value.DynamicPriority;
  498. if (WaitingDynamicPriority < HighestPriority)
  499. {
  500. HighestPriority = WaitingDynamicPriority;
  501. }
  502. }
  503. if (HighestPriority != DynamicPriority)
  504. {
  505. int OldPriority = DynamicPriority;
  506. DynamicPriority = HighestPriority;
  507. AdjustSchedulingForNewPriority(OldPriority);
  508. if (MutexOwner != null)
  509. {
  510. //Remove and re-insert to ensure proper sorting based on new priority.
  511. MutexOwner.MutexWaiters.Remove(MutexWaiterNode);
  512. MutexOwner.AddToMutexWaitersList(this);
  513. MutexOwner.UpdatePriorityInheritance();
  514. }
  515. }
  516. }
  517. private void AddToMutexWaitersList(KThread Thread)
  518. {
  519. LinkedListNode<KThread> NextPrio = MutexWaiters.First;
  520. int CurrentPriority = Thread.DynamicPriority;
  521. while (NextPrio != null && NextPrio.Value.DynamicPriority <= CurrentPriority)
  522. {
  523. NextPrio = NextPrio.Next;
  524. }
  525. if (NextPrio != null)
  526. {
  527. Thread.MutexWaiterNode = MutexWaiters.AddBefore(NextPrio, Thread);
  528. }
  529. else
  530. {
  531. Thread.MutexWaiterNode = MutexWaiters.AddLast(Thread);
  532. }
  533. }
  534. private void AdjustScheduling(ThreadSchedState OldFlags)
  535. {
  536. if (OldFlags == SchedFlags)
  537. {
  538. return;
  539. }
  540. if (OldFlags == ThreadSchedState.Running)
  541. {
  542. //Was running, now it's stopped.
  543. if (CurrentCore >= 0)
  544. {
  545. SchedulingData.Unschedule(DynamicPriority, CurrentCore, this);
  546. }
  547. for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
  548. {
  549. if (Core != CurrentCore && ((AffinityMask >> Core) & 1) != 0)
  550. {
  551. SchedulingData.Unsuggest(DynamicPriority, Core, this);
  552. }
  553. }
  554. }
  555. else if (SchedFlags == ThreadSchedState.Running)
  556. {
  557. //Was stopped, now it's running.
  558. if (CurrentCore >= 0)
  559. {
  560. SchedulingData.Schedule(DynamicPriority, CurrentCore, this);
  561. }
  562. for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
  563. {
  564. if (Core != CurrentCore && ((AffinityMask >> Core) & 1) != 0)
  565. {
  566. SchedulingData.Suggest(DynamicPriority, Core, this);
  567. }
  568. }
  569. }
  570. Scheduler.ThreadReselectionRequested = true;
  571. }
  572. private void AdjustSchedulingForNewPriority(int OldPriority)
  573. {
  574. if (SchedFlags != ThreadSchedState.Running)
  575. {
  576. return;
  577. }
  578. //Remove thread from the old priority queues.
  579. if (CurrentCore >= 0)
  580. {
  581. SchedulingData.Unschedule(OldPriority, CurrentCore, this);
  582. }
  583. for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
  584. {
  585. if (Core != CurrentCore && ((AffinityMask >> Core) & 1) != 0)
  586. {
  587. SchedulingData.Unsuggest(OldPriority, Core, this);
  588. }
  589. }
  590. //Add thread to the new priority queues.
  591. KThread CurrentThread = Scheduler.GetCurrentThread();
  592. if (CurrentCore >= 0)
  593. {
  594. if (CurrentThread == this)
  595. {
  596. SchedulingData.SchedulePrepend(DynamicPriority, CurrentCore, this);
  597. }
  598. else
  599. {
  600. SchedulingData.Schedule(DynamicPriority, CurrentCore, this);
  601. }
  602. }
  603. for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
  604. {
  605. if (Core != CurrentCore && ((AffinityMask >> Core) & 1) != 0)
  606. {
  607. SchedulingData.Suggest(DynamicPriority, Core, this);
  608. }
  609. }
  610. Scheduler.ThreadReselectionRequested = true;
  611. }
  612. private void AdjustSchedulingForNewAffinity(long OldAffinityMask, int OldCore)
  613. {
  614. if (SchedFlags != ThreadSchedState.Running || DynamicPriority >= KScheduler.PrioritiesCount)
  615. {
  616. return;
  617. }
  618. //Remove from old queues.
  619. for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
  620. {
  621. if (((OldAffinityMask >> Core) & 1) != 0)
  622. {
  623. if (Core == OldCore)
  624. {
  625. SchedulingData.Unschedule(DynamicPriority, Core, this);
  626. }
  627. else
  628. {
  629. SchedulingData.Unsuggest(DynamicPriority, Core, this);
  630. }
  631. }
  632. }
  633. //Insert on new queues.
  634. for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
  635. {
  636. if (((AffinityMask >> Core) & 1) != 0)
  637. {
  638. if (Core == CurrentCore)
  639. {
  640. SchedulingData.Schedule(DynamicPriority, Core, this);
  641. }
  642. else
  643. {
  644. SchedulingData.Suggest(DynamicPriority, Core, this);
  645. }
  646. }
  647. }
  648. Scheduler.ThreadReselectionRequested = true;
  649. }
  650. public override bool IsSignaled()
  651. {
  652. return HasExited;
  653. }
  654. public void ClearExclusive()
  655. {
  656. Owner.Memory.ClearExclusive(CurrentCore);
  657. }
  658. public void TimeUp()
  659. {
  660. System.CriticalSectionLock.Lock();
  661. SetNewSchedFlags(ThreadSchedState.Running);
  662. System.CriticalSectionLock.Unlock();
  663. }
  664. }
  665. }