diff options
| author | 2018-12-03 12:25:27 -0500 | |
|---|---|---|
| committer | 2018-12-04 01:23:50 -0500 | |
| commit | 3e75175d0242090902e4b383086e3f5ac6cf3f73 (patch) | |
| tree | c6ff5eb9787f21284a5748ad210c866d32e04bcd /src/core/hle/kernel | |
| parent | Merge pull request #1852 from VPeruS/fix-format-string (diff) | |
| download | yuzu-3e75175d0242090902e4b383086e3f5ac6cf3f73.tar.gz yuzu-3e75175d0242090902e4b383086e3f5ac6cf3f73.tar.xz yuzu-3e75175d0242090902e4b383086e3f5ac6cf3f73.zip | |
svc: Implement SetThreadActivity (thread suspension)
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/errors.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 38 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 24 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 14 |
4 files changed, 72 insertions, 6 deletions
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h index 8b58d701d..d8240ec6d 100644 --- a/src/core/hle/kernel/errors.h +++ b/src/core/hle/kernel/errors.h | |||
| @@ -27,7 +27,7 @@ constexpr ResultCode ERR_SYNCHRONIZATION_CANCELED{ErrorModule::Kernel, 118}; | |||
| 27 | constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119}; | 27 | constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119}; |
| 28 | constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120}; | 28 | constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120}; |
| 29 | constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121}; | 29 | constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121}; |
| 30 | constexpr ResultCode ERR_ALREADY_REGISTERED{ErrorModule::Kernel, 122}; | 30 | constexpr ResultCode ERR_BUSY{ErrorModule::Kernel, 122}; |
| 31 | constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE{ErrorModule::Kernel, 123}; | 31 | constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE{ErrorModule::Kernel, 123}; |
| 32 | constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125}; | 32 | constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125}; |
| 33 | constexpr ResultCode ERR_RESOURCE_LIMIT_EXCEEDED{ErrorModule::Kernel, 132}; | 33 | constexpr ResultCode ERR_RESOURCE_LIMIT_EXCEEDED{ErrorModule::Kernel, 132}; |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 948989b31..72da3eb3d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -851,8 +851,35 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 851 | } | 851 | } |
| 852 | 852 | ||
| 853 | /// Sets the thread activity | 853 | /// Sets the thread activity |
| 854 | static ResultCode SetThreadActivity(Handle handle, u32 unknown) { | 854 | static ResultCode SetThreadActivity(Handle handle, u32 activity) { |
| 855 | LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}, unknown=0x{:08X}", handle, unknown); | 855 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity); |
| 856 | if (activity > static_cast<u32>(ThreadActivity::Paused)) { | ||
| 857 | return ERR_INVALID_ENUM_VALUE; | ||
| 858 | } | ||
| 859 | |||
| 860 | const auto* current_process = Core::CurrentProcess(); | ||
| 861 | const SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle); | ||
| 862 | if (!thread) { | ||
| 863 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); | ||
| 864 | return ERR_INVALID_HANDLE; | ||
| 865 | } | ||
| 866 | |||
| 867 | if (thread->GetOwnerProcess() != current_process) { | ||
| 868 | LOG_ERROR(Kernel_SVC, | ||
| 869 | "The current process does not own the current thread, thread_handle={:08X} " | ||
| 870 | "thread_pid={}, " | ||
| 871 | "current_process_pid={}", | ||
| 872 | handle, thread->GetOwnerProcess()->GetProcessID(), | ||
| 873 | current_process->GetProcessID()); | ||
| 874 | return ERR_INVALID_HANDLE; | ||
| 875 | } | ||
| 876 | |||
| 877 | if (thread == GetCurrentThread()) { | ||
| 878 | LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); | ||
| 879 | return ERR_BUSY; | ||
| 880 | } | ||
| 881 | |||
| 882 | thread->SetActivity(static_cast<ThreadActivity>(activity)); | ||
| 856 | return RESULT_SUCCESS; | 883 | return RESULT_SUCCESS; |
| 857 | } | 884 | } |
| 858 | 885 | ||
| @@ -879,7 +906,7 @@ static ResultCode GetThreadContext(VAddr thread_context, Handle handle) { | |||
| 879 | 906 | ||
| 880 | if (thread == GetCurrentThread()) { | 907 | if (thread == GetCurrentThread()) { |
| 881 | LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); | 908 | LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); |
| 882 | return ERR_ALREADY_REGISTERED; | 909 | return ERR_BUSY; |
| 883 | } | 910 | } |
| 884 | 911 | ||
| 885 | Core::ARM_Interface::ThreadContext ctx = thread->GetContext(); | 912 | Core::ARM_Interface::ThreadContext ctx = thread->GetContext(); |
| @@ -1157,7 +1184,10 @@ static ResultCode StartThread(Handle thread_handle) { | |||
| 1157 | ASSERT(thread->GetStatus() == ThreadStatus::Dormant); | 1184 | ASSERT(thread->GetStatus() == ThreadStatus::Dormant); |
| 1158 | 1185 | ||
| 1159 | thread->ResumeFromWait(); | 1186 | thread->ResumeFromWait(); |
| 1160 | Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule(); | 1187 | |
| 1188 | if (thread->GetStatus() == ThreadStatus::Ready) { | ||
| 1189 | Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule(); | ||
| 1190 | } | ||
| 1161 | 1191 | ||
| 1162 | return RESULT_SUCCESS; | 1192 | return RESULT_SUCCESS; |
| 1163 | } | 1193 | } |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 4ffb76818..748c45dd7 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -50,7 +50,7 @@ void Thread::Stop() { | |||
| 50 | 50 | ||
| 51 | // Clean up thread from ready queue | 51 | // Clean up thread from ready queue |
| 52 | // This is only needed when the thread is terminated forcefully (SVC TerminateProcess) | 52 | // This is only needed when the thread is terminated forcefully (SVC TerminateProcess) |
| 53 | if (status == ThreadStatus::Ready) { | 53 | if (status == ThreadStatus::Ready || status == ThreadStatus::Paused) { |
| 54 | scheduler->UnscheduleThread(this, current_priority); | 54 | scheduler->UnscheduleThread(this, current_priority); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| @@ -140,6 +140,11 @@ void Thread::ResumeFromWait() { | |||
| 140 | 140 | ||
| 141 | wakeup_callback = nullptr; | 141 | wakeup_callback = nullptr; |
| 142 | 142 | ||
| 143 | if (activity == ThreadActivity::Paused) { | ||
| 144 | status = ThreadStatus::Paused; | ||
| 145 | return; | ||
| 146 | } | ||
| 147 | |||
| 143 | status = ThreadStatus::Ready; | 148 | status = ThreadStatus::Ready; |
| 144 | 149 | ||
| 145 | ChangeScheduler(); | 150 | ChangeScheduler(); |
| @@ -388,6 +393,23 @@ bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> t | |||
| 388 | return wakeup_callback(reason, std::move(thread), std::move(object), index); | 393 | return wakeup_callback(reason, std::move(thread), std::move(object), index); |
| 389 | } | 394 | } |
| 390 | 395 | ||
| 396 | void Thread::SetActivity(ThreadActivity value) { | ||
| 397 | activity = value; | ||
| 398 | |||
| 399 | if (value == ThreadActivity::Paused) { | ||
| 400 | // Set status if not waiting | ||
| 401 | if (status == ThreadStatus::Ready) { | ||
| 402 | status = ThreadStatus::Paused; | ||
| 403 | } else if (status == ThreadStatus::Running) { | ||
| 404 | status = ThreadStatus::Paused; | ||
| 405 | Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); | ||
| 406 | } | ||
| 407 | } else if (status == ThreadStatus::Paused) { | ||
| 408 | // Ready to reschedule | ||
| 409 | ResumeFromWait(); | ||
| 410 | } | ||
| 411 | } | ||
| 412 | |||
| 391 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 413 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 392 | 414 | ||
| 393 | /** | 415 | /** |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index d384d50db..268bf845b 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -44,6 +44,7 @@ enum ThreadProcessorId : s32 { | |||
| 44 | enum class ThreadStatus { | 44 | enum class ThreadStatus { |
| 45 | Running, ///< Currently running | 45 | Running, ///< Currently running |
| 46 | Ready, ///< Ready to run | 46 | Ready, ///< Ready to run |
| 47 | Paused, ///< Paused by SetThreadActivity or debug | ||
| 47 | WaitHLEEvent, ///< Waiting for hle event to finish | 48 | WaitHLEEvent, ///< Waiting for hle event to finish |
| 48 | WaitSleep, ///< Waiting due to a SleepThread SVC | 49 | WaitSleep, ///< Waiting due to a SleepThread SVC |
| 49 | WaitIPC, ///< Waiting for the reply from an IPC request | 50 | WaitIPC, ///< Waiting for the reply from an IPC request |
| @@ -60,6 +61,11 @@ enum class ThreadWakeupReason { | |||
| 60 | Timeout // The thread was woken up due to a wait timeout. | 61 | Timeout // The thread was woken up due to a wait timeout. |
| 61 | }; | 62 | }; |
| 62 | 63 | ||
| 64 | enum class ThreadActivity : u32 { | ||
| 65 | Normal = 0, | ||
| 66 | Paused = 1, | ||
| 67 | }; | ||
| 68 | |||
| 63 | class Thread final : public WaitObject { | 69 | class Thread final : public WaitObject { |
| 64 | public: | 70 | public: |
| 65 | using TLSMemory = std::vector<u8>; | 71 | using TLSMemory = std::vector<u8>; |
| @@ -370,6 +376,12 @@ public: | |||
| 370 | return affinity_mask; | 376 | return affinity_mask; |
| 371 | } | 377 | } |
| 372 | 378 | ||
| 379 | ThreadActivity GetActivity() const { | ||
| 380 | return activity; | ||
| 381 | } | ||
| 382 | |||
| 383 | void SetActivity(ThreadActivity value); | ||
| 384 | |||
| 373 | private: | 385 | private: |
| 374 | explicit Thread(KernelCore& kernel); | 386 | explicit Thread(KernelCore& kernel); |
| 375 | ~Thread() override; | 387 | ~Thread() override; |
| @@ -438,6 +450,8 @@ private: | |||
| 438 | TLSMemoryPtr tls_memory = std::make_shared<TLSMemory>(); | 450 | TLSMemoryPtr tls_memory = std::make_shared<TLSMemory>(); |
| 439 | 451 | ||
| 440 | std::string name; | 452 | std::string name; |
| 453 | |||
| 454 | ThreadActivity activity = ThreadActivity::Normal; | ||
| 441 | }; | 455 | }; |
| 442 | 456 | ||
| 443 | /** | 457 | /** |