kernel/process: Make Process a WaitObject
Process instances can be waited upon for state changes. This is also utilized by svcResetSignal, which will be modified in an upcoming change. This simply puts all of the WaitObject related machinery in place.
This commit is contained in:
parent
a3aa7aaf0b
commit
c7462ce712
|
@ -15,6 +15,7 @@ bool Object::IsWaitable() const {
|
||||||
switch (GetHandleType()) {
|
switch (GetHandleType()) {
|
||||||
case HandleType::ReadableEvent:
|
case HandleType::ReadableEvent:
|
||||||
case HandleType::Thread:
|
case HandleType::Thread:
|
||||||
|
case HandleType::Process:
|
||||||
case HandleType::Timer:
|
case HandleType::Timer:
|
||||||
case HandleType::ServerPort:
|
case HandleType::ServerPort:
|
||||||
case HandleType::ServerSession:
|
case HandleType::ServerSession:
|
||||||
|
@ -23,7 +24,6 @@ bool Object::IsWaitable() const {
|
||||||
case HandleType::Unknown:
|
case HandleType::Unknown:
|
||||||
case HandleType::WritableEvent:
|
case HandleType::WritableEvent:
|
||||||
case HandleType::SharedMemory:
|
case HandleType::SharedMemory:
|
||||||
case HandleType::Process:
|
|
||||||
case HandleType::AddressArbiter:
|
case HandleType::AddressArbiter:
|
||||||
case HandleType::ResourceLimit:
|
case HandleType::ResourceLimit:
|
||||||
case HandleType::ClientPort:
|
case HandleType::ClientPort:
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/file_sys/program_metadata.h"
|
#include "core/file_sys/program_metadata.h"
|
||||||
|
#include "core/hle/kernel/errors.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/resource_limit.h"
|
#include "core/hle/kernel/resource_limit.h"
|
||||||
|
@ -48,6 +49,21 @@ SharedPtr<ResourceLimit> Process::GetResourceLimit() const {
|
||||||
return resource_limit;
|
return resource_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultCode Process::ClearSignalState() {
|
||||||
|
if (status == ProcessStatus::Exited) {
|
||||||
|
LOG_ERROR(Kernel, "called on a terminated process instance.");
|
||||||
|
return ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_signaled) {
|
||||||
|
LOG_ERROR(Kernel, "called on a process instance that isn't signaled.");
|
||||||
|
return ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_signaled = false;
|
||||||
|
return RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
|
void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
|
||||||
program_id = metadata.GetTitleID();
|
program_id = metadata.GetTitleID();
|
||||||
is_64bit_process = metadata.Is64BitProgram();
|
is_64bit_process = metadata.Is64BitProgram();
|
||||||
|
@ -137,13 +153,13 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
|
||||||
.Unwrap();
|
.Unwrap();
|
||||||
|
|
||||||
vm_manager.LogLayout();
|
vm_manager.LogLayout();
|
||||||
status = ProcessStatus::Running;
|
ChangeStatus(ProcessStatus::Running);
|
||||||
|
|
||||||
Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this);
|
Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::PrepareForTermination() {
|
void Process::PrepareForTermination() {
|
||||||
status = ProcessStatus::Exited;
|
ChangeStatus(ProcessStatus::Exiting);
|
||||||
|
|
||||||
const auto stop_threads = [this](const std::vector<SharedPtr<Thread>>& thread_list) {
|
const auto stop_threads = [this](const std::vector<SharedPtr<Thread>>& thread_list) {
|
||||||
for (auto& thread : thread_list) {
|
for (auto& thread : thread_list) {
|
||||||
|
@ -167,6 +183,8 @@ void Process::PrepareForTermination() {
|
||||||
stop_threads(system.Scheduler(1).GetThreadList());
|
stop_threads(system.Scheduler(1).GetThreadList());
|
||||||
stop_threads(system.Scheduler(2).GetThreadList());
|
stop_threads(system.Scheduler(2).GetThreadList());
|
||||||
stop_threads(system.Scheduler(3).GetThreadList());
|
stop_threads(system.Scheduler(3).GetThreadList());
|
||||||
|
|
||||||
|
ChangeStatus(ProcessStatus::Exited);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -265,7 +283,25 @@ ResultCode Process::UnmapMemory(VAddr dst_addr, VAddr /*src_addr*/, u64 size) {
|
||||||
return vm_manager.UnmapRange(dst_addr, size);
|
return vm_manager.UnmapRange(dst_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::Process::Process(KernelCore& kernel) : Object{kernel} {}
|
Kernel::Process::Process(KernelCore& kernel) : WaitObject{kernel} {}
|
||||||
Kernel::Process::~Process() {}
|
Kernel::Process::~Process() {}
|
||||||
|
|
||||||
|
void Process::Acquire(Thread* thread) {
|
||||||
|
ASSERT_MSG(!ShouldWait(thread), "Object unavailable!");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Process::ShouldWait(Thread* thread) const {
|
||||||
|
return !is_signaled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process::ChangeStatus(ProcessStatus new_status) {
|
||||||
|
if (status == new_status) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = new_status;
|
||||||
|
is_signaled = true;
|
||||||
|
WakeupAllWaitingThreads();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -14,9 +14,10 @@
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/object.h"
|
|
||||||
#include "core/hle/kernel/thread.h"
|
#include "core/hle/kernel/thread.h"
|
||||||
#include "core/hle/kernel/vm_manager.h"
|
#include "core/hle/kernel/vm_manager.h"
|
||||||
|
#include "core/hle/kernel/wait_object.h"
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
class ProgramMetadata;
|
class ProgramMetadata;
|
||||||
|
@ -117,7 +118,7 @@ struct CodeSet final {
|
||||||
VAddr entrypoint = 0;
|
VAddr entrypoint = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Process final : public Object {
|
class Process final : public WaitObject {
|
||||||
public:
|
public:
|
||||||
static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4;
|
static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4;
|
||||||
|
|
||||||
|
@ -212,6 +213,16 @@ public:
|
||||||
return random_entropy.at(index);
|
return random_entropy.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clears the signaled state of the process if and only if it's signaled.
|
||||||
|
///
|
||||||
|
/// @pre The process must not be already terminated. If this is called on a
|
||||||
|
/// terminated process, then ERR_INVALID_STATE will be returned.
|
||||||
|
///
|
||||||
|
/// @pre The process must be in a signaled state. If this is called on a
|
||||||
|
/// process instance that is not signaled, ERR_INVALID_STATE will be
|
||||||
|
/// returned.
|
||||||
|
ResultCode ClearSignalState();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads process-specifics configuration info with metadata provided
|
* Loads process-specifics configuration info with metadata provided
|
||||||
* by an executable.
|
* by an executable.
|
||||||
|
@ -260,6 +271,17 @@ private:
|
||||||
explicit Process(KernelCore& kernel);
|
explicit Process(KernelCore& kernel);
|
||||||
~Process() override;
|
~Process() override;
|
||||||
|
|
||||||
|
/// Checks if the specified thread should wait until this process is available.
|
||||||
|
bool ShouldWait(Thread* thread) const override;
|
||||||
|
|
||||||
|
/// Acquires/locks this process for the specified thread if it's available.
|
||||||
|
void Acquire(Thread* thread) override;
|
||||||
|
|
||||||
|
/// Changes the process status. If the status is different
|
||||||
|
/// from the current process status, then this will trigger
|
||||||
|
/// a process signal.
|
||||||
|
void ChangeStatus(ProcessStatus new_status);
|
||||||
|
|
||||||
/// Memory manager for this process.
|
/// Memory manager for this process.
|
||||||
Kernel::VMManager vm_manager;
|
Kernel::VMManager vm_manager;
|
||||||
|
|
||||||
|
@ -305,6 +327,10 @@ private:
|
||||||
/// specified by metadata provided to the process during loading.
|
/// specified by metadata provided to the process during loading.
|
||||||
bool is_64bit_process = true;
|
bool is_64bit_process = true;
|
||||||
|
|
||||||
|
/// Whether or not this process is signaled. This occurs
|
||||||
|
/// upon the process changing to a different state.
|
||||||
|
bool is_signaled = false;
|
||||||
|
|
||||||
/// Total running time for the process in ticks.
|
/// Total running time for the process in ticks.
|
||||||
u64 total_process_running_time_ticks = 0;
|
u64 total_process_running_time_ticks = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue