mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
hle: kernel: Migrate KThread to KAutoObject.
This commit is contained in:
parent
d3d0f2f451
commit
479bd50b96
2 changed files with 91 additions and 109 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "core/hle/kernel/k_spin_lock.h"
|
#include "core/hle/kernel/k_spin_lock.h"
|
||||||
#include "core/hle/kernel/k_synchronization_object.h"
|
#include "core/hle/kernel/k_synchronization_object.h"
|
||||||
#include "core/hle/kernel/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_common.h"
|
||||||
#include "core/hle/kernel/svc_types.h"
|
#include "core/hle/kernel/svc_types.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
@ -99,7 +100,11 @@ enum class ThreadWaitReasonForDebugging : u32 {
|
||||||
[[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel);
|
[[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel);
|
||||||
[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
|
[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
|
||||||
|
|
||||||
class KThread final : public KSynchronizationObject, public boost::intrusive::list_base_hook<> {
|
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>,
|
||||||
|
public boost::intrusive::list_base_hook<> {
|
||||||
|
KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject);
|
||||||
|
|
||||||
|
private:
|
||||||
friend class KScheduler;
|
friend class KScheduler;
|
||||||
friend class Process;
|
friend class Process;
|
||||||
|
|
||||||
|
@ -115,57 +120,6 @@ public:
|
||||||
using ThreadContext64 = Core::ARM_Interface::ThreadContext64;
|
using ThreadContext64 = Core::ARM_Interface::ThreadContext64;
|
||||||
using WaiterList = boost::intrusive::list<KThread>;
|
using WaiterList = boost::intrusive::list<KThread>;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<std::shared_ptr<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);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<std::shared_ptr<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);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<std::shared_ptr<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);
|
|
||||||
|
|
||||||
[[nodiscard]] std::string GetName() const override {
|
[[nodiscard]] std::string GetName() const override {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -257,10 +211,6 @@ public:
|
||||||
|
|
||||||
void Suspend();
|
void Suspend();
|
||||||
|
|
||||||
void Finalize() override;
|
|
||||||
|
|
||||||
bool IsSignaled() const override;
|
|
||||||
|
|
||||||
void SetSyncedObject(KSynchronizationObject* obj, ResultCode wait_res) {
|
void SetSyncedObject(KSynchronizationObject* obj, ResultCode wait_res) {
|
||||||
synced_object = obj;
|
synced_object = obj;
|
||||||
wait_result = wait_res;
|
wait_result = wait_res;
|
||||||
|
@ -422,6 +372,40 @@ public:
|
||||||
return termination_requested || GetRawState() == ThreadState::Terminated;
|
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<uintptr_t>(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 {
|
struct StackParameters {
|
||||||
u8 svc_permission[0x10];
|
u8 svc_permission[0x10];
|
||||||
std::atomic<u8> dpc_flags;
|
std::atomic<u8> dpc_flags;
|
||||||
|
@ -675,7 +659,9 @@ private:
|
||||||
|
|
||||||
[[nodiscard]] static ResultCode InitializeThread(KThread* thread, KThreadFunction func,
|
[[nodiscard]] static ResultCode InitializeThread(KThread* thread, KThreadFunction func,
|
||||||
uintptr_t arg, VAddr user_stack_top, s32 prio,
|
uintptr_t arg, VAddr user_stack_top, s32 prio,
|
||||||
s32 core, Process* owner, ThreadType type);
|
s32 core, Process* owner, ThreadType type,
|
||||||
|
std::function<void(void*)>&& init_func,
|
||||||
|
void* init_func_parameter);
|
||||||
|
|
||||||
static void RestorePriority(KernelCore& kernel, KThread* thread);
|
static void RestorePriority(KernelCore& kernel, KThread* thread);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue