hle: kernel: svc: Migrate GetThreadContext, GetThreadCoreMask.

This commit is contained in:
bunnei 2021-04-11 12:49:51 -07:00
parent 76a0814142
commit 2cb6106523

View File

@ -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, LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
thread_handle); 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; 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, static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
u64* out_affinity_mask) { 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; return RESULT_SUCCESS;
} }