summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Lioncash2018-12-04 19:08:56 -0500
committerGravatar Lioncash2018-12-04 20:14:59 -0500
commitc7462ce71241fe6c8dfee48a859c63a6b1fd84fb (patch)
tree0350cdf3dcb0cae57573b7b2d869875c16f9b840
parentkernel/readable_event: Add member function for enforcing a strict reset contract (diff)
downloadyuzu-c7462ce71241fe6c8dfee48a859c63a6b1fd84fb.tar.gz
yuzu-c7462ce71241fe6c8dfee48a859c63a6b1fd84fb.tar.xz
yuzu-c7462ce71241fe6c8dfee48a859c63a6b1fd84fb.zip
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.
-rw-r--r--src/core/hle/kernel/object.cpp2
-rw-r--r--src/core/hle/kernel/process.cpp42
-rw-r--r--src/core/hle/kernel/process.h30
3 files changed, 68 insertions, 6 deletions
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index bb1b68778..0ea851a74 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -15,6 +15,7 @@ bool Object::IsWaitable() const {
15 switch (GetHandleType()) { 15 switch (GetHandleType()) {
16 case HandleType::ReadableEvent: 16 case HandleType::ReadableEvent:
17 case HandleType::Thread: 17 case HandleType::Thread:
18 case HandleType::Process:
18 case HandleType::Timer: 19 case HandleType::Timer:
19 case HandleType::ServerPort: 20 case HandleType::ServerPort:
20 case HandleType::ServerSession: 21 case HandleType::ServerSession:
@@ -23,7 +24,6 @@ bool Object::IsWaitable() const {
23 case HandleType::Unknown: 24 case HandleType::Unknown:
24 case HandleType::WritableEvent: 25 case HandleType::WritableEvent:
25 case HandleType::SharedMemory: 26 case HandleType::SharedMemory:
26 case HandleType::Process:
27 case HandleType::AddressArbiter: 27 case HandleType::AddressArbiter:
28 case HandleType::ResourceLimit: 28 case HandleType::ResourceLimit:
29 case HandleType::ClientPort: 29 case HandleType::ClientPort:
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 4ecb8c926..211bf6686 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -9,6 +9,7 @@
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/file_sys/program_metadata.h" 11#include "core/file_sys/program_metadata.h"
12#include "core/hle/kernel/errors.h"
12#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/process.h" 14#include "core/hle/kernel/process.h"
14#include "core/hle/kernel/resource_limit.h" 15#include "core/hle/kernel/resource_limit.h"
@@ -48,6 +49,21 @@ SharedPtr<ResourceLimit> Process::GetResourceLimit() const {
48 return resource_limit; 49 return resource_limit;
49} 50}
50 51
52ResultCode Process::ClearSignalState() {
53 if (status == ProcessStatus::Exited) {
54 LOG_ERROR(Kernel, "called on a terminated process instance.");
55 return ERR_INVALID_STATE;
56 }
57
58 if (!is_signaled) {
59 LOG_ERROR(Kernel, "called on a process instance that isn't signaled.");
60 return ERR_INVALID_STATE;
61 }
62
63 is_signaled = false;
64 return RESULT_SUCCESS;
65}
66
51void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { 67void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
52 program_id = metadata.GetTitleID(); 68 program_id = metadata.GetTitleID();
53 is_64bit_process = metadata.Is64BitProgram(); 69 is_64bit_process = metadata.Is64BitProgram();
@@ -137,13 +153,13 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
137 .Unwrap(); 153 .Unwrap();
138 154
139 vm_manager.LogLayout(); 155 vm_manager.LogLayout();
140 status = ProcessStatus::Running; 156 ChangeStatus(ProcessStatus::Running);
141 157
142 Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this); 158 Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this);
143} 159}
144 160
145void Process::PrepareForTermination() { 161void Process::PrepareForTermination() {
146 status = ProcessStatus::Exited; 162 ChangeStatus(ProcessStatus::Exiting);
147 163
148 const auto stop_threads = [this](const std::vector<SharedPtr<Thread>>& thread_list) { 164 const auto stop_threads = [this](const std::vector<SharedPtr<Thread>>& thread_list) {
149 for (auto& thread : thread_list) { 165 for (auto& thread : thread_list) {
@@ -167,6 +183,8 @@ void Process::PrepareForTermination() {
167 stop_threads(system.Scheduler(1).GetThreadList()); 183 stop_threads(system.Scheduler(1).GetThreadList());
168 stop_threads(system.Scheduler(2).GetThreadList()); 184 stop_threads(system.Scheduler(2).GetThreadList());
169 stop_threads(system.Scheduler(3).GetThreadList()); 185 stop_threads(system.Scheduler(3).GetThreadList());
186
187 ChangeStatus(ProcessStatus::Exited);
170} 188}
171 189
172/** 190/**
@@ -265,7 +283,25 @@ ResultCode Process::UnmapMemory(VAddr dst_addr, VAddr /*src_addr*/, u64 size) {
265 return vm_manager.UnmapRange(dst_addr, size); 283 return vm_manager.UnmapRange(dst_addr, size);
266} 284}
267 285
268Kernel::Process::Process(KernelCore& kernel) : Object{kernel} {} 286Kernel::Process::Process(KernelCore& kernel) : WaitObject{kernel} {}
269Kernel::Process::~Process() {} 287Kernel::Process::~Process() {}
270 288
289void Process::Acquire(Thread* thread) {
290 ASSERT_MSG(!ShouldWait(thread), "Object unavailable!");
291}
292
293bool Process::ShouldWait(Thread* thread) const {
294 return !is_signaled;
295}
296
297void Process::ChangeStatus(ProcessStatus new_status) {
298 if (status == new_status) {
299 return;
300 }
301
302 status = new_status;
303 is_signaled = true;
304 WakeupAllWaitingThreads();
305}
306
271} // namespace Kernel 307} // namespace Kernel
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 49345aa66..bcb9ac4b8 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -14,9 +14,10 @@
14#include "common/bit_field.h" 14#include "common/bit_field.h"
15#include "common/common_types.h" 15#include "common/common_types.h"
16#include "core/hle/kernel/handle_table.h" 16#include "core/hle/kernel/handle_table.h"
17#include "core/hle/kernel/object.h"
18#include "core/hle/kernel/thread.h" 17#include "core/hle/kernel/thread.h"
19#include "core/hle/kernel/vm_manager.h" 18#include "core/hle/kernel/vm_manager.h"
19#include "core/hle/kernel/wait_object.h"
20#include "core/hle/result.h"
20 21
21namespace FileSys { 22namespace FileSys {
22class ProgramMetadata; 23class ProgramMetadata;
@@ -117,7 +118,7 @@ struct CodeSet final {
117 VAddr entrypoint = 0; 118 VAddr entrypoint = 0;
118}; 119};
119 120
120class Process final : public Object { 121class Process final : public WaitObject {
121public: 122public:
122 static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; 123 static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4;
123 124
@@ -212,6 +213,16 @@ public:
212 return random_entropy.at(index); 213 return random_entropy.at(index);
213 } 214 }
214 215
216 /// Clears the signaled state of the process if and only if it's signaled.
217 ///
218 /// @pre The process must not be already terminated. If this is called on a
219 /// terminated process, then ERR_INVALID_STATE will be returned.
220 ///
221 /// @pre The process must be in a signaled state. If this is called on a
222 /// process instance that is not signaled, ERR_INVALID_STATE will be
223 /// returned.
224 ResultCode ClearSignalState();
225
215 /** 226 /**
216 * Loads process-specifics configuration info with metadata provided 227 * Loads process-specifics configuration info with metadata provided
217 * by an executable. 228 * by an executable.
@@ -260,6 +271,17 @@ private:
260 explicit Process(KernelCore& kernel); 271 explicit Process(KernelCore& kernel);
261 ~Process() override; 272 ~Process() override;
262 273
274 /// Checks if the specified thread should wait until this process is available.
275 bool ShouldWait(Thread* thread) const override;
276
277 /// Acquires/locks this process for the specified thread if it's available.
278 void Acquire(Thread* thread) override;
279
280 /// Changes the process status. If the status is different
281 /// from the current process status, then this will trigger
282 /// a process signal.
283 void ChangeStatus(ProcessStatus new_status);
284
263 /// Memory manager for this process. 285 /// Memory manager for this process.
264 Kernel::VMManager vm_manager; 286 Kernel::VMManager vm_manager;
265 287
@@ -305,6 +327,10 @@ private:
305 /// specified by metadata provided to the process during loading. 327 /// specified by metadata provided to the process during loading.
306 bool is_64bit_process = true; 328 bool is_64bit_process = true;
307 329
330 /// Whether or not this process is signaled. This occurs
331 /// upon the process changing to a different state.
332 bool is_signaled = false;
333
308 /// Total running time for the process in ticks. 334 /// Total running time for the process in ticks.
309 u64 total_process_running_time_ticks = 0; 335 u64 total_process_running_time_ticks = 0;
310 336