summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/k_thread.cpp')
-rw-r--r--src/core/hle/kernel/k_thread.cpp115
1 files changed, 56 insertions, 59 deletions
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index e0f53287c..ef6dfeeca 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -18,17 +18,16 @@
#include "core/core.h"
#include "core/cpu_manager.h"
#include "core/hardware_properties.h"
-#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_condition_variable.h"
+#include "core/hle/kernel/k_handle_table.h"
#include "core/hle/kernel/k_memory_layout.h"
+#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/object.h"
-#include "core/hle/kernel/process.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/time_manager.h"
#include "core/hle/result.h"
@@ -62,11 +61,11 @@ 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,
- s32 virt_core, Process* owner, ThreadType type) {
+ s32 virt_core, KProcess* owner, ThreadType type) {
// Assert parameters are valid.
ASSERT((type == ThreadType::Main) ||
(Svc::HighestThreadPriority <= prio && prio <= Svc::LowestThreadPriority));
@@ -177,6 +176,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();
}
@@ -209,14 +209,56 @@ 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) {
+ VAddr user_stack_top, s32 prio, s32 core, KProcess* owner,
+ ThreadType type, std::function<void(void*)>&& 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<Common::Fiber>(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, KProcess* 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) {
+ KProcess* owner = reinterpret_cast<KProcess*>(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(LimitableResource::Threads, 1, hint_value);
+ owner->Close();
+ }
+}
+
void KThread::Finalize() {
// If the thread has an owner process, unregister it.
if (parent != nullptr) {
@@ -246,8 +288,10 @@ void KThread::Finalize() {
// Decrement the parent process's thread count.
if (parent != nullptr) {
parent->DecrementThreadCount();
- parent->GetResourceLimit()->Release(LimitableResource::Threads, 1);
}
+
+ // Perform inherited finalization.
+ KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>::Finalize();
}
bool KThread::IsSignaled() const {
@@ -294,6 +338,9 @@ void KThread::StartTermination() {
// Register terminated dpc flag.
RegisterDpc(DpcFlag::Terminated);
+
+ // Close the thread.
+ this->Close();
}
void KThread::Pin() {
@@ -932,7 +979,7 @@ void KThread::Exit() {
// Release the thread resource hint from parent.
if (parent != nullptr) {
- // TODO(bunnei): Hint that the resource is about to be released.
+ parent->GetResourceLimit()->Release(Kernel::LimitableResource::Threads, 0, 1);
resource_limit_release_hint = true;
}
@@ -995,56 +1042,6 @@ std::shared_ptr<Common::Fiber>& KThread::GetHostContext() {
return host_context;
}
-ResultVal<std::shared_ptr<KThread>> 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<KThread> thread = std::make_shared<KThread>(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::shared_ptr<KThread>>(std::move(thread));
-}
-
-ResultVal<std::shared_ptr<KThread>> 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<void(void*)>&& 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<Common::Fiber>(std::move(thread_start_func), thread_start_parameter);
- }
-
- return thread_result;
-}
-
-ResultVal<std::shared_ptr<KThread>> 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<void(void*)> 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();
}