aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/hle/service/os
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/os')
-rw-r--r--src/core/hle/service/os/process.cpp152
-rw-r--r--src/core/hle/service/os/process.h58
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