summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-04-11 21:49:51 +0200
committerbunnei <bunneidev@gmail.com>2021-05-06 01:40:51 +0200
commit2cb6106523a87ae78d3a6b92c34b3b1d2817415e (patch)
tree64303177f862736efc1cdd4d22475c4f428458a1
parenthle: kernel: svc: Migrate GetProcessId, CancelSynchronization, SetThreadActivity. (diff)
downloadyuzu-2cb6106523a87ae78d3a6b92c34b3b1d2817415e.tar
yuzu-2cb6106523a87ae78d3a6b92c34b3b1d2817415e.tar.gz
yuzu-2cb6106523a87ae78d3a6b92c34b3b1d2817415e.tar.bz2
yuzu-2cb6106523a87ae78d3a6b92c34b3b1d2817415e.tar.lz
yuzu-2cb6106523a87ae78d3a6b92c34b3b1d2817415e.tar.xz
yuzu-2cb6106523a87ae78d3a6b92c34b3b1d2817415e.tar.zst
yuzu-2cb6106523a87ae78d3a6b92c34b3b1d2817415e.zip
-rw-r--r--src/core/hle/kernel/svc.cpp61
1 files changed, 59 insertions, 2 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index fae4c7209..b83ee3e69 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1100,7 +1100,55 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
thread_handle);
- __debugbreak();
+ auto& kernel = system.Kernel();
+
+ // Get the thread from its handle.
+ KScopedAutoObject thread =
+ kernel.CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
+ R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
+
+ // Require the handle be to a non-current thread in the current process.
+ const auto* current_process = kernel.CurrentProcess();
+ R_UNLESS(current_process == thread->GetOwnerProcess(), ResultInvalidId);
+
+ // Verify that the thread isn't terminated.
+ R_UNLESS(thread->GetState() != ThreadState::Terminated, ResultTerminationRequested);
+
+ /// Check that the thread is not the current one.
+ /// NOTE: Nintendo does not check this, and thus the following loop will deadlock.
+ R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultInvalidId);
+
+ // Try to get the thread context until the thread isn't current on any core.
+ while (true) {
+ KScopedSchedulerLock sl{kernel};
+
+ // TODO(bunnei): Enforce that thread is suspended for debug here.
+
+ // If the thread's raw state isn't runnable, check if it's current on some core.
+ if (thread->GetRawState() != ThreadState::Runnable) {
+ bool current = false;
+ for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
+ if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetCurrentThread()) {
+ current = true;
+ }
+ break;
+ }
+
+ // If the thread is current, retry until it isn't.
+ if (current) {
+ continue;
+ }
+ }
+
+ // Get the thread context.
+ std::vector<u8> context;
+ R_TRY(thread->GetThreadContext3(context));
+
+ // Copy the thread context to user space.
+ system.Memory().WriteBlock(out_context, context.data(), context.size());
+
+ return RESULT_SUCCESS;
+ }
return RESULT_SUCCESS;
}
@@ -1885,7 +1933,16 @@ static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u
static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
u64* out_affinity_mask) {
- __debugbreak();
+ LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
+
+ // Get the thread from its handle.
+ KScopedAutoObject thread =
+ system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
+ R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
+
+ // Get the core mask.
+ R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask));
+
return RESULT_SUCCESS;
}