mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-30 23:49:01 -05:00 
			
		
		
		
	Merge pull request #1849 from encounter/svcSetThreadActivity
svc: Implement SetThreadActivity (thread suspension)
This commit is contained in:
		| @@ -27,7 +27,7 @@ constexpr ResultCode ERR_SYNCHRONIZATION_CANCELED{ErrorModule::Kernel, 118}; | ||||
| constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119}; | ||||
| constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120}; | ||||
| constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121}; | ||||
| constexpr ResultCode ERR_ALREADY_REGISTERED{ErrorModule::Kernel, 122}; | ||||
| constexpr ResultCode ERR_BUSY{ErrorModule::Kernel, 122}; | ||||
| constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE{ErrorModule::Kernel, 123}; | ||||
| constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125}; | ||||
| constexpr ResultCode ERR_RESOURCE_LIMIT_EXCEEDED{ErrorModule::Kernel, 132}; | ||||
|   | ||||
| @@ -932,8 +932,35 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | ||||
| } | ||||
|  | ||||
| /// Sets the thread activity | ||||
| static ResultCode SetThreadActivity(Handle handle, u32 unknown) { | ||||
|     LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}, unknown=0x{:08X}", handle, unknown); | ||||
| static ResultCode SetThreadActivity(Handle handle, u32 activity) { | ||||
|     LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity); | ||||
|     if (activity > static_cast<u32>(ThreadActivity::Paused)) { | ||||
|         return ERR_INVALID_ENUM_VALUE; | ||||
|     } | ||||
|  | ||||
|     const auto* current_process = Core::CurrentProcess(); | ||||
|     const SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle); | ||||
|     if (!thread) { | ||||
|         LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); | ||||
|         return ERR_INVALID_HANDLE; | ||||
|     } | ||||
|  | ||||
|     if (thread->GetOwnerProcess() != current_process) { | ||||
|         LOG_ERROR(Kernel_SVC, | ||||
|                   "The current process does not own the current thread, thread_handle={:08X} " | ||||
|                   "thread_pid={}, " | ||||
|                   "current_process_pid={}", | ||||
|                   handle, thread->GetOwnerProcess()->GetProcessID(), | ||||
|                   current_process->GetProcessID()); | ||||
|         return ERR_INVALID_HANDLE; | ||||
|     } | ||||
|  | ||||
|     if (thread == GetCurrentThread()) { | ||||
|         LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); | ||||
|         return ERR_BUSY; | ||||
|     } | ||||
|  | ||||
|     thread->SetActivity(static_cast<ThreadActivity>(activity)); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|  | ||||
| @@ -960,7 +987,7 @@ static ResultCode GetThreadContext(VAddr thread_context, Handle handle) { | ||||
|  | ||||
|     if (thread == GetCurrentThread()) { | ||||
|         LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); | ||||
|         return ERR_ALREADY_REGISTERED; | ||||
|         return ERR_BUSY; | ||||
|     } | ||||
|  | ||||
|     Core::ARM_Interface::ThreadContext ctx = thread->GetContext(); | ||||
| @@ -1245,7 +1272,10 @@ static ResultCode StartThread(Handle thread_handle) { | ||||
|     ASSERT(thread->GetStatus() == ThreadStatus::Dormant); | ||||
|  | ||||
|     thread->ResumeFromWait(); | ||||
|     Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule(); | ||||
|  | ||||
|     if (thread->GetStatus() == ThreadStatus::Ready) { | ||||
|         Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule(); | ||||
|     } | ||||
|  | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|   | ||||
| @@ -50,7 +50,7 @@ void Thread::Stop() { | ||||
|  | ||||
|     // Clean up thread from ready queue | ||||
|     // This is only needed when the thread is terminated forcefully (SVC TerminateProcess) | ||||
|     if (status == ThreadStatus::Ready) { | ||||
|     if (status == ThreadStatus::Ready || status == ThreadStatus::Paused) { | ||||
|         scheduler->UnscheduleThread(this, current_priority); | ||||
|     } | ||||
|  | ||||
| @@ -140,6 +140,11 @@ void Thread::ResumeFromWait() { | ||||
|  | ||||
|     wakeup_callback = nullptr; | ||||
|  | ||||
|     if (activity == ThreadActivity::Paused) { | ||||
|         status = ThreadStatus::Paused; | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     status = ThreadStatus::Ready; | ||||
|  | ||||
|     ChangeScheduler(); | ||||
| @@ -391,6 +396,23 @@ bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> t | ||||
|     return wakeup_callback(reason, std::move(thread), std::move(object), index); | ||||
| } | ||||
|  | ||||
| void Thread::SetActivity(ThreadActivity value) { | ||||
|     activity = value; | ||||
|  | ||||
|     if (value == ThreadActivity::Paused) { | ||||
|         // Set status if not waiting | ||||
|         if (status == ThreadStatus::Ready) { | ||||
|             status = ThreadStatus::Paused; | ||||
|         } else if (status == ThreadStatus::Running) { | ||||
|             status = ThreadStatus::Paused; | ||||
|             Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); | ||||
|         } | ||||
|     } else if (status == ThreadStatus::Paused) { | ||||
|         // Ready to reschedule | ||||
|         ResumeFromWait(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -45,6 +45,7 @@ enum ThreadProcessorId : s32 { | ||||
| enum class ThreadStatus { | ||||
|     Running,      ///< Currently running | ||||
|     Ready,        ///< Ready to run | ||||
|     Paused,       ///< Paused by SetThreadActivity or debug | ||||
|     WaitHLEEvent, ///< Waiting for hle event to finish | ||||
|     WaitSleep,    ///< Waiting due to a SleepThread SVC | ||||
|     WaitIPC,      ///< Waiting for the reply from an IPC request | ||||
| @@ -61,6 +62,11 @@ enum class ThreadWakeupReason { | ||||
|     Timeout // The thread was woken up due to a wait timeout. | ||||
| }; | ||||
|  | ||||
| enum class ThreadActivity : u32 { | ||||
|     Normal = 0, | ||||
|     Paused = 1, | ||||
| }; | ||||
|  | ||||
| class Thread final : public WaitObject { | ||||
| public: | ||||
|     using TLSMemory = std::vector<u8>; | ||||
| @@ -371,6 +377,12 @@ public: | ||||
|         return affinity_mask; | ||||
|     } | ||||
|  | ||||
|     ThreadActivity GetActivity() const { | ||||
|         return activity; | ||||
|     } | ||||
|  | ||||
|     void SetActivity(ThreadActivity value); | ||||
|  | ||||
| private: | ||||
|     explicit Thread(KernelCore& kernel); | ||||
|     ~Thread() override; | ||||
| @@ -439,6 +451,8 @@ private: | ||||
|     TLSMemoryPtr tls_memory = std::make_shared<TLSMemory>(); | ||||
|  | ||||
|     std::string name; | ||||
|  | ||||
|     ThreadActivity activity = ThreadActivity::Normal; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei