From cdd14b03e5c8e29bc6cd11bbde0ef726d2f166ce Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Wed, 20 Jan 2021 13:42:27 -0800
Subject: hle: kernel: Recode implementation of KThread to be more accurate.

---
 src/core/hle/kernel/svc.cpp | 355 +++++++++++++++++++-------------------------
 1 file changed, 152 insertions(+), 203 deletions(-)

(limited to 'src/core/hle/kernel/svc.cpp')

diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 2512bfd98f..dbef854f8f 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -351,7 +351,8 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
         session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming());
     }
 
-    return thread->GetSignalingResult();
+    KSynchronizationObject* dummy{};
+    return thread->GetWaitResult(std::addressof(dummy));
 }
 
 static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
@@ -359,27 +360,26 @@ static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
 }
 
 /// Get the ID for the specified thread.
-static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle thread_handle) {
+static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) {
     LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
 
+    // Get the thread from its handle.
     const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
     const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
-    if (!thread) {
-        LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", thread_handle);
-        return ERR_INVALID_HANDLE;
-    }
+    R_UNLESS(thread, Svc::ResultInvalidHandle);
 
-    *thread_id = thread->GetThreadID();
+    // Get the thread's id.
+    *out_thread_id = thread->GetThreadID();
     return RESULT_SUCCESS;
 }
 
-static ResultCode GetThreadId32(Core::System& system, u32* thread_id_low, u32* thread_id_high,
-                                Handle thread_handle) {
-    u64 thread_id{};
-    const ResultCode result{GetThreadId(system, &thread_id, thread_handle)};
+static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low,
+                                u32* out_thread_id_high, Handle thread_handle) {
+    u64 out_thread_id{};
+    const ResultCode result{GetThreadId(system, &out_thread_id, thread_handle)};
 
-    *thread_id_low = static_cast<u32>(thread_id >> 32);
-    *thread_id_high = static_cast<u32>(thread_id & std::numeric_limits<u32>::max());
+    *out_thread_id_low = static_cast<u32>(out_thread_id >> 32);
+    *out_thread_id_high = static_cast<u32>(out_thread_id & std::numeric_limits<u32>::max());
 
     return result;
 }
@@ -473,15 +473,13 @@ static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u
 static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) {
     LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
 
+    // Get the thread from its handle.
     const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
     std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
-    if (!thread) {
-        LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
-                  thread_handle);
-        return ERR_INVALID_HANDLE;
-    }
+    R_UNLESS(thread, Svc::ResultInvalidHandle);
 
-    thread->CancelWait();
+    // Cancel the thread's wait.
+    thread->WaitCancel();
     return RESULT_SUCCESS;
 }
 
@@ -630,7 +628,7 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
         handle_debug_buffer(info1, info2);
 
         auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
-        const auto thread_processor_id = current_thread->GetProcessorID();
+        const auto thread_processor_id = current_thread->GetActiveCore();
         system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
     }
 }
@@ -888,7 +886,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
         const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks();
         u64 out_ticks = 0;
         if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
-            const u64 thread_ticks = current_thread->GetTotalCPUTimeTicks();
+            const u64 thread_ticks = current_thread->GetCpuTime();
 
             out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks);
         } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) {
@@ -1025,127 +1023,109 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size
     return UnmapPhysicalMemory(system, addr, size);
 }
 
-/// Sets the thread activity
-static ResultCode SetThreadActivity(Core::System& system, 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;
+constexpr bool IsValidThreadActivity(Svc::ThreadActivity thread_activity) {
+    switch (thread_activity) {
+    case Svc::ThreadActivity::Runnable:
+    case Svc::ThreadActivity::Paused:
+        return true;
+    default:
+        return false;
     }
+}
 
-    const auto* current_process = system.Kernel().CurrentProcess();
-    const std::shared_ptr<KThread> thread = current_process->GetHandleTable().Get<KThread>(handle);
-    if (!thread) {
-        LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
-        return ERR_INVALID_HANDLE;
-    }
+/// Sets the thread activity
+static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle,
+                                    Svc::ThreadActivity thread_activity) {
+    LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle,
+              thread_activity);
 
-    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;
-    }
+    // Validate the activity.
+    R_UNLESS(IsValidThreadActivity(thread_activity), Svc::ResultInvalidEnumValue);
 
-    if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) {
-        LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread");
-        return ERR_BUSY;
-    }
+    // Get the thread from its handle.
+    auto& kernel = system.Kernel();
+    const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
+    const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
+    R_UNLESS(thread, Svc::ResultInvalidHandle);
+
+    // Check that the activity is being set on a non-current thread for the current process.
+    R_UNLESS(thread->GetOwnerProcess() == kernel.CurrentProcess(), Svc::ResultInvalidHandle);
+    R_UNLESS(thread.get() != GetCurrentThreadPointer(kernel), Svc::ResultBusy);
+
+    // Set the activity.
+    R_TRY(thread->SetActivity(thread_activity));
 
-    return thread->SetActivity(static_cast<ThreadActivity>(activity));
+    return RESULT_SUCCESS;
 }
 
-static ResultCode SetThreadActivity32(Core::System& system, Handle handle, u32 activity) {
-    return SetThreadActivity(system, handle, activity);
+static ResultCode SetThreadActivity32(Core::System& system, Handle thread_handle,
+                                      Svc::ThreadActivity thread_activity) {
+    return SetThreadActivity(system, thread_handle, thread_activity);
 }
 
 /// Gets the thread context
-static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, Handle handle) {
-    LOG_DEBUG(Kernel_SVC, "called, context=0x{:08X}, thread=0x{:X}", thread_context, handle);
+static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Handle thread_handle) {
+    LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
+              thread_handle);
 
+    // Get the thread from its handle.
     const auto* current_process = system.Kernel().CurrentProcess();
-    const std::shared_ptr<KThread> thread = current_process->GetHandleTable().Get<KThread>(handle);
-    if (!thread) {
-        LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
-        return ERR_INVALID_HANDLE;
-    }
+    const std::shared_ptr<KThread> thread =
+        current_process->GetHandleTable().Get<KThread>(thread_handle);
+    R_UNLESS(thread, Svc::ResultInvalidHandle);
 
-    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;
-    }
+    // Require the handle be to a non-current thread in the current process.
+    R_UNLESS(thread->GetOwnerProcess() == current_process, Svc::ResultInvalidHandle);
+    R_UNLESS(thread.get() != system.Kernel().CurrentScheduler()->GetCurrentThread(),
+             Svc::ResultBusy);
 
-    if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) {
-        LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread");
-        return ERR_BUSY;
-    }
+    // Get the thread context.
+    std::vector<u8> context;
+    R_TRY(thread->GetThreadContext3(context));
 
-    Core::ARM_Interface::ThreadContext64 ctx = thread->GetContext64();
-    // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
-    ctx.pstate &= 0xFF0FFE20;
+    // Copy the thread context to user space.
+    system.Memory().WriteBlock(out_context, context.data(), context.size());
 
-    // If 64-bit, we can just write the context registers directly and we're good.
-    // However, if 32-bit, we have to ensure some registers are zeroed out.
-    if (!current_process->Is64BitProcess()) {
-        std::fill(ctx.cpu_registers.begin() + 15, ctx.cpu_registers.end(), 0);
-        std::fill(ctx.vector_registers.begin() + 16, ctx.vector_registers.end(), u128{});
-    }
-
-    system.Memory().WriteBlock(thread_context, &ctx, sizeof(ctx));
     return RESULT_SUCCESS;
 }
 
-static ResultCode GetThreadContext32(Core::System& system, u32 thread_context, Handle handle) {
-    return GetThreadContext(system, thread_context, handle);
+static ResultCode GetThreadContext32(Core::System& system, u32 out_context, Handle thread_handle) {
+    return GetThreadContext(system, out_context, thread_handle);
 }
 
 /// Gets the priority for the specified thread
-static ResultCode GetThreadPriority(Core::System& system, u32* priority, Handle handle) {
+static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Handle handle) {
     LOG_TRACE(Kernel_SVC, "called");
 
+    // Get the thread from its handle.
     const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
     const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
-    if (!thread) {
-        *priority = 0;
-        LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
-        return ERR_INVALID_HANDLE;
-    }
+    R_UNLESS(thread, Svc::ResultInvalidHandle);
 
-    *priority = thread->GetPriority();
+    // Get the thread's priority.
+    *out_priority = thread->GetPriority();
     return RESULT_SUCCESS;
 }
 
-static ResultCode GetThreadPriority32(Core::System& system, u32* priority, Handle handle) {
-    return GetThreadPriority(system, priority, handle);
+static ResultCode GetThreadPriority32(Core::System& system, u32* out_priority, Handle handle) {
+    return GetThreadPriority(system, out_priority, handle);
 }
 
 /// Sets the priority for the specified thread
 static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) {
     LOG_TRACE(Kernel_SVC, "called");
 
-    if (priority > Svc::LowestThreadPriority) {
-        LOG_ERROR(Kernel_SVC, "An invalid priority was specified {} for thread_handle={:08X}",
-                  priority, handle);
-        return ERR_INVALID_THREAD_PRIORITY;
-    }
-
-    const auto* const current_process = system.Kernel().CurrentProcess();
+    // Validate the priority.
+    R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority,
+             Svc::ResultInvalidPriority);
 
-    std::shared_ptr<KThread> thread = current_process->GetHandleTable().Get<KThread>(handle);
-    if (!thread) {
-        LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
-        return ERR_INVALID_HANDLE;
-    }
+    // Get the thread from its handle.
+    const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
+    const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
+    R_UNLESS(thread, Svc::ResultInvalidHandle);
 
+    // Set the thread priority.
     thread->SetBasePriority(priority);
-
     return RESULT_SUCCESS;
 }
 
