mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-07-07 03:57:53 -05:00
Merge yuzu-emu#13018
This commit is contained in:
152
src/core/hle/service/os/process.cpp
Normal file
152
src/core/hle/service/os/process.cpp
Normal file
@ -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
|
58
src/core/hle/service/os/process.h
Normal file
58
src/core/hle/service/os/process.h
Normal file
@ -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
|
Reference in New Issue
Block a user