|
|
@ -62,7 +62,7 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, |
|
|
namespace Kernel { |
|
|
namespace Kernel { |
|
|
|
|
|
|
|
|
KThread::KThread(KernelCore& kernel) |
|
|
KThread::KThread(KernelCore& kernel) |
|
|
: KSynchronizationObject{kernel}, activity_pause_lock{kernel} {} |
|
|
|
|
|
|
|
|
: KAutoObjectWithSlabHeapAndContainer{kernel}, activity_pause_lock{kernel} {} |
|
|
KThread::~KThread() = default; |
|
|
KThread::~KThread() = default; |
|
|
|
|
|
|
|
|
ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, |
|
|
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.
|
|
|
// Set parent, if relevant.
|
|
|
if (owner != nullptr) { |
|
|
if (owner != nullptr) { |
|
|
parent = owner; |
|
|
parent = owner; |
|
|
|
|
|
parent->Open(); |
|
|
parent->IncrementThreadCount(); |
|
|
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, |
|
|
ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, |
|
|
VAddr user_stack_top, s32 prio, s32 core, Process* owner, |
|
|
VAddr user_stack_top, s32 prio, s32 core, Process* owner, |
|
|
ThreadType type) { |
|
|
|
|
|
|
|
|
ThreadType type, std::function<void(void*)>&& init_func, |
|
|
|
|
|
void* init_func_parameter) { |
|
|
// Initialize the thread.
|
|
|
// Initialize the thread.
|
|
|
R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); |
|
|
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; |
|
|
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<Process*>(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() { |
|
|
void KThread::Finalize() { |
|
|
// If the thread has an owner process, unregister it.
|
|
|
// If the thread has an owner process, unregister it.
|
|
|
if (parent != nullptr) { |
|
|
if (parent != nullptr) { |
|
|
@ -294,6 +337,9 @@ void KThread::StartTermination() { |
|
|
|
|
|
|
|
|
// Register terminated dpc flag.
|
|
|
// Register terminated dpc flag.
|
|
|
RegisterDpc(DpcFlag::Terminated); |
|
|
RegisterDpc(DpcFlag::Terminated); |
|
|
|
|
|
|
|
|
|
|
|
// Close the thread.
|
|
|
|
|
|
this->Close(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void KThread::Pin() { |
|
|
void KThread::Pin() { |
|
|
@ -995,56 +1041,6 @@ std::shared_ptr<Common::Fiber>& KThread::GetHostContext() { |
|
|
return host_context; |
|
|
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) { |
|
|
KThread* GetCurrentThreadPointer(KernelCore& kernel) { |
|
|
return kernel.GetCurrentEmuThread(); |
|
|
return kernel.GetCurrentEmuThread(); |
|
|
} |
|
|
} |
|
|
|