| 
									
										
										
										
											2014-05-09 22:11:18 -04:00
										 |  |  | // Copyright 2014 Citra Emulator Project / PPSSPP Project
 | 
					
						
							| 
									
										
										
										
											2014-12-16 21:38:14 -08:00
										 |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							| 
									
										
										
										
											2014-11-19 08:49:13 +00:00
										 |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2014-05-09 22:11:18 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  | #include <array>
 | 
					
						
							| 
									
										
										
										
											2018-07-31 08:06:09 -04:00
										 |  |  | #include <functional>
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  | #include <span>
 | 
					
						
							| 
									
										
										
										
											2014-12-22 04:32:03 -02:00
										 |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2020-03-10 13:13:39 -04:00
										 |  |  | #include <utility>
 | 
					
						
							| 
									
										
										
										
											2014-12-22 04:32:03 -02:00
										 |  |  | #include <vector>
 | 
					
						
							| 
									
										
										
										
											2018-07-31 08:06:09 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  | #include <boost/intrusive/list.hpp>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-09 22:11:18 -04:00
										 |  |  | #include "common/common_types.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  | #include "common/intrusive_red_black_tree.h"
 | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  | #include "common/spin_lock.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-22 00:08:09 -05:00
										 |  |  | #include "core/arm/arm_interface.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-16 21:02:45 -08:00
										 |  |  | #include "core/hle/kernel/k_affinity_mask.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  | #include "core/hle/kernel/k_synchronization_object.h"
 | 
					
						
							| 
									
										
										
										
											2018-08-01 22:40:00 -04:00
										 |  |  | #include "core/hle/kernel/object.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  | #include "core/hle/kernel/svc_common.h"
 | 
					
						
							| 
									
										
										
										
											2014-10-23 01:20:01 -02:00
										 |  |  | #include "core/hle/result.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-09 22:11:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  | namespace Common { | 
					
						
							|  |  |  | class Fiber; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Core { | 
					
						
							| 
									
										
										
										
											2020-03-01 12:14:17 -04:00
										 |  |  | class ARM_Interface; | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  | class System; | 
					
						
							| 
									
										
										
										
											2020-03-03 13:37:11 -04:00
										 |  |  | } // namespace Core
 | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-13 15:57:45 -04:00
										 |  |  | namespace Kernel { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  | class GlobalSchedulerContext; | 
					
						
							| 
									
										
										
										
											2018-09-13 15:57:45 -04:00
										 |  |  | class KernelCore; | 
					
						
							|  |  |  | class Process; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  | class KScheduler; | 
					
						
							| 
									
										
										
										
											2018-09-13 15:57:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-27 00:26:09 +01:00
										 |  |  | enum ThreadPriority : u32 { | 
					
						
							| 
									
										
										
										
											2020-02-25 19:43:28 -04:00
										 |  |  |     THREADPRIO_HIGHEST = 0,            ///< Highest thread priority
 | 
					
						
							|  |  |  |     THREADPRIO_MAX_CORE_MIGRATION = 2, ///< Highest priority for a core migration
 | 
					
						
							|  |  |  |     THREADPRIO_USERLAND_MAX = 24,      ///< Highest thread priority for userland apps
 | 
					
						
							|  |  |  |     THREADPRIO_DEFAULT = 44,           ///< Default thread priority for userland apps
 | 
					
						
							|  |  |  |     THREADPRIO_LOWEST = 63,            ///< Lowest thread priority
 | 
					
						
							|  |  |  |     THREADPRIO_COUNT = 64,             ///< Total number of possible thread priorities.
 | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum ThreadType : u32 { | 
					
						
							|  |  |  |     THREADTYPE_USER = 0x1, | 
					
						
							|  |  |  |     THREADTYPE_KERNEL = 0x2, | 
					
						
							|  |  |  |     THREADTYPE_HLE = 0x4, | 
					
						
							|  |  |  |     THREADTYPE_IDLE = 0x8, | 
					
						
							|  |  |  |     THREADTYPE_SUSPEND = 0x10, | 
					
						
							| 
									
										
										
										
											2014-05-17 00:56:00 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 23:55:21 -04:00
										 |  |  | enum ThreadProcessorId : s32 { | 
					
						
							| 
									
										
										
										
											2019-04-15 20:17:15 -04:00
										 |  |  |     /// Indicates that no particular processor core is preferred.
 | 
					
						
							|  |  |  |     THREADPROCESSORID_DONT_CARE = -1, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Run thread on the ideal core specified by the process.
 | 
					
						
							|  |  |  |     THREADPROCESSORID_IDEAL = -2, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Indicates that the preferred processor ID shouldn't be updated in
 | 
					
						
							|  |  |  |     /// a core mask setting operation.
 | 
					
						
							|  |  |  |     THREADPROCESSORID_DONT_UPDATE = -3, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     THREADPROCESSORID_0 = 0,   ///< Run thread on core 0
 | 
					
						
							|  |  |  |     THREADPROCESSORID_1 = 1,   ///< Run thread on core 1
 | 
					
						
							|  |  |  |     THREADPROCESSORID_2 = 2,   ///< Run thread on core 2
 | 
					
						
							|  |  |  |     THREADPROCESSORID_3 = 3,   ///< Run thread on core 3
 | 
					
						
							|  |  |  |     THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this
 | 
					
						
							| 
									
										
										
										
											2018-01-10 00:58:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Allowed CPU mask
 | 
					
						
							|  |  |  |     THREADPROCESSORID_DEFAULT_MASK = (1 << THREADPROCESSORID_0) | (1 << THREADPROCESSORID_1) | | 
					
						
							|  |  |  |                                      (1 << THREADPROCESSORID_2) | (1 << THREADPROCESSORID_3) | 
					
						
							| 
									
										
										
										
											2014-05-17 00:56:00 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-28 13:16:43 -08:00
										 |  |  | enum class ThreadState : u16 { | 
					
						
							|  |  |  |     Initialized = 0, | 
					
						
							|  |  |  |     Waiting = 1, | 
					
						
							|  |  |  |     Runnable = 2, | 
					
						
							|  |  |  |     Terminated = 3, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SuspendShift = 4, | 
					
						
							|  |  |  |     Mask = (1 << SuspendShift) - 1, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ProcessSuspended = (1 << (0 + SuspendShift)), | 
					
						
							|  |  |  |     ThreadSuspended = (1 << (1 + SuspendShift)), | 
					
						
							|  |  |  |     DebugSuspended = (1 << (2 + SuspendShift)), | 
					
						
							|  |  |  |     BacktraceSuspended = (1 << (3 + SuspendShift)), | 
					
						
							|  |  |  |     InitSuspended = (1 << (4 + SuspendShift)), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SuspendFlagMask = ((1 << 5) - 1) << SuspendShift, | 
					
						
							| 
									
										
										
										
											2014-05-22 18:50:36 -04:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2020-12-28 13:16:43 -08:00
										 |  |  | DECLARE_ENUM_FLAG_OPERATORS(ThreadState); | 
					
						
							| 
									
										
										
										
											2014-05-22 18:50:36 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-28 11:53:32 -05:00
										 |  |  | enum class ThreadWakeupReason { | 
					
						
							|  |  |  |     Signal, // The thread was woken up by WakeupAllWaitingThreads due to an object signal.
 | 
					
						
							|  |  |  |     Timeout // The thread was woken up due to a wait timeout.
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:25:27 -05:00
										 |  |  | enum class ThreadActivity : u32 { | 
					
						
							|  |  |  |     Normal = 0, | 
					
						
							|  |  |  |     Paused = 1, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-12 10:13:25 -04:00
										 |  |  | enum class ThreadSchedFlags : u32 { | 
					
						
							| 
									
										
										
										
											2019-03-29 17:01:46 -04:00
										 |  |  |     ProcessPauseFlag = 1 << 4, | 
					
						
							|  |  |  |     ThreadPauseFlag = 1 << 5, | 
					
						
							|  |  |  |     ProcessDebugPauseFlag = 1 << 6, | 
					
						
							|  |  |  |     KernelInitPauseFlag = 1 << 8, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  | class Thread final : public KSynchronizationObject, public boost::intrusive::list_base_hook<> { | 
					
						
							|  |  |  |     friend class KScheduler; | 
					
						
							|  |  |  |     friend class Process; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-22 04:32:03 -02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2019-11-24 20:15:51 -05:00
										 |  |  |     explicit Thread(KernelCore& kernel); | 
					
						
							|  |  |  |     ~Thread() override; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     using MutexWaitingThreads = std::vector<std::shared_ptr<Thread>>; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-01 23:46:10 -05:00
										 |  |  |     using ThreadContext32 = Core::ARM_Interface::ThreadContext32; | 
					
						
							|  |  |  |     using ThreadContext64 = Core::ARM_Interface::ThreadContext64; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-25 19:43:28 -04:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * Creates and returns a new thread. The new thread is immediately scheduled | 
					
						
							|  |  |  |      * @param system The instance of the whole system | 
					
						
							|  |  |  |      * @param name The friendly name desired for the thread | 
					
						
							|  |  |  |      * @param entry_point The address at which the thread should start execution | 
					
						
							|  |  |  |      * @param priority The thread's priority | 
					
						
							|  |  |  |      * @param arg User data to pass to the thread | 
					
						
							|  |  |  |      * @param processor_id The ID(s) of the processors on which the thread is desired to be run | 
					
						
							|  |  |  |      * @param stack_top The address of the thread's stack top | 
					
						
							|  |  |  |      * @param owner_process The parent process for the thread, if null, it's a kernel thread | 
					
						
							|  |  |  |      * @return A shared pointer to the newly created thread | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     static ResultVal<std::shared_ptr<Thread>> Create(Core::System& system, ThreadType type_flags, | 
					
						
							|  |  |  |                                                      std::string name, VAddr entry_point, | 
					
						
							|  |  |  |                                                      u32 priority, u64 arg, s32 processor_id, | 
					
						
							|  |  |  |                                                      VAddr stack_top, Process* owner_process); | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-25 22:56:17 -08:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * Creates and returns a new thread. The new thread is immediately scheduled | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  |      * @param system The instance of the whole system | 
					
						
							| 
									
										
										
										
											2015-01-25 22:56:17 -08:00
										 |  |  |      * @param name The friendly name desired for the thread | 
					
						
							|  |  |  |      * @param entry_point The address at which the thread should start execution | 
					
						
							|  |  |  |      * @param priority The thread's priority | 
					
						
							|  |  |  |      * @param arg User data to pass to the thread | 
					
						
							|  |  |  |      * @param processor_id The ID(s) of the processors on which the thread is desired to be run | 
					
						
							|  |  |  |      * @param stack_top The address of the thread's stack top | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  |      * @param owner_process The parent process for the thread, if null, it's a kernel thread | 
					
						
							|  |  |  |      * @param thread_start_func The function where the host context will start. | 
					
						
							|  |  |  |      * @param thread_start_parameter The parameter which will passed to host context on init | 
					
						
							| 
									
										
										
										
											2015-01-25 22:56:17 -08:00
										 |  |  |      * @return A shared pointer to the newly created thread | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-02-25 19:43:28 -04:00
										 |  |  |     static ResultVal<std::shared_ptr<Thread>> Create(Core::System& system, ThreadType type_flags, | 
					
						
							|  |  |  |                                                      std::string name, VAddr entry_point, | 
					
						
							|  |  |  |                                                      u32 priority, u64 arg, s32 processor_id, | 
					
						
							|  |  |  |                                                      VAddr stack_top, Process* owner_process, | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  |                                                      std::function<void(void*)>&& thread_start_func, | 
					
						
							|  |  |  |                                                      void* thread_start_parameter); | 
					
						
							| 
									
										
										
										
											2014-12-22 11:07:22 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-18 09:38:01 +09:00
										 |  |  |     std::string GetName() const override { | 
					
						
							|  |  |  |         return name; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-15 15:54:25 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     void SetName(std::string new_name) { | 
					
						
							|  |  |  |         name = std::move(new_name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-18 09:38:01 +09:00
										 |  |  |     std::string GetTypeName() const override { | 
					
						
							|  |  |  |         return "Thread"; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-12-22 04:32:03 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-11 16:30:52 -04:00
										 |  |  |     static constexpr HandleType HANDLE_TYPE = HandleType::Thread; | 
					
						
							| 
									
										
										
										
											2016-09-18 09:38:01 +09:00
										 |  |  |     HandleType GetHandleType() const override { | 
					
						
							|  |  |  |         return HANDLE_TYPE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-12-22 04:32:03 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-25 22:56:17 -08:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * Gets the thread's current priority | 
					
						
							|  |  |  |      * @return The current thread's priority | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     [[nodiscard]] s32 GetPriority() const { | 
					
						
							| 
									
										
										
										
											2016-09-18 09:38:01 +09:00
										 |  |  |         return current_priority; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-25 22:56:17 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * Sets the thread's current priority. | 
					
						
							|  |  |  |      * @param priority The new priority. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     void SetPriority(s32 priority) { | 
					
						
							|  |  |  |         current_priority = priority; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * Gets the thread's nominal priority. | 
					
						
							|  |  |  |      * @return The current thread's nominal priority. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     [[nodiscard]] s32 GetBasePriority() const { | 
					
						
							|  |  |  |         return base_priority; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-25 22:56:17 -08:00
										 |  |  |     /**
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |      * Sets the thread's nominal priority. | 
					
						
							|  |  |  |      * @param priority The new priority. | 
					
						
							| 
									
										
										
										
											2015-01-25 22:56:17 -08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     void SetBasePriority(u32 priority); | 
					
						
							| 
									
										
										
										
											2018-04-20 20:15:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-05 23:03:01 -04:00
										 |  |  |     /// Changes the core that the thread is running or scheduled to run on.
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     [[nodiscard]] ResultCode SetCoreAndAffinityMask(s32 new_core, u64 new_affinity_mask); | 
					
						
							| 
									
										
										
										
											2018-05-05 23:03:01 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-25 22:56:17 -08:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * Gets the thread's thread ID | 
					
						
							|  |  |  |      * @return The thread's ID | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     [[nodiscard]] u64 GetThreadID() const { | 
					
						
							| 
									
										
										
										
											2016-09-18 09:38:01 +09:00
										 |  |  |         return thread_id; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-25 20:34:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 07:08:12 -04:00
										 |  |  |     /// Resumes a thread from waiting
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     void Wakeup(); | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-25 12:40:33 -04:00
										 |  |  |     ResultCode Start(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     virtual bool IsSignaled() const override; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 07:08:12 -04:00
										 |  |  |     /// Cancels a waiting operation that this thread may or may not be within.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// When the thread is within a waiting state, this will set the thread's
 | 
					
						
							|  |  |  |     /// waiting result to signal a canceled wait. The function will then resume
 | 
					
						
							|  |  |  |     /// this thread.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     void CancelWait(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     void SetSynchronizationResults(KSynchronizationObject* object, ResultCode result); | 
					
						
							| 
									
										
										
										
											2020-02-25 16:38:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     void SetSyncedObject(KSynchronizationObject* object, ResultCode result) { | 
					
						
							|  |  |  |         SetSynchronizationResults(object, result); | 
					
						
							| 
									
										
										
										
											2020-02-25 16:38:33 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     ResultCode GetWaitResult(KSynchronizationObject** out) const { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |         *out = signaling_object; | 
					
						
							| 
									
										
										
										
											2020-02-25 16:38:33 -04:00
										 |  |  |         return signaling_result; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-01-17 02:03:44 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     ResultCode GetSignalingResult() const { | 
					
						
							|  |  |  |         return signaling_result; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-12-03 22:38:14 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-25 22:56:17 -08:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * Stops a thread, invalidating it from further use | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     void Stop(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-10 18:35:37 -05:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * Returns the Thread Local Storage address of the current thread | 
					
						
							|  |  |  |      * @returns VAddr of the thread's TLS | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-09-18 09:38:01 +09:00
										 |  |  |     VAddr GetTLSAddress() const { | 
					
						
							|  |  |  |         return tls_address; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-10 18:35:37 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-20 19:57:45 -05:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * Returns the value of the TPIDR_EL0 Read/Write system register for this thread. | 
					
						
							|  |  |  |      * @returns The value of the TPIDR_EL0 register. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     u64 GetTPIDR_EL0() const { | 
					
						
							|  |  |  |         return tpidr_el0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     /// Sets the value of the TPIDR_EL0 Read/Write system register for this thread.
 | 
					
						
							|  |  |  |     void SetTPIDR_EL0(u64 value) { | 
					
						
							|  |  |  |         tpidr_el0 = value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-29 14:47:52 -05:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * Returns the address of the current thread's command buffer, located in the TLS. | 
					
						
							|  |  |  |      * @returns VAddr of the thread's command buffer. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     VAddr GetCommandBufferAddress() const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-01 23:46:10 -05:00
										 |  |  |     ThreadContext32& GetContext32() { | 
					
						
							|  |  |  |         return context_32; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-01 23:46:10 -05:00
										 |  |  |     const ThreadContext32& GetContext32() const { | 
					
						
							|  |  |  |         return context_32; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ThreadContext64& GetContext64() { | 
					
						
							|  |  |  |         return context_64; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const ThreadContext64& GetContext64() const { | 
					
						
							|  |  |  |         return context_64; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  |     bool IsHLEThread() const { | 
					
						
							|  |  |  |         return (type & THREADTYPE_HLE) != 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-12 16:48:43 -04:00
										 |  |  |     bool IsSuspendThread() const { | 
					
						
							|  |  |  |         return (type & THREADTYPE_SUSPEND) != 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool IsIdleThread() const { | 
					
						
							|  |  |  |         return (type & THREADTYPE_IDLE) != 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool WasRunning() const { | 
					
						
							|  |  |  |         return was_running; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void SetWasRunning(bool value) { | 
					
						
							|  |  |  |         was_running = value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-13 14:17:34 -04:00
										 |  |  |     std::shared_ptr<Common::Fiber>& GetHostContext(); | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-28 13:16:43 -08:00
										 |  |  |     ThreadState GetState() const { | 
					
						
							|  |  |  |         return thread_state & ThreadState::Mask; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-28 13:16:43 -08:00
										 |  |  |     ThreadState GetRawState() const { | 
					
						
							|  |  |  |         return thread_state; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     void SetState(ThreadState state); | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  |     s64 GetLastScheduledTick() const { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |         return last_scheduled_tick; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     void SetLastScheduledTick(s64 tick) { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |         last_scheduled_tick = tick; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 18:42:50 -04:00
										 |  |  |     u64 GetTotalCPUTimeTicks() const { | 
					
						
							|  |  |  |         return total_cpu_time_ticks; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void UpdateCPUTimeTicks(u64 ticks) { | 
					
						
							|  |  |  |         total_cpu_time_ticks += ticks; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     s32 GetProcessorID() const { | 
					
						
							|  |  |  |         return processor_id; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |     s32 GetActiveCore() const { | 
					
						
							|  |  |  |         return GetProcessorID(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-29 17:01:46 -04:00
										 |  |  |     void SetProcessorID(s32 new_core) { | 
					
						
							|  |  |  |         processor_id = new_core; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |     void SetActiveCore(s32 new_core) { | 
					
						
							|  |  |  |         processor_id = new_core; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 00:42:10 -04:00
										 |  |  |     Process* GetOwnerProcess() { | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |         return owner_process; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 00:42:10 -04:00
										 |  |  |     const Process* GetOwnerProcess() const { | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |         return owner_process; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const MutexWaitingThreads& GetMutexWaitingThreads() const { | 
					
						
							|  |  |  |         return wait_mutex_threads; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Thread* GetLockOwner() const { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |         return lock_owner; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-12-22 04:32:03 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     void SetLockOwner(Thread* owner) { | 
					
						
							|  |  |  |         lock_owner = owner; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-12-22 04:32:03 -02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 19:07:39 -07:00
										 |  |  |     u32 GetIdealCore() const { | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |         return ideal_core; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  |     const KAffinityMask& GetAffinityMask() const { | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |         return affinity_mask; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 12:44:35 -04:00
										 |  |  |     ResultCode SetActivity(ThreadActivity value); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:25:27 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 23:28:29 -04:00
										 |  |  |     /// Sleeps this thread for the given amount of nanoseconds.
 | 
					
						
							| 
									
										
										
										
											2020-02-25 12:40:33 -04:00
										 |  |  |     ResultCode Sleep(s64 nanoseconds); | 
					
						
							| 
									
										
										
										
											2019-03-15 23:28:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  |     s64 GetYieldScheduleCount() const { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |         return schedule_count; | 
					
						
							| 
									
										
										
										
											2019-09-11 12:14:37 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     void SetYieldScheduleCount(s64 count) { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |         schedule_count = count; | 
					
						
							| 
									
										
										
										
											2019-09-11 12:14:37 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-29 17:01:46 -04:00
										 |  |  |     bool IsRunning() const { | 
					
						
							|  |  |  |         return is_running; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void SetIsRunning(bool value) { | 
					
						
							|  |  |  |         is_running = value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     bool IsWaitCancelled() const { | 
					
						
							| 
									
										
										
										
											2019-11-16 11:05:39 -04:00
										 |  |  |         return is_sync_cancelled; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     void ClearWaitCancelled() { | 
					
						
							|  |  |  |         is_sync_cancelled = false; | 
					
						
							| 
									
										
										
										
											2019-11-16 11:05:39 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-14 09:30:53 -04:00
										 |  |  |     Handle GetGlobalHandle() const { | 
					
						
							|  |  |  |         return global_handle; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     bool IsCancellable() const { | 
					
						
							|  |  |  |         return is_cancellable; | 
					
						
							| 
									
										
										
										
											2020-03-07 10:24:46 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     void SetCancellable() { | 
					
						
							|  |  |  |         is_cancellable = true; | 
					
						
							| 
									
										
										
										
											2020-03-07 10:24:46 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     void ClearCancellable() { | 
					
						
							|  |  |  |         is_cancellable = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool IsTerminationRequested() const { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |         return will_be_terminated || GetRawState() == ThreadState::Terminated; | 
					
						
							| 
									
										
										
										
											2020-03-07 12:44:35 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool IsPaused() const { | 
					
						
							|  |  |  |         return pausing_state != 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-10 18:41:11 -04:00
										 |  |  |     bool IsContinuousOnSVC() const { | 
					
						
							|  |  |  |         return is_continuous_on_svc; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void SetContinuousOnSVC(bool is_continuous) { | 
					
						
							|  |  |  |         is_continuous_on_svc = is_continuous; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-19 13:09:32 -04:00
										 |  |  |     bool IsPhantomMode() const { | 
					
						
							|  |  |  |         return is_phantom_mode; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void SetPhantomMode(bool phantom) { | 
					
						
							|  |  |  |         is_phantom_mode = phantom; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 14:16:25 -04:00
										 |  |  |     bool HasExited() const { | 
					
						
							|  |  |  |         return has_exited; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  |     class QueueEntry { | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |     public: | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  |         constexpr QueueEntry() = default; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         constexpr void Initialize() { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |             prev = nullptr; | 
					
						
							|  |  |  |             next = nullptr; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         constexpr Thread* GetPrev() const { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |             return prev; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |         constexpr Thread* GetNext() const { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |             return next; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  |         constexpr void SetPrev(Thread* thread) { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |             prev = thread; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  |         constexpr void SetNext(Thread* thread) { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |             next = thread; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |         Thread* prev{}; | 
					
						
							|  |  |  |         Thread* next{}; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  |     QueueEntry& GetPriorityQueueEntry(s32 core) { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |         return per_core_priority_queue_entry[core]; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const QueueEntry& GetPriorityQueueEntry(s32 core) const { | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |         return per_core_priority_queue_entry[core]; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s32 GetDisableDispatchCount() const { | 
					
						
							|  |  |  |         return disable_count; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void DisableDispatch() { | 
					
						
							|  |  |  |         ASSERT(GetDisableDispatchCount() >= 0); | 
					
						
							|  |  |  |         disable_count++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void EnableDispatch() { | 
					
						
							|  |  |  |         ASSERT(GetDisableDispatchCount() > 0); | 
					
						
							|  |  |  |         disable_count--; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     void SetWaitObjectsForDebugging(const std::span<KSynchronizationObject*>& objects) { | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |         wait_objects_for_debugging.clear(); | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |         wait_objects_for_debugging.reserve(objects.size()); | 
					
						
							|  |  |  |         for (const auto& object : objects) { | 
					
						
							|  |  |  |             wait_objects_for_debugging.emplace_back(object); | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     [[nodiscard]] const std::vector<KSynchronizationObject*>& GetWaitObjectsForDebugging() const { | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |         return wait_objects_for_debugging; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     void SetMutexWaitAddressForDebugging(VAddr address) { | 
					
						
							|  |  |  |         mutex_wait_address_for_debugging = address; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] VAddr GetMutexWaitAddressForDebugging() const { | 
					
						
							|  |  |  |         return mutex_wait_address_for_debugging; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void AddWaiter(Thread* thread); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void RemoveWaiter(Thread* thread); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] Thread* RemoveWaiterByKey(s32* out_num_waiters, VAddr key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] VAddr GetAddressKey() const { | 
					
						
							|  |  |  |         return address_key; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] u32 GetAddressKeyValue() const { | 
					
						
							|  |  |  |         return address_key_value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void SetAddressKey(VAddr key) { | 
					
						
							|  |  |  |         address_key = key; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void SetAddressKey(VAddr key, u32 val) { | 
					
						
							|  |  |  |         address_key = key; | 
					
						
							|  |  |  |         address_key_value = val; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     static constexpr size_t PriorityInheritanceCountMax = 10; | 
					
						
							|  |  |  |     union SyncObjectBuffer { | 
					
						
							|  |  |  |         std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> sync_objects{}; | 
					
						
							|  |  |  |         std::array<Handle, | 
					
						
							|  |  |  |                    Svc::ArgumentHandleCountMax*(sizeof(KSynchronizationObject*) / sizeof(Handle))> | 
					
						
							|  |  |  |             handles; | 
					
						
							|  |  |  |         constexpr SyncObjectBuffer() {} | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     static_assert(sizeof(SyncObjectBuffer::sync_objects) == sizeof(SyncObjectBuffer::handles)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     struct ConditionVariableComparator { | 
					
						
							|  |  |  |         struct LightCompareType { | 
					
						
							|  |  |  |             u64 cv_key{}; | 
					
						
							|  |  |  |             s32 priority{}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             [[nodiscard]] constexpr u64 GetConditionVariableKey() const { | 
					
						
							|  |  |  |                 return cv_key; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             [[nodiscard]] constexpr s32 GetPriority() const { | 
					
						
							|  |  |  |                 return priority; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         template <typename T> | 
					
						
							|  |  |  |         requires( | 
					
						
							|  |  |  |             std::same_as<T, Thread> || | 
					
						
							|  |  |  |             std::same_as<T, LightCompareType>) static constexpr int Compare(const T& lhs, | 
					
						
							|  |  |  |                                                                             const Thread& rhs) { | 
					
						
							|  |  |  |             const uintptr_t l_key = lhs.GetConditionVariableKey(); | 
					
						
							|  |  |  |             const uintptr_t r_key = rhs.GetConditionVariableKey(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (l_key < r_key) { | 
					
						
							|  |  |  |                 // Sort first by key
 | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             } else if (l_key == r_key && lhs.GetPriority() < rhs.GetPriority()) { | 
					
						
							|  |  |  |                 // And then by priority.
 | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 return 1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Common::IntrusiveRedBlackTreeNode condvar_arbiter_tree_node{}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     using ConditionVariableThreadTreeTraits = | 
					
						
							|  |  |  |         Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&Thread::condvar_arbiter_tree_node>; | 
					
						
							|  |  |  |     using ConditionVariableThreadTree = | 
					
						
							|  |  |  |         ConditionVariableThreadTreeTraits::TreeType<ConditionVariableComparator>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     using ConditionVariableThreadTreeType = ConditionVariableThreadTree; | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     [[nodiscard]] uintptr_t GetConditionVariableKey() const { | 
					
						
							|  |  |  |         return condvar_key; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] uintptr_t GetAddressArbiterKey() const { | 
					
						
							|  |  |  |         return condvar_key; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void SetConditionVariable(ConditionVariableThreadTree* tree, VAddr address, uintptr_t cv_key, | 
					
						
							|  |  |  |                               u32 value) { | 
					
						
							|  |  |  |         condvar_tree = tree; | 
					
						
							|  |  |  |         condvar_key = cv_key; | 
					
						
							|  |  |  |         address_key = address; | 
					
						
							|  |  |  |         address_key_value = value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void ClearConditionVariable() { | 
					
						
							|  |  |  |         condvar_tree = nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] bool IsWaitingForConditionVariable() const { | 
					
						
							|  |  |  |         return condvar_tree != nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void SetAddressArbiter(ConditionVariableThreadTree* tree, uintptr_t address) { | 
					
						
							|  |  |  |         condvar_tree = tree; | 
					
						
							|  |  |  |         condvar_key = address; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void ClearAddressArbiter() { | 
					
						
							|  |  |  |         condvar_tree = nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] bool IsWaitingForAddressArbiter() const { | 
					
						
							|  |  |  |         return condvar_tree != nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] ConditionVariableThreadTree* GetConditionVariableTree() const { | 
					
						
							|  |  |  |         return condvar_tree; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] bool HasWaiters() const { | 
					
						
							|  |  |  |         return !waiter_list.empty(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2020-03-07 12:44:35 -04:00
										 |  |  |     void AddSchedulingFlag(ThreadSchedFlags flag); | 
					
						
							|  |  |  |     void RemoveSchedulingFlag(ThreadSchedFlags flag); | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     void AddWaiterImpl(Thread* thread); | 
					
						
							|  |  |  |     void RemoveWaiterImpl(Thread* thread); | 
					
						
							|  |  |  |     static void RestorePriority(KernelCore& kernel, Thread* thread); | 
					
						
							| 
									
										
										
										
											2019-03-29 17:01:46 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-01 12:14:17 -04:00
										 |  |  |     Common::SpinLock context_guard{}; | 
					
						
							| 
									
										
										
										
											2020-03-01 23:46:10 -05:00
										 |  |  |     ThreadContext32 context_32{}; | 
					
						
							|  |  |  |     ThreadContext64 context_64{}; | 
					
						
							| 
									
										
										
										
											2020-03-10 13:13:39 -04:00
										 |  |  |     std::shared_ptr<Common::Fiber> host_context{}; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-28 13:16:43 -08:00
										 |  |  |     ThreadState thread_state = ThreadState::Initialized; | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-18 22:37:01 -05:00
										 |  |  |     u64 thread_id = 0; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     VAddr entry_point = 0; | 
					
						
							|  |  |  |     VAddr stack_top = 0; | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |     std::atomic_int disable_count = 0; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-24 22:04:12 -04:00
										 |  |  |     ThreadType type; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-14 21:58:23 -04:00
										 |  |  |     /// Nominal thread priority, as set by the emulated application.
 | 
					
						
							|  |  |  |     /// The nominal priority is the thread priority without priority
 | 
					
						
							|  |  |  |     /// inheritance taken into account.
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     s32 base_priority{}; | 
					
						
							| 
									
										
										
										
											2019-03-14 21:58:23 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Current thread priority. This may change over the course of the
 | 
					
						
							|  |  |  |     /// thread's lifetime in order to facilitate priority inheritance.
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     s32 current_priority{}; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 18:42:50 -04:00
										 |  |  |     u64 total_cpu_time_ticks = 0; ///< Total CPU running ticks.
 | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |     s64 schedule_count{}; | 
					
						
							|  |  |  |     s64 last_scheduled_tick{}; | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     s32 processor_id = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     VAddr tls_address = 0; ///< Virtual address of the Thread Local Storage of the thread
 | 
					
						
							|  |  |  |     u64 tpidr_el0 = 0;     ///< TPIDR_EL0 read/write system register.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Process that owns this thread
 | 
					
						
							| 
									
										
										
										
											2018-10-10 00:42:10 -04:00
										 |  |  |     Process* owner_process; | 
					
						
							| 
									
										
										
										
											2016-12-04 09:58:36 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 10:53:01 -05:00
										 |  |  |     /// Objects that the thread is waiting on, in the same order as they were
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     /// passed to WaitSynchronization. This is used for debugging only.
 | 
					
						
							|  |  |  |     std::vector<KSynchronizationObject*> wait_objects_for_debugging; | 
					
						
							| 
									
										
										
										
											2016-12-04 09:58:36 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     /// The current mutex wait address. This is used for debugging only.
 | 
					
						
							|  |  |  |     VAddr mutex_wait_address_for_debugging{}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     KSynchronizationObject* signaling_object; | 
					
						
							| 
									
										
										
										
											2020-02-25 16:38:33 -04:00
										 |  |  |     ResultCode signaling_result{RESULT_SUCCESS}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-20 20:15:16 -05:00
										 |  |  |     /// List of threads that are waiting for a mutex that is held by this thread.
 | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     MutexWaitingThreads wait_mutex_threads; | 
					
						
							| 
									
										
										
										
											2018-04-20 20:15:16 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Thread that owns the lock that this thread is waiting for.
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     Thread* lock_owner{}; | 
					
						
							| 
									
										
										
										
											2016-12-03 22:38:14 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-07 23:39:37 -04:00
										 |  |  |     /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
 | 
					
						
							| 
									
										
										
										
											2020-02-14 09:30:53 -04:00
										 |  |  |     Handle global_handle = 0; | 
					
						
							| 
									
										
										
										
											2015-06-07 23:39:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-02 18:08:35 -08:00
										 |  |  |     KScheduler* scheduler = nullptr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 00:17:18 -08:00
										 |  |  |     std::array<QueueEntry, Core::Hardware::NUM_CPU_CORES> per_core_priority_queue_entry{}; | 
					
						
							| 
									
										
										
										
											2018-05-02 22:36:51 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 19:07:39 -07:00
										 |  |  |     u32 ideal_core{0xFFFFFFFF}; | 
					
						
							| 
									
										
										
										
											2020-11-16 21:02:45 -08:00
										 |  |  |     KAffinityMask affinity_mask{}; | 
					
						
							| 
									
										
										
										
											2018-05-05 23:03:01 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-29 17:01:46 -04:00
										 |  |  |     s32 ideal_core_override = -1; | 
					
						
							|  |  |  |     u32 affinity_override_count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 12:44:35 -04:00
										 |  |  |     u32 pausing_state = 0; | 
					
						
							| 
									
										
										
										
											2019-03-29 17:01:46 -04:00
										 |  |  |     bool is_running = false; | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     bool is_cancellable = false; | 
					
						
							| 
									
										
										
										
											2019-11-16 11:05:39 -04:00
										 |  |  |     bool is_sync_cancelled = false; | 
					
						
							| 
									
										
										
										
											2019-03-29 17:01:46 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-10 18:41:11 -04:00
										 |  |  |     bool is_continuous_on_svc = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 12:44:35 -04:00
										 |  |  |     bool will_be_terminated = false; | 
					
						
							| 
									
										
										
										
											2020-03-19 13:09:32 -04:00
										 |  |  |     bool is_phantom_mode = false; | 
					
						
							| 
									
										
										
										
											2020-03-07 14:16:25 -04:00
										 |  |  |     bool has_exited = false; | 
					
						
							| 
									
										
										
										
											2020-02-25 12:40:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-12 16:48:43 -04:00
										 |  |  |     bool was_running = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-21 22:36:53 -08:00
										 |  |  |     bool signaled{}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 01:14:02 -08:00
										 |  |  |     ConditionVariableThreadTree* condvar_tree{}; | 
					
						
							|  |  |  |     uintptr_t condvar_key{}; | 
					
						
							|  |  |  |     VAddr address_key{}; | 
					
						
							|  |  |  |     u32 address_key_value{}; | 
					
						
							|  |  |  |     s32 num_kernel_waiters{}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     using WaiterList = boost::intrusive::list<Thread>; | 
					
						
							|  |  |  |     WaiterList waiter_list{}; | 
					
						
							|  |  |  |     WaiterList pinned_waiter_list{}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 18:47:57 -04:00
										 |  |  |     std::string name; | 
					
						
							| 
									
										
										
										
											2014-12-22 04:32:03 -02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-26 17:40:49 -05:00
										 |  |  | } // namespace Kernel
 |