summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Luke Street2018-12-03 12:25:27 -0500
committerGravatar Luke Street2018-12-04 01:23:50 -0500
commit3e75175d0242090902e4b383086e3f5ac6cf3f73 (patch)
treec6ff5eb9787f21284a5748ad210c866d32e04bcd /src/core/hle/kernel
parentMerge pull request #1852 from VPeruS/fix-format-string (diff)
downloadyuzu-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.h2
-rw-r--r--src/core/hle/kernel/svc.cpp38
-rw-r--r--src/core/hle/kernel/thread.cpp24
-rw-r--r--src/core/hle/kernel/thread.h14
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};
27constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119}; 27constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119};
28constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120}; 28constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120};
29constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121}; 29constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121};
30constexpr ResultCode ERR_ALREADY_REGISTERED{ErrorModule::Kernel, 122}; 30constexpr ResultCode ERR_BUSY{ErrorModule::Kernel, 122};
31constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE{ErrorModule::Kernel, 123}; 31constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE{ErrorModule::Kernel, 123};
32constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125}; 32constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125};
33constexpr ResultCode ERR_RESOURCE_LIMIT_EXCEEDED{ErrorModule::Kernel, 132}; 33constexpr 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
854static ResultCode SetThreadActivity(Handle handle, u32 unknown) { 854static 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
396void 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 {
44enum class ThreadStatus { 44enum 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
64enum class ThreadActivity : u32 {
65 Normal = 0,
66 Paused = 1,
67};
68
63class Thread final : public WaitObject { 69class Thread final : public WaitObject {
64public: 70public:
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
373private: 385private:
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/**