@@ -1436,7 +1416,7 @@ static void ExitProcess(Core::System& system) {
     current_process->PrepareForTermination();
 
     // Kill the current thread
-    system.Kernel().CurrentScheduler()->GetCurrentThread()->Stop();
+    system.Kernel().CurrentScheduler()->GetCurrentThread()->Exit();
 }
 
 static void ExitProcess32(Core::System& system) {
@@ -1500,17 +1480,15 @@ static ResultCode CreateThread32(Core::System& system, Handle* out_handle, u32 p
 static ResultCode StartThread(Core::System& system, Handle thread_handle) {
     LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
 
+    // Get the thread from its handle.
     const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
     const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
-    if (!thread) {
-        LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
-                  thread_handle);
-        return ERR_INVALID_HANDLE;
-    }
+    R_UNLESS(thread, Svc::ResultInvalidHandle);
 
-    ASSERT(thread->GetState() == ThreadState::Initialized);
+    // Try to start the thread.
+    R_TRY(thread->Run());
 
-    return thread->Start();
+    return RESULT_SUCCESS;
 }
 
 static ResultCode StartThread32(Core::System& system, Handle thread_handle) {
@@ -1523,7 +1501,7 @@ static void ExitThread(Core::System& system) {
 
     auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
     system.GlobalSchedulerContext().RemoveThread(SharedFrom(current_thread));
-    current_thread->Stop();
+    current_thread->Exit();
 }
 
 static void ExitThread32(Core::System& system) {
@@ -1532,34 +1510,28 @@ static void ExitThread32(Core::System& system) {
 
 /// Sleep the current thread
 static void SleepThread(Core::System& system, s64 nanoseconds) {
-    LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
+    auto& kernel = system.Kernel();
+    const auto yield_type = static_cast<Svc::YieldType>(nanoseconds);
 
-    enum class SleepType : s64 {
-        YieldWithoutCoreMigration = 0,
-        YieldWithCoreMigration = -1,
-        YieldAndWaitForLoadBalancing = -2,
-    };
+    LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
 
-    auto& scheduler = *system.Kernel().CurrentScheduler();
-    if (nanoseconds <= 0) {
-        switch (static_cast<SleepType>(nanoseconds)) {
-        case SleepType::YieldWithoutCoreMigration: {
-            scheduler.YieldWithoutCoreMigration();
-            break;
-        }
-        case SleepType::YieldWithCoreMigration: {
-            scheduler.YieldWithCoreMigration();
-            break;
-        }
-        case SleepType::YieldAndWaitForLoadBalancing: {
-            scheduler.YieldToAnyThread();
-            break;
-        }
-        default:
-            UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
-        }
+    // When the input tick is positive, sleep.
+    if (nanoseconds > 0) {
+        // Convert the timeout from nanoseconds to ticks.
+        // NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
+
+        // Sleep.
+        // NOTE: Nintendo does not check the result of this sleep.
+        static_cast<void>(GetCurrentThread(kernel).Sleep(nanoseconds));
+    } else if (yield_type == Svc::YieldType::WithoutCoreMigration) {
+        KScheduler::YieldWithoutCoreMigration(kernel);
+    } else if (yield_type == Svc::YieldType::WithCoreMigration) {
+        KScheduler::YieldWithCoreMigration(kernel);
+    } else if (yield_type == Svc::YieldType::ToAnyThread) {
+        KScheduler::YieldToAnyThread(kernel);
     } else {
-        scheduler.GetCurrentThread()->Sleep(nanoseconds);
+        // Nintendo does nothing at all if an otherwise invalid value is passed.
+        UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
     }
 }
 
@@ -1822,95 +1794,72 @@ static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u
     return CreateTransferMemory(system, handle, addr, size, permissions);
 }
 
-static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core,
-                                    u64* mask) {
+static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
+                                    u64* out_affinity_mask) {
     LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
 
+    // Get the thread from its handle.
     const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
     const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
-    if (!thread) {
-        LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
-                  thread_handle);
-        *core = 0;
-        *mask = 0;
-        return ERR_INVALID_HANDLE;
-    }
+    R_UNLESS(thread, Svc::ResultInvalidHandle);
 
-    *core = thread->GetIdealCore();
-    *mask = thread->GetAffinityMask().GetAffinityMask();
+    // Get the core mask.
+    R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask));
 
     return RESULT_SUCCESS;
 }
 
-static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle, u32* core,
-                                      u32* mask_low, u32* mask_high) {
-    u64 mask{};
-    const auto result = GetThreadCoreMask(system, thread_handle, core, &mask);
-    *mask_high = static_cast<u32>(mask >> 32);
-    *mask_low = static_cast<u32>(mask);
+static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle, s32* out_core_id,
+                                      u32* out_affinity_mask_low, u32* out_affinity_mask_high) {
+    u64 out_affinity_mask{};
+    const auto result = GetThreadCoreMask(system, thread_handle, out_core_id, &out_affinity_mask);
+    *out_affinity_mask_high = static_cast<u32>(out_affinity_mask >> 32);
+    *out_affinity_mask_low = static_cast<u32>(out_affinity_mask);
     return result;
 }
 
-static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core,
+static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id,
                                     u64 affinity_mask) {
-    LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core=0x{:X}, affinity_mask=0x{:016X}",
-              thread_handle, core, affinity_mask);
-
-    const auto* const current_process = system.Kernel().CurrentProcess();
+    LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core_id=0x{:X}, affinity_mask=0x{:016X}",
+              thread_handle, core_id, affinity_mask);
 
