diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/object.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 42 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 30 |
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 | ||
| 52 | ResultCode 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 | |||
| 51 | void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { | 67 | void 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 | ||
| 145 | void Process::PrepareForTermination() { | 161 | void 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 | ||
| 268 | Kernel::Process::Process(KernelCore& kernel) : Object{kernel} {} | 286 | Kernel::Process::Process(KernelCore& kernel) : WaitObject{kernel} {} |
| 269 | Kernel::Process::~Process() {} | 287 | Kernel::Process::~Process() {} |
| 270 | 288 | ||
| 289 | void Process::Acquire(Thread* thread) { | ||
| 290 | ASSERT_MSG(!ShouldWait(thread), "Object unavailable!"); | ||
| 291 | } | ||
| 292 | |||
| 293 | bool Process::ShouldWait(Thread* thread) const { | ||
| 294 | return !is_signaled; | ||
| 295 | } | ||
| 296 | |||
| 297 | void 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 | ||
| 21 | namespace FileSys { | 22 | namespace FileSys { |
| 22 | class ProgramMetadata; | 23 | class ProgramMetadata; |
| @@ -117,7 +118,7 @@ struct CodeSet final { | |||
| 117 | VAddr entrypoint = 0; | 118 | VAddr entrypoint = 0; |
| 118 | }; | 119 | }; |
| 119 | 120 | ||
| 120 | class Process final : public Object { | 121 | class Process final : public WaitObject { |
| 121 | public: | 122 | public: |
| 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 | ||