diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 100 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.h | 100 |
2 files changed, 91 insertions, 109 deletions
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index e0f53287c..5d0b266c5 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -62,7 +62,7 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, | |||
| 62 | namespace Kernel { | 62 | namespace Kernel { |
| 63 | 63 | ||
| 64 | KThread::KThread(KernelCore& kernel) | 64 | KThread::KThread(KernelCore& kernel) |
| 65 | : KSynchronizationObject{kernel}, activity_pause_lock{kernel} {} | 65 | : KAutoObjectWithSlabHeapAndContainer{kernel}, activity_pause_lock{kernel} {} |
| 66 | KThread::~KThread() = default; | 66 | KThread::~KThread() = default; |
| 67 | 67 | ||
| 68 | ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, | 68 | ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, |
| @@ -177,6 +177,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s | |||
| 177 | // Set parent, if relevant. | 177 | // Set parent, if relevant. |
| 178 | if (owner != nullptr) { | 178 | if (owner != nullptr) { |
| 179 | parent = owner; | 179 | parent = owner; |
| 180 | parent->Open(); | ||
| 180 | parent->IncrementThreadCount(); | 181 | parent->IncrementThreadCount(); |
| 181 | } | 182 | } |
| 182 | 183 | ||
| @@ -210,13 +211,55 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s | |||
| 210 | 211 | ||
| 211 | ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, | 212 | ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, |
| 212 | VAddr user_stack_top, s32 prio, s32 core, Process* owner, | 213 | VAddr user_stack_top, s32 prio, s32 core, Process* owner, |
| 213 | ThreadType type) { | 214 | ThreadType type, std::function<void(void*)>&& init_func, |
| 215 | void* init_func_parameter) { | ||
| 214 | // Initialize the thread. | 216 | // Initialize the thread. |
| 215 | R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); | 217 | R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); |
| 216 | 218 | ||
| 219 | // Initialize host context. | ||
| 220 | thread->host_context = | ||
| 221 | std::make_shared<Common::Fiber>(std::move(init_func), init_func_parameter); | ||
| 222 | |||
| 217 | return RESULT_SUCCESS; | 223 | return RESULT_SUCCESS; |
| 218 | } | 224 | } |
| 219 | 225 | ||
| 226 | ResultCode KThread::InitializeDummyThread(KThread* thread) { | ||
| 227 | return thread->Initialize({}, {}, {}, DefaultThreadPriority, 3, {}, ThreadType::Main); | ||
| 228 | } | ||
| 229 | |||
| 230 | ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { | ||
| 231 | return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, | ||
| 232 | Core::CpuManager::GetIdleThreadStartFunc(), | ||
| 233 | system.GetCpuManager().GetStartFuncParamater()); | ||
| 234 | } | ||
| 235 | |||
| 236 | ResultCode KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, | ||
| 237 | KThreadFunction func, uintptr_t arg, | ||
| 238 | s32 virt_core) { | ||
| 239 | return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, | ||
| 240 | Core::CpuManager::GetSuspendThreadStartFunc(), | ||
| 241 | system.GetCpuManager().GetStartFuncParamater()); | ||
| 242 | } | ||
| 243 | |||
| 244 | ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread, | ||
| 245 | KThreadFunction func, uintptr_t arg, VAddr user_stack_top, | ||
| 246 | s32 prio, s32 virt_core, Process* owner) { | ||
| 247 | system.Kernel().GlobalSchedulerContext().AddThread(thread); | ||
| 248 | return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, | ||
| 249 | ThreadType::User, Core::CpuManager::GetGuestThreadStartFunc(), | ||
| 250 | system.GetCpuManager().GetStartFuncParamater()); | ||
| 251 | } | ||
| 252 | |||
| 253 | void KThread::PostDestroy(uintptr_t arg) { | ||
| 254 | Process* owner = reinterpret_cast<Process*>(arg & ~1ULL); | ||
| 255 | const bool resource_limit_release_hint = (arg & 1); | ||
| 256 | const s64 hint_value = (resource_limit_release_hint ? 0 : 1); | ||
| 257 | if (owner != nullptr) { | ||
| 258 | owner->GetResourceLimit()->Release(Kernel::LimitableResource::Threads, 1, hint_value); | ||
| 259 | owner->Close(); | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 220 | void KThread::Finalize() { | 263 | void KThread::Finalize() { |
| 221 | // If the thread has an owner process, unregister it. | 264 | // If the thread has an owner process, unregister it. |
| 222 | if (parent != nullptr) { | 265 | if (parent != nullptr) { |
| @@ -294,6 +337,9 @@ void KThread::StartTermination() { | |||
| 294 | 337 | ||
| 295 | // Register terminated dpc flag. | 338 | // Register terminated dpc flag. |
| 296 | RegisterDpc(DpcFlag::Terminated); | 339 | RegisterDpc(DpcFlag::Terminated); |
| 340 | |||
| 341 | // Close the thread. | ||
| 342 | this->Close(); | ||
| 297 | } | 343 | } |
| 298 | 344 | ||
| 299 | void KThread::Pin() { | 345 | void KThread::Pin() { |
| @@ -995,56 +1041,6 @@ std::shared_ptr<Common::Fiber>& KThread::GetHostContext() { | |||
| 995 | return host_context; | 1041 | return host_context; |
| 996 | } | 1042 | } |
| 997 | 1043 | ||
| 998 | ResultVal<std::shared_ptr<KThread>> KThread::CreateThread(Core::System& system, | ||
| 999 | ThreadType type_flags, std::string name, | ||
| 1000 | VAddr entry_point, u32 priority, u64 arg, | ||
| 1001 | s32 processor_id, VAddr stack_top, | ||
| 1002 | Process* owner_process) { | ||
| 1003 | auto& kernel = system.Kernel(); | ||
| 1004 | |||
| 1005 | std::shared_ptr<KThread> thread = std::make_shared<KThread>(kernel); | ||
| 1006 | |||
| 1007 | if (const auto result = | ||
| 1008 | thread->InitializeThread(thread.get(), entry_point, arg, stack_top, priority, | ||
| 1009 | processor_id, owner_process, type_flags); | ||
| 1010 | result.IsError()) { | ||
| 1011 | return result; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | thread->name = name; | ||
| 1015 | |||
| 1016 | auto& scheduler = kernel.GlobalSchedulerContext(); | ||
| 1017 | scheduler.AddThread(thread); | ||
| 1018 | |||
| 1019 | return MakeResult<std::shared_ptr<KThread>>(std::move(thread)); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | ResultVal<std::shared_ptr<KThread>> KThread::CreateThread( | ||
| 1023 | Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, u32 priority, | ||
| 1024 | u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process, | ||
| 1025 | std::function<void(void*)>&& thread_start_func, void* thread_start_parameter) { | ||
| 1026 | auto thread_result = CreateThread(system, type_flags, name, entry_point, priority, arg, | ||
| 1027 | processor_id, stack_top, owner_process); | ||
| 1028 | |||
| 1029 | if (thread_result.Succeeded()) { | ||
| 1030 | (*thread_result)->host_context = | ||
| 1031 | std::make_shared<Common::Fiber>(std::move(thread_start_func), thread_start_parameter); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | return thread_result; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | ResultVal<std::shared_ptr<KThread>> KThread::CreateUserThread( | ||
| 1038 | Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, u32 priority, | ||
| 1039 | u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process) { | ||
| 1040 | std::function<void(void*)> init_func = Core::CpuManager::GetGuestThreadStartFunc(); | ||
| 1041 | |||
| 1042 | void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); | ||
| 1043 | |||
| 1044 | return CreateThread(system, type_flags, name, entry_point, priority, arg, processor_id, | ||
| 1045 | stack_top, owner_process, std::move(init_func), init_func_parameter); | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | KThread* GetCurrentThreadPointer(KernelCore& kernel) { | 1044 | KThread* GetCurrentThreadPointer(KernelCore& kernel) { |
| 1049 | return kernel.GetCurrentEmuThread(); | 1045 | return kernel.GetCurrentEmuThread(); |
| 1050 | } | 1046 | } |
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index b442dfe57..5c1c17d48 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "core/hle/kernel/k_spin_lock.h" | 20 | #include "core/hle/kernel/k_spin_lock.h" |
| 21 | #include "core/hle/kernel/k_synchronization_object.h" | 21 | #include "core/hle/kernel/k_synchronization_object.h" |
| 22 | #include "core/hle/kernel/object.h" | 22 | #include "core/hle/kernel/object.h" |
| 23 | #include "core/hle/kernel/slab_helpers.h" | ||
| 23 | #include "core/hle/kernel/svc_common.h" | 24 | #include "core/hle/kernel/svc_common.h" |
| 24 | #include "core/hle/kernel/svc_types.h" | 25 | #include "core/hle/kernel/svc_types.h" |
| 25 | #include "core/hle/result.h" | 26 | #include "core/hle/result.h" |
| @@ -99,7 +100,11 @@ enum class ThreadWaitReasonForDebugging : u32 { | |||
| 99 | [[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); | 100 | [[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); |
| 100 | [[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); | 101 | [[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); |
| 101 | 102 | ||
| 102 | class KThread final : public KSynchronizationObject, public boost::intrusive::list_base_hook<> { | 103 | class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>, |
| 104 | public boost::intrusive::list_base_hook<> { | ||
| 105 | KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); | ||
| 106 | |||
| 107 | private: | ||
| 103 | friend class KScheduler; | 108 | friend class KScheduler; |
| 104 | friend class Process; | 109 | friend class Process; |
| 105 | 110 | ||
| @@ -115,57 +120,6 @@ public: | |||
| 115 | using ThreadContext64 = Core::ARM_Interface::ThreadContext64; | 120 | using ThreadContext64 = Core::ARM_Interface::ThreadContext64; |
| 116 | using WaiterList = boost::intrusive::list<KThread>; | 121 | using WaiterList = boost::intrusive::list<KThread>; |
| 117 | 122 | ||
| 118 | /** | ||
| 119 | * Creates and returns a new thread. | ||
| 120 | * @param system The instance of the whole system | ||
| 121 | * @param name The friendly name desired for the thread | ||
| 122 | * @param entry_point The address at which the thread should start execution | ||
| 123 | * @param priority The thread's priority | ||
| 124 | * @param arg User data to pass to the thread | ||
| 125 | * @param processor_id The ID(s) of the processors on which the thread is desired to be run | ||
| 126 | * @param stack_top The address of the thread's stack top | ||
| 127 | * @param owner_process The parent process for the thread, if null, it's a kernel thread | ||
| 128 | * @return A shared pointer to the newly created thread | ||
| 129 | */ | ||
| 130 | [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> CreateThread( | ||
| 131 | Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, | ||
| 132 | u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process); | ||
| 133 | |||
| 134 | /** | ||
| 135 | * Creates and returns a new thread, with a specified entry point. | ||
| 136 | * @param system The instance of the whole system | ||
| 137 | * @param name The friendly name desired for the thread | ||
| 138 | * @param entry_point The address at which the thread should start execution | ||
| 139 | * @param priority The thread's priority | ||
| 140 | * @param arg User data to pass to the thread | ||
| 141 | * @param processor_id The ID(s) of the processors on which the thread is desired to be run | ||
| 142 | * @param stack_top The address of the thread's stack top | ||
| 143 | * @param owner_process The parent process for the thread, if null, it's a kernel thread | ||
| 144 | * @param thread_start_func The function where the host context will start. | ||
| 145 | * @param thread_start_parameter The parameter which will passed to host context on init | ||
| 146 | * @return A shared pointer to the newly created thread | ||
| 147 | */ | ||
| 148 | [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> CreateThread( | ||
| 149 | Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, | ||
| 150 | u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process, | ||
| 151 | std::function<void(void*)>&& thread_start_func, void* thread_start_parameter); | ||
| 152 | |||
| 153 | /** | ||
| 154 | * Creates and returns a new thread for the emulated "user" process. | ||
| 155 | * @param system The instance of the whole system | ||
| 156 | * @param name The friendly name desired for the thread | ||
| 157 | * @param entry_point The address at which the thread should start execution | ||
| 158 | * @param priority The thread's priority | ||
| 159 | * @param arg User data to pass to the thread | ||
| 160 | * @param processor_id The ID(s) of the processors on which the thread is desired to be run | ||
| 161 | * @param stack_top The address of the thread's stack top | ||
| 162 | * @param owner_process The parent process for the thread, if null, it's a kernel thread | ||
| 163 | * @return A shared pointer to the newly created thread | ||
| 164 | */ | ||
| 165 | [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> CreateUserThread( | ||
| 166 | Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, | ||
| 167 | u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process); | ||
| 168 | |||
| 169 | [[nodiscard]] std::string GetName() const override { | 123 | [[nodiscard]] std::string GetName() const override { |
| 170 | return name; | 124 | return name; |
| 171 | } | 125 | } |
| @@ -257,10 +211,6 @@ public: | |||
| 257 | 211 | ||
| 258 | void Suspend(); | 212 | void Suspend(); |
| 259 | 213 | ||
| 260 | void Finalize() override; | ||
| 261 | |||
| 262 | bool IsSignaled() const override; | ||
| 263 | |||
| 264 | void SetSyncedObject(KSynchronizationObject* obj, ResultCode wait_res) { | 214 | void SetSyncedObject(KSynchronizationObject* obj, ResultCode wait_res) { |
| 265 | synced_object = obj; | 215 | synced_object = obj; |
| 266 | wait_result = wait_res; | 216 | wait_result = wait_res; |
| @@ -422,6 +372,40 @@ public: | |||
| 422 | return termination_requested || GetRawState() == ThreadState::Terminated; | 372 | return termination_requested || GetRawState() == ThreadState::Terminated; |
| 423 | } | 373 | } |
| 424 | 374 | ||
| 375 | [[nodiscard]] virtual u64 GetId() const override final { | ||
| 376 | return this->GetThreadID(); | ||
| 377 | } | ||
| 378 | |||
| 379 | [[nodiscard]] virtual bool IsInitialized() const override { | ||
| 380 | return initialized; | ||
| 381 | } | ||
| 382 | |||
| 383 | [[nodiscard]] virtual uintptr_t GetPostDestroyArgument() const override { | ||
| 384 | return reinterpret_cast<uintptr_t>(parent) | (resource_limit_release_hint ? 1 : 0); | ||
| 385 | } | ||
| 386 | |||
| 387 | virtual void Finalize() override; | ||
| 388 | |||
| 389 | [[nodiscard]] virtual bool IsSignaled() const override; | ||
| 390 | |||
| 391 | static void PostDestroy(uintptr_t arg); | ||
| 392 | |||
| 393 | [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); | ||
| 394 | |||
| 395 | [[nodiscard]] static ResultCode InitializeIdleThread(Core::System& system, KThread* thread, | ||
| 396 | s32 virt_core); | ||
| 397 | |||
| 398 | [[nodiscard]] static ResultCode InitializeHighPriorityThread(Core::System& system, | ||
| 399 | KThread* thread, | ||
| 400 | KThreadFunction func, | ||
| 401 | uintptr_t arg, s32 virt_core); | ||
| 402 | |||
| 403 | [[nodiscard]] static ResultCode InitializeUserThread(Core::System& system, KThread* thread, | ||
| 404 | KThreadFunction func, uintptr_t arg, | ||
| 405 | VAddr user_stack_top, s32 prio, | ||
| 406 | s32 virt_core, Process* owner); | ||
| 407 | |||
| 408 | public: | ||
| 425 | struct StackParameters { | 409 | struct StackParameters { |
| 426 | u8 svc_permission[0x10]; | 410 | u8 svc_permission[0x10]; |
| 427 | std::atomic<u8> dpc_flags; | 411 | std::atomic<u8> dpc_flags; |
| @@ -675,7 +659,9 @@ private: | |||
| 675 | 659 | ||
| 676 | [[nodiscard]] static ResultCode InitializeThread(KThread* thread, KThreadFunction func, | 660 | [[nodiscard]] static ResultCode InitializeThread(KThread* thread, KThreadFunction func, |
| 677 | uintptr_t arg, VAddr user_stack_top, s32 prio, | 661 | uintptr_t arg, VAddr user_stack_top, s32 prio, |
| 678 | s32 core, Process* owner, ThreadType type); | 662 | s32 core, Process* owner, ThreadType type, |
| 663 | std::function<void(void*)>&& init_func, | ||
| 664 | void* init_func_parameter); | ||
| 679 | 665 | ||
| 680 | static void RestorePriority(KernelCore& kernel, KThread* thread); | 666 | static void RestorePriority(KernelCore& kernel, KThread* thread); |
| 681 | 667 | ||