153 lines
3.6 KiB
C++
153 lines
3.6 KiB
C++
|
// 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
|