diff options
Diffstat (limited to 'src/core/hle/service/os')
-rw-r--r-- | src/core/hle/service/os/process.cpp | 152 | ||||
-rw-r--r-- | src/core/hle/service/os/process.h | 58 |
2 files changed, 210 insertions, 0 deletions
diff --git a/src/core/hle/service/os/process.cpp b/src/core/hle/service/os/process.cpp new file mode 100644 index 000000000..0dbadc315 --- /dev/null +++ b/src/core/hle/service/os/process.cpp @@ -0,0 +1,152 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/scope_exit.h" + +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/svc_types.h" +#include "core/hle/service/os/process.h" +#include "core/loader/loader.h" + +namespace Service { + +Process::Process(Core::System& system) + : m_system(system), m_process(), m_main_thread_priority(), m_main_thread_stack_size(), + m_process_started() {} + +Process::~Process() { + this->Finalize(); +} + +bool Process::Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_load_result) { + // First, ensure we are not holding another process. + this->Finalize(); + + // Create the process. + auto* const process = Kernel::KProcess::Create(m_system.Kernel()); + Kernel::KProcess::Register(m_system.Kernel(), process); + + // On exit, ensure we free the additional reference to the process. + SCOPE_EXIT { + process->Close(); + }; + + // Insert process modules into memory. + const auto [load_result, load_parameters] = loader.Load(*process, m_system); + out_load_result = load_result; + + // Ensure loading was successful. + if (load_result != Loader::ResultStatus::Success) { + return false; + } + + // TODO: remove this, kernel already tracks this + m_system.Kernel().AppendNewProcess(process); + + // Note the load parameters from NPDM. + m_main_thread_priority = load_parameters->main_thread_priority; + m_main_thread_stack_size = load_parameters->main_thread_stack_size; + + // This process has not started yet. + m_process_started = false; + + // Take ownership of the process object. + m_process = process; + m_process->Open(); + + // We succeeded. + return true; +} + +void Process::Finalize() { + // Terminate, if we are currently holding a process. + this->Terminate(); + + // Close the process. + if (m_process) { + m_process->Close(); + + // TODO: remove this, kernel already tracks this + m_system.Kernel().RemoveProcess(m_process); + } + + // Clean up. + m_process = nullptr; + m_main_thread_priority = 0; + m_main_thread_stack_size = 0; + m_process_started = false; +} + +bool Process::Run() { + // If we already started the process, don't start again. + if (m_process_started) { + return false; + } + + // Start. + if (m_process) { + m_process->Run(m_main_thread_priority, m_main_thread_stack_size); + } + + // Mark as started. + m_process_started = true; + + // We succeeded. + return true; +} + +void Process::Terminate() { + if (m_process) { + m_process->Terminate(); + } +} + +void Process::ResetSignal() { + if (m_process) { + m_process->Reset(); + } +} + +bool Process::IsRunning() const { + if (m_process) { + const auto state = m_process->GetState(); + return state == Kernel::KProcess::State::Running || + state == Kernel::KProcess::State::RunningAttached || + state == Kernel::KProcess::State::DebugBreak; + } + + return false; +} + +bool Process::IsTerminated() const { + if (m_process) { + return m_process->IsTerminated(); + } + + return false; +} + +u64 Process::GetProcessId() const { + if (m_process) { + return m_process->GetProcessId(); + } + + return 0; +} + +u64 Process::GetProgramId() const { + if (m_process) { + return m_process->GetProgramId(); + } + + return 0; +} + +void Process::Suspend(bool suspended) { + if (m_process) { + m_process->SetActivity(suspended ? Kernel::Svc::ProcessActivity::Paused + : Kernel::Svc::ProcessActivity::Runnable); + } +} + +} // namespace Service diff --git a/src/core/hle/service/os/process.h b/src/core/hle/service/os/process.h new file mode 100644 index 000000000..9109b7d0a --- /dev/null +++ b/src/core/hle/service/os/process.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_types.h" + +namespace Core { +class System; +} + +namespace Loader { +class AppLoader; +enum class ResultStatus : u16; +} // namespace Loader + +namespace Kernel { +class KProcess; +} + +namespace Service { + +class Process { +public: + explicit Process(Core::System& system); + ~Process(); + + bool Initialize(Loader::AppLoader& loader, Loader::ResultStatus& out_load_result); + void Finalize(); + + bool Run(); + void Terminate(); + void Suspend(bool suspended); + void ResetSignal(); + + bool IsInitialized() const { + return m_process != nullptr; + } + + bool IsRunning() const; + bool IsTerminated() const; + + u64 GetProcessId() const; + u64 GetProgramId() const; + + Kernel::KProcess* GetHandle() const { + return m_process; + } + +private: + Core::System& m_system; + Kernel::KProcess* m_process{}; + s32 m_main_thread_priority{}; + u64 m_main_thread_stack_size{}; + bool m_process_started{}; +}; + +} // namespace Service |