k_thread.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <atomic>
  6. #include <condition_variable>
  7. #include <mutex>
  8. #include <span>
  9. #include <string>
  10. #include <utility>
  11. #include <vector>
  12. #include <boost/intrusive/list.hpp>
  13. #include "common/common_types.h"
  14. #include "common/intrusive_red_black_tree.h"
  15. #include "common/spin_lock.h"
  16. #include "core/arm/arm_interface.h"
  17. #include "core/hle/kernel/k_affinity_mask.h"
  18. #include "core/hle/kernel/k_light_lock.h"
  19. #include "core/hle/kernel/k_spin_lock.h"
  20. #include "core/hle/kernel/k_synchronization_object.h"
  21. #include "core/hle/kernel/k_worker_task.h"
  22. #include "core/hle/kernel/slab_helpers.h"
  23. #include "core/hle/kernel/svc_common.h"
  24. #include "core/hle/kernel/svc_types.h"
  25. #include "core/hle/result.h"
  26. namespace Common {
  27. class Fiber;
  28. }
  29. namespace Core {
  30. class ARM_Interface;
  31. class System;
  32. } // namespace Core
  33. namespace Kernel {
  34. class GlobalSchedulerContext;
  35. class KernelCore;
  36. class KProcess;
  37. class KScheduler;
  38. class KThreadQueue;
  39. using KThreadFunction = VAddr;
  40. enum class ThreadType : u32 {
  41. Main = 0,
  42. Kernel = 1,
  43. HighPriority = 2,
  44. User = 3,
  45. Dummy = 100, // Special thread type for emulation purposes only
  46. };
  47. DECLARE_ENUM_FLAG_OPERATORS(ThreadType);
  48. enum class SuspendType : u32 {
  49. Process = 0,
  50. Thread = 1,
  51. Debug = 2,
  52. Backtrace = 3,
  53. Init = 4,
  54. Count,
  55. };
  56. enum class ThreadState : u16 {
  57. Initialized = 0,
  58. Waiting = 1,
  59. Runnable = 2,
  60. Terminated = 3,
  61. SuspendShift = 4,
  62. Mask = (1 << SuspendShift) - 1,
  63. ProcessSuspended = (1 << (0 + SuspendShift)),
  64. ThreadSuspended = (1 << (1 + SuspendShift)),
  65. DebugSuspended = (1 << (2 + SuspendShift)),
  66. BacktraceSuspended = (1 << (3 + SuspendShift)),
  67. InitSuspended = (1 << (4 + SuspendShift)),
  68. SuspendFlagMask = ((1 << 5) - 1) << SuspendShift,
  69. };
  70. DECLARE_ENUM_FLAG_OPERATORS(ThreadState);
  71. enum class DpcFlag : u32 {
  72. Terminating = (1 << 0),
  73. Terminated = (1 << 1),
  74. };
  75. enum class ThreadWaitReasonForDebugging : u32 {
  76. None, ///< Thread is not waiting
  77. Sleep, ///< Thread is waiting due to a SleepThread SVC
  78. IPC, ///< Thread is waiting for the reply from an IPC request
  79. Synchronization, ///< Thread is waiting due to a WaitSynchronization SVC
  80. ConditionVar, ///< Thread is waiting due to a WaitProcessWideKey SVC
  81. Arbitration, ///< Thread is waiting due to a SignalToAddress/WaitForAddress SVC
  82. Suspended, ///< Thread is waiting due to process suspension
  83. };
  84. enum class StepState : u32 {
  85. NotStepping, ///< Thread is not currently stepping
  86. StepPending, ///< Thread will step when next scheduled
  87. StepPerformed, ///< Thread has stepped, waiting to be scheduled again
  88. };
  89. [[nodiscard]] KThread* GetCurrentThreadPointer(KernelCore& kernel);
  90. [[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel);
  91. [[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
  92. class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,
  93. public boost::intrusive::list_base_hook<> {
  94. KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject);
  95. private:
  96. friend class KScheduler;
  97. friend class KProcess;
  98. public:
  99. static constexpr s32 DefaultThreadPriority = 44;
  100. static constexpr s32 IdleThreadPriority = Svc::LowestThreadPriority + 1;
  101. static constexpr s32 DummyThreadPriority = Svc::LowestThreadPriority + 2;
  102. explicit KThread(KernelCore& kernel_);
  103. ~KThread() override;
  104. public:
  105. using ThreadContext32 = Core::ARM_Interface::ThreadContext32;
  106. using ThreadContext64 = Core::ARM_Interface::ThreadContext64;
  107. using WaiterList = boost::intrusive::list<KThread>;
  108. void SetName(std::string new_name) {
  109. name = std::move(new_name);
  110. }
  111. /**
  112. * Gets the thread's current priority
  113. * @return The current thread's priority
  114. */
  115. [[nodiscard]] s32 GetPriority() const {
  116. return priority;
  117. }
  118. /**
  119. * Sets the thread's current priority.
  120. * @param priority The new priority.
  121. */
  122. void SetPriority(s32 value) {
  123. priority = value;
  124. }
  125. /**
  126. * Gets the thread's nominal priority.
  127. * @return The current thread's nominal priority.
  128. */
  129. [[nodiscard]] s32 GetBasePriority() const {
  130. return base_priority;
  131. }
  132. /**
  133. * Gets the thread's thread ID
  134. * @return The thread's ID
  135. */
  136. [[nodiscard]] u64 GetThreadID() const {
  137. return thread_id;
  138. }
  139. void ContinueIfHasKernelWaiters() {
  140. if (GetNumKernelWaiters() > 0) {
  141. Continue();
  142. }
  143. }
  144. void SetBasePriority(s32 value);
  145. [[nodiscard]] ResultCode Run();
  146. void Exit();
  147. [[nodiscard]] u32 GetSuspendFlags() const {
  148. return suspend_allowed_flags & suspend_request_flags;
  149. }
  150. [[nodiscard]] bool IsSuspended() const {
  151. return GetSuspendFlags() != 0;
  152. }
  153. [[nodiscard]] bool IsSuspendRequested(SuspendType type) const {
  154. return (suspend_request_flags &
  155. (1u << (static_cast<u32>(ThreadState::SuspendShift) + static_cast<u32>(type)))) !=
  156. 0;
  157. }
  158. [[nodiscard]] bool IsSuspendRequested() const {
  159. return suspend_request_flags != 0;
  160. }
  161. void RequestSuspend(SuspendType type);
  162. void Resume(SuspendType type);
  163. void TrySuspend();
  164. void UpdateState();
  165. void Continue();
  166. constexpr void SetSyncedIndex(s32 index) {
  167. synced_index = index;
  168. }
  169. [[nodiscard]] constexpr s32 GetSyncedIndex() const {
  170. return synced_index;
  171. }
  172. constexpr void SetWaitResult(ResultCode wait_res) {
  173. wait_result = wait_res;
  174. }
  175. [[nodiscard]] constexpr ResultCode GetWaitResult() const {
  176. return wait_result;
  177. }
  178. /*
  179. * Returns the Thread Local Storage address of the current thread
  180. * @returns VAddr of the thread's TLS
  181. */
  182. [[nodiscard]] VAddr GetTLSAddress() const {
  183. return tls_address;
  184. }
  185. /*
  186. * Returns the value of the TPIDR_EL0 Read/Write system register for this thread.
  187. * @returns The value of the TPIDR_EL0 register.
  188. */
  189. [[nodiscard]] u64 GetTPIDR_EL0() const {
  190. return thread_context_64.tpidr;
  191. }
  192. /// Sets the value of the TPIDR_EL0 Read/Write system register for this thread.
  193. void SetTPIDR_EL0(u64 value) {
  194. thread_context_64.tpidr = value;
  195. thread_context_32.tpidr = static_cast<u32>(value);
  196. }
  197. [[nodiscard]] ThreadContext32& GetContext32() {
  198. return thread_context_32;
  199. }
  200. [[nodiscard]] const ThreadContext32& GetContext32() const {
  201. return thread_context_32;
  202. }
  203. [[nodiscard]] ThreadContext64& GetContext64() {
  204. return thread_context_64;
  205. }
  206. [[nodiscard]] const ThreadContext64& GetContext64() const {
  207. return thread_context_64;
  208. }
  209. [[nodiscard]] std::shared_ptr<Common::Fiber>& GetHostContext();
  210. [[nodiscard]] ThreadState GetState() const {
  211. return thread_state.load(std::memory_order_relaxed) & ThreadState::Mask;
  212. }
  213. [[nodiscard]] ThreadState GetRawState() const {
  214. return thread_state.load(std::memory_order_relaxed);
  215. }
  216. void SetState(ThreadState state);
  217. [[nodiscard]] StepState GetStepState() const {
  218. return step_state;
  219. }
  220. void SetStepState(StepState state) {
  221. step_state = state;
  222. }
  223. [[nodiscard]] s64 GetLastScheduledTick() const {
  224. return last_scheduled_tick;
  225. }
  226. void SetLastScheduledTick(s64 tick) {
  227. last_scheduled_tick = tick;
  228. }
  229. void AddCpuTime([[maybe_unused]] s32 core_id_, s64 amount) {
  230. cpu_time += amount;
  231. // TODO(bunnei): Debug kernels track per-core tick counts. Should we?
  232. }
  233. [[nodiscard]] s64 GetCpuTime() const {
  234. return cpu_time;
  235. }
  236. [[nodiscard]] s32 GetActiveCore() const {
  237. return core_id;
  238. }
  239. void SetActiveCore(s32 core) {
  240. core_id = core;
  241. }
  242. [[nodiscard]] s32 GetCurrentCore() const {
  243. return current_core_id;
  244. }
  245. void SetCurrentCore(s32 core) {
  246. current_core_id = core;
  247. }
  248. [[nodiscard]] KProcess* GetOwnerProcess() {
  249. return parent;
  250. }
  251. [[nodiscard]] const KProcess* GetOwnerProcess() const {
  252. return parent;
  253. }
  254. [[nodiscard]] bool IsUserThread() const {
  255. return parent != nullptr;
  256. }
  257. u16 GetUserDisableCount() const;
  258. void SetInterruptFlag();
  259. void ClearInterruptFlag();
  260. [[nodiscard]] KThread* GetLockOwner() const {
  261. return lock_owner;
  262. }
  263. void SetLockOwner(KThread* owner) {
  264. lock_owner = owner;
  265. }
  266. [[nodiscard]] const KAffinityMask& GetAffinityMask() const {
  267. return physical_affinity_mask;
  268. }
  269. [[nodiscard]] ResultCode GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask);
  270. [[nodiscard]] ResultCode GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask);
  271. [[nodiscard]] ResultCode SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask);
  272. [[nodiscard]] ResultCode SetActivity(Svc::ThreadActivity activity);
  273. [[nodiscard]] ResultCode Sleep(s64 timeout);
  274. [[nodiscard]] s64 GetYieldScheduleCount() const {
  275. return schedule_count;
  276. }
  277. void SetYieldScheduleCount(s64 count) {
  278. schedule_count = count;
  279. }
  280. void WaitCancel();
  281. [[nodiscard]] bool IsWaitCancelled() const {
  282. return wait_cancelled;
  283. }
  284. void ClearWaitCancelled() {
  285. wait_cancelled = false;
  286. }
  287. [[nodiscard]] bool IsCancellable() const {
  288. return cancellable;
  289. }
  290. void SetCancellable() {
  291. cancellable = true;
  292. }
  293. void ClearCancellable() {
  294. cancellable = false;
  295. }
  296. [[nodiscard]] bool IsTerminationRequested() const {
  297. return termination_requested || GetRawState() == ThreadState::Terminated;
  298. }
  299. [[nodiscard]] u64 GetId() const override {
  300. return this->GetThreadID();
  301. }
  302. [[nodiscard]] bool IsInitialized() const override {
  303. return initialized;
  304. }
  305. [[nodiscard]] uintptr_t GetPostDestroyArgument() const override {
  306. return reinterpret_cast<uintptr_t>(parent) | (resource_limit_release_hint ? 1 : 0);
  307. }
  308. void Finalize() override;
  309. [[nodiscard]] bool IsSignaled() const override;
  310. void OnTimer();
  311. void DoWorkerTaskImpl();
  312. static void PostDestroy(uintptr_t arg);
  313. [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread);
  314. [[nodiscard]] static ResultCode InitializeIdleThread(Core::System& system, KThread* thread,
  315. s32 virt_core);
  316. [[nodiscard]] static ResultCode InitializeHighPriorityThread(Core::System& system,
  317. KThread* thread,
  318. KThreadFunction func,
  319. uintptr_t arg, s32 virt_core);
  320. [[nodiscard]] static ResultCode InitializeUserThread(Core::System& system, KThread* thread,
  321. KThreadFunction func, uintptr_t arg,
  322. VAddr user_stack_top, s32 prio,
  323. s32 virt_core, KProcess* owner);
  324. public:
  325. struct StackParameters {
  326. u8 svc_permission[0x10];
  327. std::atomic<u8> dpc_flags;
  328. u8 current_svc_id;
  329. bool is_calling_svc;
  330. bool is_in_exception_handler;
  331. bool is_pinned;
  332. s32 disable_count;
  333. KThread* cur_thread;
  334. };
  335. [[nodiscard]] StackParameters& GetStackParameters() {
  336. return stack_parameters;
  337. }
  338. [[nodiscard]] const StackParameters& GetStackParameters() const {
  339. return stack_parameters;
  340. }
  341. class QueueEntry {
  342. public:
  343. constexpr QueueEntry() = default;
  344. constexpr void Initialize() {
  345. prev = nullptr;
  346. next = nullptr;
  347. }
  348. constexpr KThread* GetPrev() const {
  349. return prev;
  350. }
  351. constexpr KThread* GetNext() const {
  352. return next;
  353. }
  354. constexpr void SetPrev(KThread* thread) {
  355. prev = thread;
  356. }
  357. constexpr void SetNext(KThread* thread) {
  358. next = thread;
  359. }
  360. private:
  361. KThread* prev{};
  362. KThread* next{};
  363. };
  364. [[nodiscard]] QueueEntry& GetPriorityQueueEntry(s32 core) {
  365. return per_core_priority_queue_entry[core];
  366. }
  367. [[nodiscard]] const QueueEntry& GetPriorityQueueEntry(s32 core) const {
  368. return per_core_priority_queue_entry[core];
  369. }
  370. [[nodiscard]] bool IsKernelThread() const {
  371. return GetActiveCore() == 3;
  372. }
  373. [[nodiscard]] bool IsDispatchTrackingDisabled() const {
  374. return is_single_core || IsKernelThread();
  375. }
  376. [[nodiscard]] s32 GetDisableDispatchCount() const {
  377. if (IsDispatchTrackingDisabled()) {
  378. // TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch.
  379. return 1;
  380. }
  381. return this->GetStackParameters().disable_count;
  382. }
  383. void DisableDispatch() {
  384. if (IsDispatchTrackingDisabled()) {
  385. // TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch.
  386. return;
  387. }
  388. ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() >= 0);
  389. this->GetStackParameters().disable_count++;
  390. }
  391. void EnableDispatch() {
  392. if (IsDispatchTrackingDisabled()) {
  393. // TODO(bunnei): Until kernel threads are emulated, we cannot enable/disable dispatch.
  394. return;
  395. }
  396. ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() > 0);
  397. this->GetStackParameters().disable_count--;
  398. }
  399. void Pin(s32 current_core);
  400. void Unpin();
  401. void SetInExceptionHandler() {
  402. this->GetStackParameters().is_in_exception_handler = true;
  403. }
  404. void ClearInExceptionHandler() {
  405. this->GetStackParameters().is_in_exception_handler = false;
  406. }
  407. [[nodiscard]] bool IsInExceptionHandler() const {
  408. return this->GetStackParameters().is_in_exception_handler;
  409. }
  410. void SetIsCallingSvc() {
  411. this->GetStackParameters().is_calling_svc = true;
  412. }
  413. void ClearIsCallingSvc() {
  414. this->GetStackParameters().is_calling_svc = false;
  415. }
  416. [[nodiscard]] bool IsCallingSvc() const {
  417. return this->GetStackParameters().is_calling_svc;
  418. }
  419. [[nodiscard]] u8 GetSvcId() const {
  420. return this->GetStackParameters().current_svc_id;
  421. }
  422. void RegisterDpc(DpcFlag flag) {
  423. this->GetStackParameters().dpc_flags |= static_cast<u8>(flag);
  424. }
  425. void ClearDpc(DpcFlag flag) {
  426. this->GetStackParameters().dpc_flags &= ~static_cast<u8>(flag);
  427. }
  428. [[nodiscard]] u8 GetDpc() const {
  429. return this->GetStackParameters().dpc_flags;
  430. }
  431. [[nodiscard]] bool HasDpc() const {
  432. return this->GetDpc() != 0;
  433. }
  434. void SetWaitReasonForDebugging(ThreadWaitReasonForDebugging reason) {
  435. wait_reason_for_debugging = reason;
  436. }
  437. [[nodiscard]] ThreadWaitReasonForDebugging GetWaitReasonForDebugging() const {
  438. return wait_reason_for_debugging;
  439. }
  440. [[nodiscard]] ThreadType GetThreadType() const {
  441. return thread_type;
  442. }
  443. [[nodiscard]] bool IsDummyThread() const {
  444. return GetThreadType() == ThreadType::Dummy;
  445. }
  446. void SetWaitObjectsForDebugging(const std::span<KSynchronizationObject*>& objects) {
  447. wait_objects_for_debugging.clear();
  448. wait_objects_for_debugging.reserve(objects.size());
  449. for (const auto& object : objects) {
  450. wait_objects_for_debugging.emplace_back(object);
  451. }
  452. }
  453. [[nodiscard]] const std::vector<KSynchronizationObject*>& GetWaitObjectsForDebugging() const {
  454. return wait_objects_for_debugging;
  455. }
  456. void SetMutexWaitAddressForDebugging(VAddr address) {
  457. mutex_wait_address_for_debugging = address;
  458. }
  459. [[nodiscard]] VAddr GetMutexWaitAddressForDebugging() const {
  460. return mutex_wait_address_for_debugging;
  461. }
  462. [[nodiscard]] s32 GetIdealCoreForDebugging() const {
  463. return virtual_ideal_core_id;
  464. }
  465. void AddWaiter(KThread* thread);
  466. void RemoveWaiter(KThread* thread);
  467. [[nodiscard]] ResultCode GetThreadContext3(std::vector<u8>& out);
  468. [[nodiscard]] KThread* RemoveWaiterByKey(s32* out_num_waiters, VAddr key);
  469. [[nodiscard]] VAddr GetAddressKey() const {
  470. return address_key;
  471. }
  472. [[nodiscard]] u32 GetAddressKeyValue() const {
  473. return address_key_value;
  474. }
  475. void SetAddressKey(VAddr key) {
  476. address_key = key;
  477. }
  478. void SetAddressKey(VAddr key, u32 val) {
  479. address_key = key;
  480. address_key_value = val;
  481. }
  482. void ClearWaitQueue() {
  483. wait_queue = nullptr;
  484. }
  485. void BeginWait(KThreadQueue* queue);
  486. void NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_);
  487. void EndWait(ResultCode wait_result_);
  488. void CancelWait(ResultCode wait_result_, bool cancel_timer_task);
  489. [[nodiscard]] bool HasWaiters() const {
  490. return !waiter_list.empty();
  491. }
  492. [[nodiscard]] s32 GetNumKernelWaiters() const {
  493. return num_kernel_waiters;
  494. }
  495. [[nodiscard]] u64 GetConditionVariableKey() const {
  496. return condvar_key;
  497. }
  498. [[nodiscard]] u64 GetAddressArbiterKey() const {
  499. return condvar_key;
  500. }
  501. // Dummy threads (used for HLE host threads) cannot wait based on the guest scheduler, and
  502. // therefore will not block on guest kernel synchronization primitives. These methods handle
  503. // blocking as needed.
  504. void IfDummyThreadTryWait();
  505. void IfDummyThreadEndWait();
  506. [[nodiscard]] uintptr_t GetArgument() const {
  507. return argument;
  508. }
  509. [[nodiscard]] VAddr GetUserStackTop() const {
  510. return stack_top;
  511. }
  512. private:
  513. static constexpr size_t PriorityInheritanceCountMax = 10;
  514. union SyncObjectBuffer {
  515. std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> sync_objects{};
  516. std::array<Handle,
  517. Svc::ArgumentHandleCountMax*(sizeof(KSynchronizationObject*) / sizeof(Handle))>
  518. handles;
  519. constexpr SyncObjectBuffer() {}
  520. };
  521. static_assert(sizeof(SyncObjectBuffer::sync_objects) == sizeof(SyncObjectBuffer::handles));
  522. struct ConditionVariableComparator {
  523. struct RedBlackKeyType {
  524. u64 cv_key{};
  525. s32 priority{};
  526. [[nodiscard]] constexpr u64 GetConditionVariableKey() const {
  527. return cv_key;
  528. }
  529. [[nodiscard]] constexpr s32 GetPriority() const {
  530. return priority;
  531. }
  532. };
  533. template <typename T>
  534. requires(
  535. std::same_as<T, KThread> ||
  536. std::same_as<T, RedBlackKeyType>) static constexpr int Compare(const T& lhs,
  537. const KThread& rhs) {
  538. const u64 l_key = lhs.GetConditionVariableKey();
  539. const u64 r_key = rhs.GetConditionVariableKey();
  540. if (l_key < r_key) {
  541. // Sort first by key
  542. return -1;
  543. } else if (l_key == r_key && lhs.GetPriority() < rhs.GetPriority()) {
  544. // And then by priority.
  545. return -1;
  546. } else {
  547. return 1;
  548. }
  549. }
  550. };
  551. void AddWaiterImpl(KThread* thread);
  552. void RemoveWaiterImpl(KThread* thread);
  553. void StartTermination();
  554. void FinishTermination();
  555. [[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top,
  556. s32 prio, s32 virt_core, KProcess* owner, ThreadType type);
  557. [[nodiscard]] static ResultCode InitializeThread(KThread* thread, KThreadFunction func,
  558. uintptr_t arg, VAddr user_stack_top, s32 prio,
  559. s32 core, KProcess* owner, ThreadType type,
  560. std::function<void(void*)>&& init_func,
  561. void* init_func_parameter);
  562. static void RestorePriority(KernelCore& kernel_ctx, KThread* thread);
  563. // For core KThread implementation
  564. ThreadContext32 thread_context_32{};
  565. ThreadContext64 thread_context_64{};
  566. Common::IntrusiveRedBlackTreeNode condvar_arbiter_tree_node{};
  567. s32 priority{};
  568. using ConditionVariableThreadTreeTraits =
  569. Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<
  570. &KThread::condvar_arbiter_tree_node>;
  571. using ConditionVariableThreadTree =
  572. ConditionVariableThreadTreeTraits::TreeType<ConditionVariableComparator>;
  573. ConditionVariableThreadTree* condvar_tree{};
  574. u64 condvar_key{};
  575. u64 virtual_affinity_mask{};
  576. KAffinityMask physical_affinity_mask{};
  577. u64 thread_id{};
  578. std::atomic<s64> cpu_time{};
  579. VAddr address_key{};
  580. KProcess* parent{};
  581. VAddr kernel_stack_top{};
  582. u32* light_ipc_data{};
  583. VAddr tls_address{};
  584. KLightLock activity_pause_lock;
  585. s64 schedule_count{};
  586. s64 last_scheduled_tick{};
  587. std::array<QueueEntry, Core::Hardware::NUM_CPU_CORES> per_core_priority_queue_entry{};
  588. KThreadQueue* wait_queue{};
  589. WaiterList waiter_list{};
  590. WaiterList pinned_waiter_list{};
  591. KThread* lock_owner{};
  592. u32 address_key_value{};
  593. u32 suspend_request_flags{};
  594. u32 suspend_allowed_flags{};
  595. s32 synced_index{};
  596. ResultCode wait_result{ResultSuccess};
  597. s32 base_priority{};
  598. s32 physical_ideal_core_id{};
  599. s32 virtual_ideal_core_id{};
  600. s32 num_kernel_waiters{};
  601. s32 current_core_id{};
  602. s32 core_id{};
  603. KAffinityMask original_physical_affinity_mask{};
  604. s32 original_physical_ideal_core_id{};
  605. s32 num_core_migration_disables{};
  606. std::atomic<ThreadState> thread_state{};
  607. std::atomic<bool> termination_requested{};
  608. bool wait_cancelled{};
  609. bool cancellable{};
  610. bool signaled{};
  611. bool initialized{};
  612. bool debug_attached{};
  613. s8 priority_inheritance_count{};
  614. bool resource_limit_release_hint{};
  615. StackParameters stack_parameters{};
  616. Common::SpinLock context_guard{};
  617. // For emulation
  618. std::shared_ptr<Common::Fiber> host_context{};
  619. bool is_single_core{};
  620. ThreadType thread_type{};
  621. StepState step_state{};
  622. std::mutex dummy_wait_lock;
  623. std::condition_variable dummy_wait_cv;
  624. // For debugging
  625. std::vector<KSynchronizationObject*> wait_objects_for_debugging;
  626. VAddr mutex_wait_address_for_debugging{};
  627. ThreadWaitReasonForDebugging wait_reason_for_debugging{};
  628. uintptr_t argument;
  629. VAddr stack_top;
  630. public:
  631. using ConditionVariableThreadTreeType = ConditionVariableThreadTree;
  632. void SetConditionVariable(ConditionVariableThreadTree* tree, VAddr address, u64 cv_key,
  633. u32 value) {
  634. condvar_tree = tree;
  635. condvar_key = cv_key;
  636. address_key = address;
  637. address_key_value = value;
  638. }
  639. void ClearConditionVariable() {
  640. condvar_tree = nullptr;
  641. }
  642. [[nodiscard]] bool IsWaitingForConditionVariable() const {
  643. return condvar_tree != nullptr;
  644. }
  645. void SetAddressArbiter(ConditionVariableThreadTree* tree, u64 address) {
  646. condvar_tree = tree;
  647. condvar_key = address;
  648. }
  649. void ClearAddressArbiter() {
  650. condvar_tree = nullptr;
  651. }
  652. [[nodiscard]] bool IsWaitingForAddressArbiter() const {
  653. return condvar_tree != nullptr;
  654. }
  655. [[nodiscard]] ConditionVariableThreadTree* GetConditionVariableTree() const {
  656. return condvar_tree;
  657. }
  658. };
  659. class KScopedDisableDispatch {
  660. public:
  661. [[nodiscard]] explicit KScopedDisableDispatch(KernelCore& kernel_) : kernel{kernel_} {
  662. // If we are shutting down the kernel, none of this is relevant anymore.
  663. if (kernel.IsShuttingDown()) {
  664. return;
  665. }
  666. GetCurrentThread(kernel).DisableDispatch();
  667. }
  668. ~KScopedDisableDispatch();
  669. private:
  670. KernelCore& kernel;
  671. };
  672. } // namespace Kernel