-    if (core == static_cast<u32>(Svc::IdealCoreUseProcessValue)) {
-        const u8 ideal_cpu_core = current_process->GetIdealCoreId();
+    const auto& current_process = *system.Kernel().CurrentProcess();
 
-        ASSERT(ideal_cpu_core != static_cast<u8>(Svc::IdealCoreUseProcessValue));
-
-        // Set the target CPU to the ideal core specified by the process.
-        core = ideal_cpu_core;
-        affinity_mask = 1ULL << core;
+    // Determine the core id/affinity mask.
+    if (core_id == Svc::IdealCoreUseProcessValue) {
+        core_id = current_process.GetIdealCoreId();
+        affinity_mask = (1ULL << core_id);
     } else {
-        const u64 core_mask = current_process->GetCoreMask();
-
-        if ((core_mask | affinity_mask) != core_mask) {
-            LOG_ERROR(
-                Kernel_SVC,
-                "Invalid processor ID specified (core_mask=0x{:08X}, affinity_mask=0x{:016X})",
-                core_mask, affinity_mask);
-            return ERR_INVALID_PROCESSOR_ID;
-        }
-
-        if (affinity_mask == 0) {
-            LOG_ERROR(Kernel_SVC, "Specfified affinity mask is zero.");
-            return ERR_INVALID_COMBINATION;
-        }
-
-        if (core < Core::Hardware::NUM_CPU_CORES) {
-            if ((affinity_mask & (1ULL << core)) == 0) {
-                LOG_ERROR(Kernel_SVC,
-                          "Core is not enabled for the current mask, core={}, mask={:016X}", core,
-                          affinity_mask);
-                return ERR_INVALID_COMBINATION;
-            }
-        } else if (core != static_cast<u32>(Svc::IdealCoreDontCare) &&
-                   core != static_cast<u32>(Svc::IdealCoreNoUpdate)) {
-            LOG_ERROR(Kernel_SVC, "Invalid processor ID specified (core={}).", core);
-            return ERR_INVALID_PROCESSOR_ID;
+        // Validate the affinity mask.
+        const u64 process_core_mask = current_process.GetCoreMask();
+        R_UNLESS((affinity_mask | process_core_mask) == process_core_mask,
+                 Svc::ResultInvalidCoreId);
+        R_UNLESS(affinity_mask != 0, Svc::ResultInvalidCombination);
+
+        // Validate the core id.
+        if (IsValidCoreId(core_id)) {
+            R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, Svc::ResultInvalidCombination);
+        } else {
+            R_UNLESS(core_id == Svc::IdealCoreNoUpdate || core_id == Svc::IdealCoreDontCare,
+                     Svc::ResultInvalidCoreId);
         }
     }
 
-    const auto& handle_table = current_process->GetHandleTable();
+    // Get the thread from its handle.
+    const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
     const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
-    if (!thread) {
-        LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
-                  thread_handle);
-        return ERR_INVALID_HANDLE;
-    }
+    R_UNLESS(thread, Svc::ResultInvalidHandle);
 
-    return thread->SetCoreAndAffinityMask(core, affinity_mask);
+    // Set the core mask.
+    R_TRY(thread->SetCoreMask(core_id, affinity_mask));
+
+    return RESULT_SUCCESS;
 }
 
-static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, u32 core,
+static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, s32 core_id,
                                       u32 affinity_mask_low, u32 affinity_mask_high) {
     const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32);
-    return SetThreadCoreMask(system, thread_handle, core, affinity_mask);
+    return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
 }
 
 static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) {
@@ -2474,7 +2423,7 @@ void Call(Core::System& system, u32 immediate) {
     kernel.EnterSVCProfile();
 
     auto* thread = kernel.CurrentScheduler()->GetCurrentThread();
-    thread->SetContinuousOnSVC(true);
+    thread->SetIsCallingSvc();
 
     const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate)
                                                                         : GetSVCInfo32(immediate);
@@ -2490,7 +2439,7 @@ void Call(Core::System& system, u32 immediate) {
 
     kernel.ExitSVCProfile();
 
-    if (!thread->IsContinuousOnSVC()) {
+    if (!thread->IsCallingSvc()) {
         auto* host_context = thread->GetHostContext().get();
         host_context->Rewind();
     }
-- 
cgit v1.2.3-70-g09d2