diff options
| author | 2018-12-26 15:54:14 -0500 | |
|---|---|---|
| committer | 2018-12-26 15:54:14 -0500 | |
| commit | ae582b6669eed99e66829b1941152f0b8b073128 (patch) | |
| tree | 5aa768c110f6876823a61d31193cca58c103ddc6 /src/core | |
| parent | Merge pull request #1943 from ReinUsesLisp/fixup-texs (diff) | |
| parent | debugger: Set paused thread color (diff) | |
| download | yuzu-ae582b6669eed99e66829b1941152f0b8b073128.tar.gz yuzu-ae582b6669eed99e66829b1941152f0b8b073128.tar.xz yuzu-ae582b6669eed99e66829b1941152f0b8b073128.zip | |
Merge pull request #1849 from encounter/svcSetThreadActivity
svc: Implement SetThreadActivity (thread suspension)
Diffstat (limited to 'src/core')
| -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 28268e112..2e80b48c2 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -932,8 +932,35 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 932 | } | 932 | } |
| 933 | 933 | ||
| 934 | /// Sets the thread activity | 934 | /// Sets the thread activity |
| 935 | static ResultCode SetThreadActivity(Handle handle, u32 unknown) { | 935 | static ResultCode SetThreadActivity(Handle handle, u32 activity) { |
| 936 | LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}, unknown=0x{:08X}", handle, unknown); | 936 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity); |
| 937 | if (activity > static_cast<u32>(ThreadActivity::Paused)) { | ||
| 938 | return ERR_INVALID_ENUM_VALUE; | ||
| 939 | } | ||
| 940 | |||
| 941 | const auto* current_process = Core::CurrentProcess(); | ||
| 942 | const SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle); | ||
| 943 | if (!thread) { | ||
| 944 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); | ||
| 945 | return ERR_INVALID_HANDLE; | ||
| 946 | } | ||
| 947 | |||
| 948 | if (thread->GetOwnerProcess() != current_process) { | ||
| 949 | LOG_ERROR(Kernel_SVC, | ||
| 950 | "The current process does not own the current thread, thread_handle={:08X} " | ||
| 951 | "thread_pid={}, " | ||
| 952 | "current_process_pid={}", | ||
| 953 | handle, thread->GetOwnerProcess()->GetProcessID(), | ||
| 954 | current_process->GetProcessID()); | ||
| 955 | return ERR_INVALID_HANDLE; | ||
| 956 | } | ||
| 957 | |||
| 958 | if (thread == GetCurrentThread()) { | ||
| 959 | LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); | ||
| 960 | return ERR_BUSY; | ||
| 961 | } | ||
| 962 | |||
| 963 | thread->SetActivity(static_cast<ThreadActivity>(activity)); | ||
| 937 | return RESULT_SUCCESS; | 964 | return RESULT_SUCCESS; |
| 938 | } | 965 | } |
| 939 | 966 | ||
| @@ -960,7 +987,7 @@ static ResultCode GetThreadContext(VAddr thread_context, Handle handle) { | |||
| 960 | 987 | ||
| 961 | if (thread == GetCurrentThread()) { | 988 | if (thread == GetCurrentThread()) { |
| 962 | LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); | 989 | LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); |
| 963 | return ERR_ALREADY_REGISTERED; | 990 | return ERR_BUSY; |
| 964 | } | 991 | } |
| 965 | 992 | ||
| 966 | Core::ARM_Interface::ThreadContext ctx = thread->GetContext(); | 993 | Core::ARM_Interface::ThreadContext ctx = thread->GetContext(); |
| @@ -1245,7 +1272,10 @@ static ResultCode StartThread(Handle thread_handle) { | |||
| 1245 | ASSERT(thread->GetStatus() == ThreadStatus::Dormant); | 1272 | ASSERT(thread->GetStatus() == ThreadStatus::Dormant); |
| 1246 | 1273 | ||
| 1247 | thread->ResumeFromWait(); | 1274 | thread->ResumeFromWait(); |
| 1248 | Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule(); | 1275 | |
| 1276 | if (thread->GetStatus() == ThreadStatus::Ready) { | ||
| 1277 | Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule(); | ||
| 1278 | } | ||
| 1249 | 1279 | ||
| 1250 | return RESULT_SUCCESS; | 1280 | return RESULT_SUCCESS; |
| 1251 | } | 1281 | } |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 63f8923fd..434655638 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(); |
| @@ -391,6 +396,23 @@ bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> t | |||
| 391 | return wakeup_callback(reason, std::move(thread), std::move(object), index); | 396 | return wakeup_callback(reason, std::move(thread), std::move(object), index); |
| 392 | } | 397 | } |
| 393 | 398 | ||
| 399 | void Thread::SetActivity(ThreadActivity value) { | ||
| 400 | activity = value; | ||
| 401 | |||
| 402 | if (value == ThreadActivity::Paused) { | ||
| 403 | // Set status if not waiting | ||
| 404 | if (status == ThreadStatus::Ready) { | ||
| 405 | status = ThreadStatus::Paused; | ||
| 406 | } else if (status == ThreadStatus::Running) { | ||
| 407 | status = ThreadStatus::Paused; | ||
| 408 | Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); | ||
| 409 | } | ||
| 410 | } else if (status == ThreadStatus::Paused) { | ||
| 411 | // Ready to reschedule | ||
| 412 | ResumeFromWait(); | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 394 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 416 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 395 | 417 | ||
| 396 | /** | 418 | /** |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index d6e7981d3..fe5398d56 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -45,6 +45,7 @@ enum ThreadProcessorId : s32 { | |||
| 45 | enum class ThreadStatus { | 45 | enum class ThreadStatus { |
| 46 | Running, ///< Currently running | 46 | Running, ///< Currently running |
| 47 | Ready, ///< Ready to run | 47 | Ready, ///< Ready to run |
| 48 | Paused, ///< Paused by SetThreadActivity or debug | ||
| 48 | WaitHLEEvent, ///< Waiting for hle event to finish | 49 | WaitHLEEvent, ///< Waiting for hle event to finish |
| 49 | WaitSleep, ///< Waiting due to a SleepThread SVC | 50 | WaitSleep, ///< Waiting due to a SleepThread SVC |
| 50 | WaitIPC, ///< Waiting for the reply from an IPC request | 51 | WaitIPC, ///< Waiting for the reply from an IPC request |
| @@ -61,6 +62,11 @@ enum class ThreadWakeupReason { | |||
| 61 | Timeout // The thread was woken up due to a wait timeout. | 62 | Timeout // The thread was woken up due to a wait timeout. |
| 62 | }; | 63 | }; |
| 63 | 64 | ||
| 65 | enum class ThreadActivity : u32 { | ||
| 66 | Normal = 0, | ||
| 67 | Paused = 1, | ||
| 68 | }; | ||
| 69 | |||
| 64 | class Thread final : public WaitObject { | 70 | class Thread final : public WaitObject { |
| 65 | public: | 71 | public: |
| 66 | using TLSMemory = std::vector<u8>; | 72 | using TLSMemory = std::vector<u8>; |
| @@ -371,6 +377,12 @@ public: | |||
| 371 | return affinity_mask; | 377 | return affinity_mask; |
| 372 | } | 378 | } |
| 373 | 379 | ||
| 380 | ThreadActivity GetActivity() const { | ||
| 381 | return activity; | ||
| 382 | } | ||
| 383 | |||
| 384 | void SetActivity(ThreadActivity value); | ||
| 385 | |||
| 374 | private: | 386 | private: |
| 375 | explicit Thread(KernelCore& kernel); | 387 | explicit Thread(KernelCore& kernel); |
| 376 | ~Thread() override; | 388 | ~Thread() override; |
| @@ -439,6 +451,8 @@ private: | |||
| 439 | TLSMemoryPtr tls_memory = std::make_shared<TLSMemory>(); | 451 | TLSMemoryPtr tls_memory = std::make_shared<TLSMemory>(); |
| 440 | 452 | ||
| 441 | std::string name; | 453 | std::string name; |
| 454 | |||
| 455 | ThreadActivity activity = ThreadActivity::Normal; | ||
| 442 | }; | 456 | }; |
| 443 | 457 | ||
| 444 | /** | 458 | /** |