From 479bd50b96ecb7258528dea98d7528568ba67bee Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 2 Apr 2021 23:24:20 -0700 Subject: [PATCH] hle: kernel: Migrate KThread to KAutoObject. --- src/core/hle/kernel/k_thread.cpp | 100 +++++++++++++++---------------- 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 e0f53287cb..5d0b266c59 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, namespace Kernel { KThread::KThread(KernelCore& kernel) - : KSynchronizationObject{kernel}, activity_pause_lock{kernel} {} + : KAutoObjectWithSlabHeapAndContainer{kernel}, activity_pause_lock{kernel} {} KThread::~KThread() = default; 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 // Set parent, if relevant. if (owner != nullptr) { parent = owner; + parent->Open(); parent->IncrementThreadCount(); } @@ -210,13 +211,55 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, s32 core, Process* owner, - ThreadType type) { + ThreadType type, std::function&& init_func, + void* init_func_parameter) { // Initialize the thread. R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); + // Initialize host context. + thread->host_context = + std::make_shared(std::move(init_func), init_func_parameter); + return RESULT_SUCCESS; } +ResultCode KThread::InitializeDummyThread(KThread* thread) { + return thread->Initialize({}, {}, {}, DefaultThreadPriority, 3, {}, ThreadType::Main); +} + +ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { + return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, + Core::CpuManager::GetIdleThreadStartFunc(), + system.GetCpuManager().GetStartFuncParamater()); +} + +ResultCode KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, + KThreadFunction func, uintptr_t arg, + s32 virt_core) { + return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, + Core::CpuManager::GetSuspendThreadStartFunc(), + system.GetCpuManager().GetStartFuncParamater()); +} + +ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread, + KThreadFunction func, uintptr_t arg, VAddr user_stack_top, + s32 prio, s32 virt_core, Process* owner) { + system.Kernel().GlobalSchedulerContext().AddThread(thread); + return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, + ThreadType::User, Core::CpuManager::GetGuestThreadStartFunc(), + system.GetCpuManager().GetStartFuncParamater()); +} + +void KThread::PostDestroy(uintptr_t arg) { + Process* owner = reinterpret_cast(arg & ~1ULL); + const bool resource_limit_release_hint = (arg & 1); + const s64 hint_value = (resource_limit_release_hint ? 0 : 1); + if (owner != nullptr) { + owner->GetResourceLimit()->Release(Kernel::LimitableResource::Threads, 1, hint_value); + owner->Close(); + } +} + void KThread::Finalize() { // If the thread has an owner process, unregister it. if (parent != nullptr) { @@ -294,6 +337,9 @@ void KThread::StartTermination() { // Register terminated dpc flag. RegisterDpc(DpcFlag::Terminated); + + // Close the thread. + this->Close(); } void KThread::Pin() { @@ -995,56 +1041,6 @@ std::shared_ptr& KThread::GetHostContext() { return host_context; } -ResultVal> KThread::CreateThread(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) { - auto& kernel = system.Kernel(); - - std::shared_ptr thread = std::make_shared(kernel); - - if (const auto result = - thread->InitializeThread(thread.get(), entry_point, arg, stack_top, priority, - processor_id, owner_process, type_flags); - result.IsError()) { - return result; - } - - thread->name = name; - - auto& scheduler = kernel.GlobalSchedulerContext(); - scheduler.AddThread(thread); - - return MakeResult>(std::move(thread)); -} - -ResultVal> KThread::CreateThread( - 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, - std::function&& thread_start_func, void* thread_start_parameter) { - auto thread_result = CreateThread(system, type_flags, name, entry_point, priority, arg, - processor_id, stack_top, owner_process); - - if (thread_result.Succeeded()) { - (*thread_result)->host_context = - std::make_shared(std::move(thread_start_func), thread_start_parameter); - } - - return thread_result; -} - -ResultVal> KThread::CreateUserThread( - 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) { - std::function init_func = Core::CpuManager::GetGuestThreadStartFunc(); - - void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); - - return CreateThread(system, type_flags, name, entry_point, priority, arg, processor_id, - stack_top, owner_process, std::move(init_func), init_func_parameter); -} - KThread* GetCurrentThreadPointer(KernelCore& kernel) { return kernel.GetCurrentEmuThread(); } diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index b442dfe577..5c1c17d486 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -20,6 +20,7 @@ #include "core/hle/kernel/k_spin_lock.h" #include "core/hle/kernel/k_synchronization_object.h" #include "core/hle/kernel/object.h" +#include "core/hle/kernel/slab_helpers.h" #include "core/hle/kernel/svc_common.h" #include "core/hle/kernel/svc_types.h" #include "core/hle/result.h" @@ -99,7 +100,11 @@ enum class ThreadWaitReasonForDebugging : u32 { [[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); [[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); -class KThread final : public KSynchronizationObject, public boost::intrusive::list_base_hook<> { +class KThread final : public KAutoObjectWithSlabHeapAndContainer, + public boost::intrusive::list_base_hook<> { + KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); + +private: friend class KScheduler; friend class Process; @@ -115,57 +120,6 @@ public: using ThreadContext64 = Core::ARM_Interface::ThreadContext64; using WaiterList = boost::intrusive::list; - /** - * Creates and returns a new thread. - * @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 - */ - [[nodiscard]] static ResultVal> CreateThread( - 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); - - /** - * Creates and returns a new thread, with a specified entry point. - * @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 - * @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 - * @return A shared pointer to the newly created thread - */ - [[nodiscard]] static ResultVal> CreateThread( - 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, - std::function&& thread_start_func, void* thread_start_parameter); - - /** - * Creates and returns a new thread for the emulated "user" process. - * @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 - */ - [[nodiscard]] static ResultVal> CreateUserThread( - 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); - [[nodiscard]] std::string GetName() const override { return name; } @@ -257,10 +211,6 @@ public: void Suspend(); - void Finalize() override; - - bool IsSignaled() const override; - void SetSyncedObject(KSynchronizationObject* obj, ResultCode wait_res) { synced_object = obj; wait_result = wait_res; @@ -422,6 +372,40 @@ public: return termination_requested || GetRawState() == ThreadState::Terminated; } + [[nodiscard]] virtual u64 GetId() const override final { + return this->GetThreadID(); + } + + [[nodiscard]] virtual bool IsInitialized() const override { + return initialized; + } + + [[nodiscard]] virtual uintptr_t GetPostDestroyArgument() const override { + return reinterpret_cast(parent) | (resource_limit_release_hint ? 1 : 0); + } + + virtual void Finalize() override; + + [[nodiscard]] virtual bool IsSignaled() const override; + + static void PostDestroy(uintptr_t arg); + + [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); + + [[nodiscard]] static ResultCode InitializeIdleThread(Core::System& system, KThread* thread, + s32 virt_core); + + [[nodiscard]] static ResultCode InitializeHighPriorityThread(Core::System& system, + KThread* thread, + KThreadFunction func, + uintptr_t arg, s32 virt_core); + + [[nodiscard]] static ResultCode InitializeUserThread(Core::System& system, KThread* thread, + KThreadFunction func, uintptr_t arg, + VAddr user_stack_top, s32 prio, + s32 virt_core, Process* owner); + +public: struct StackParameters { u8 svc_permission[0x10]; std::atomic dpc_flags; @@ -675,7 +659,9 @@ private: [[nodiscard]] static ResultCode InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, - s32 core, Process* owner, ThreadType type); + s32 core, Process* owner, ThreadType type, + std::function&& init_func, + void* init_func_parameter); static void RestorePriority(KernelCore& kernel, KThread* thread);