diff options
| author | 2021-04-11 12:49:51 -0700 | |
|---|---|---|
| committer | 2021-05-05 16:40:51 -0700 | |
| commit | 2cb6106523a87ae78d3a6b92c34b3b1d2817415e (patch) | |
| tree | 64303177f862736efc1cdd4d22475c4f428458a1 | |
| parent | hle: kernel: svc: Migrate GetProcessId, CancelSynchronization, SetThreadActiv... (diff) | |
| download | yuzu-2cb6106523a87ae78d3a6b92c34b3b1d2817415e.tar.gz yuzu-2cb6106523a87ae78d3a6b92c34b3b1d2817415e.tar.xz yuzu-2cb6106523a87ae78d3a6b92c34b3b1d2817415e.zip | |
hle: kernel: svc: Migrate GetThreadContext, GetThreadCoreMask.
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 61 |
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 | |||
| 1100 | LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, | 1100 | LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, |
| 1101 | thread_handle); | 1101 | thread_handle); |
| 1102 | 1102 | ||
| 1103 | __debugbreak(); | 1103 | auto& kernel = system.Kernel(); |
| 1104 | |||
| 1105 | // Get the thread from its handle. | ||
| 1106 | KScopedAutoObject thread = | ||
| 1107 | kernel.CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); | ||
| 1108 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); | ||
| 1109 | |||
| 1110 | // Require the handle be to a non-current thread in the current process. | ||
| 1111 | const auto* current_process = kernel.CurrentProcess(); | ||
| 1112 | R_UNLESS(current_process == thread->GetOwnerProcess(), ResultInvalidId); | ||
| 1113 | |||
| 1114 | // Verify that the thread isn't terminated. | ||
| 1115 | R_UNLESS(thread->GetState() != ThreadState::Terminated, ResultTerminationRequested); | ||
| 1116 | |||
| 1117 | /// Check that the thread is not the current one. | ||
| 1118 | /// NOTE: Nintendo does not check this, and thus the following loop will deadlock. | ||
| 1119 | R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultInvalidId); | ||
| 1120 | |||
| 1121 | // Try to get the thread context until the thread isn't current on any core. | ||
| 1122 | while (true) { | ||
| 1123 | KScopedSchedulerLock sl{kernel}; | ||
| 1124 | |||
| 1125 | // TODO(bunnei): Enforce that thread is suspended for debug here. | ||
| 1126 | |||
| 1127 | // If the thread's raw state isn't runnable, check if it's current on some core. | ||
| 1128 | if (thread->GetRawState() != ThreadState::Runnable) { | ||
| 1129 | bool current = false; | ||
| 1130 | for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) { | ||
| 1131 | if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetCurrentThread()) { | ||
| 1132 | current = true; | ||
| 1133 | } | ||
| 1134 | break; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | // If the thread is current, retry until it isn't. | ||
| 1138 | if (current) { | ||
| 1139 | continue; | ||
| 1140 | } | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | // Get the thread context. | ||
| 1144 | std::vector<u8> context; | ||
| 1145 | R_TRY(thread->GetThreadContext3(context)); | ||
| 1146 | |||
| 1147 | // Copy the thread context to user space. | ||
| 1148 | system.Memory().WriteBlock(out_context, context.data(), context.size()); | ||
| 1149 | |||
| 1150 | return RESULT_SUCCESS; | ||
| 1151 | } | ||
| 1104 | 1152 | ||
| 1105 | return RESULT_SUCCESS; | 1153 | return RESULT_SUCCESS; |
| 1106 | } | 1154 | } |
| @@ -1885,7 +1933,16 @@ static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u | |||
| 1885 | 1933 | ||
| 1886 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, | 1934 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, |
| 1887 | u64* out_affinity_mask) { | 1935 | u64* out_affinity_mask) { |
| 1888 | __debugbreak(); | 1936 | LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); |
| 1937 | |||
| 1938 | // Get the thread from its handle. | ||
| 1939 | KScopedAutoObject thread = | ||
| 1940 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); | ||
| 1941 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); | ||
| 1942 | |||
| 1943 | // Get the core mask. | ||
| 1944 | R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask)); | ||
| 1945 | |||
| 1889 | return RESULT_SUCCESS; | 1946 | return RESULT_SUCCESS; |
| 1890 | } | 1947 | } |
| 1891 | 1948 | ||