From 4dbf3f4880cac69db21cc8f18582814dc986c854 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Sun, 3 Jan 2021 01:49:18 -0800
Subject: [PATCH] hle: kernel: KThread: Clean up thread priorities.

---
 .../hle/kernel/global_scheduler_context.h     |  2 +-
 src/core/hle/kernel/k_scheduler.cpp           |  2 +-
 src/core/hle/kernel/k_thread.cpp              | 10 +--
 src/core/hle/kernel/k_thread.h                | 22 ------
 src/core/hle/kernel/process.cpp               |  2 +-
 src/core/hle/kernel/process.h                 |  7 +-
 src/core/hle/kernel/svc.cpp                   | 70 ++++++++-----------
 src/core/hle/kernel/svc_results.h             |  1 +
 src/core/hle/kernel/svc_types.h               |  4 ++
 src/yuzu/debugger/wait_tree.cpp               | 11 +--
 10 files changed, 46 insertions(+), 85 deletions(-)

diff --git a/src/core/hle/kernel/global_scheduler_context.h b/src/core/hle/kernel/global_scheduler_context.h
index 11592843e8..0f7b9a61cd 100644
--- a/src/core/hle/kernel/global_scheduler_context.h
+++ b/src/core/hle/kernel/global_scheduler_context.h
@@ -21,7 +21,7 @@ class KernelCore;
 class SchedulerLock;
 
 using KSchedulerPriorityQueue =
-    KPriorityQueue<KThread, Core::Hardware::NUM_CPU_CORES, Svc::LowestThreadPriority,
+    KPriorityQueue<KThread, Core::Hardware::NUM_CPU_CORES, Svc::LowestThreadPriority + 1,
                    Svc::HighestThreadPriority>;
 
 static constexpr s32 HighestCoreMigrationAllowedPriority = 2;
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 0e6300760a..2330220232 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -764,7 +764,7 @@ void KScheduler::Initialize() {
     std::function<void(void*)> init_func = Core::CpuManager::GetIdleThreadStartFunc();
     void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
     auto thread_res = KThread::Create(system, ThreadType::Kernel, name, 0,
-                                      Svc::LowestThreadPriority, 0, static_cast<u32>(core_id), 0,
+                                      KThread::IdleThreadPriority, 0, static_cast<u32>(core_id), 0,
                                       nullptr, std::move(init_func), init_func_parameter);
     idle_thread = thread_res.Unwrap().get();
 
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 518c5d5df9..e5be849bb8 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -127,14 +127,6 @@ ResultVal<std::shared_ptr<KThread>> KThread::Create(Core::System& system, Thread
                                                     void* thread_start_parameter) {
     auto& kernel = system.Kernel();
 
-    R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority,
-             Svc::ResultInvalidPriority);
-
-    if (processor_id > THREADPROCESSORID_MAX) {
-        LOG_ERROR(Kernel_SVC, "Invalid processor id: {}", processor_id);
-        return ERR_INVALID_PROCESSOR_ID;
-    }
-
     if (owner_process) {
         if (!system.Memory().IsValidVirtualAddress(*owner_process, entry_point)) {
             LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point);
@@ -423,7 +415,7 @@ ResultCode KThread::SetCoreAndAffinityMask(s32 new_core, u64 new_affinity_mask)
     };
 
     const bool use_override = affinity_override_count != 0;
-    if (new_core == THREADPROCESSORID_DONT_UPDATE) {
+    if (new_core == Svc::IdealCoreNoUpdate) {
         new_core = use_override ? ideal_core_override : ideal_core;
         if ((new_affinity_mask & (1ULL << new_core)) == 0) {
             LOG_ERROR(Kernel, "New affinity mask is incorrect! new_core={}, new_affinity_mask={}",
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 83a6d36ae3..ef2313f871 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -47,28 +47,6 @@ enum class ThreadType : u32 {
 };
 DECLARE_ENUM_FLAG_OPERATORS(ThreadType);
 
-enum ThreadProcessorId : s32 {
-    /// Indicates that no particular processor core is preferred.
-    THREADPROCESSORID_DONT_CARE = -1,
-
-    /// Run thread on the ideal core specified by the process.
-    THREADPROCESSORID_IDEAL = -2,
-
-    /// Indicates that the preferred processor ID shouldn't be updated in
-    /// a core mask setting operation.
-    THREADPROCESSORID_DONT_UPDATE = -3,
-
-    THREADPROCESSORID_0 = 0,   ///< Run thread on core 0
-    THREADPROCESSORID_1 = 1,   ///< Run thread on core 1
-    THREADPROCESSORID_2 = 2,   ///< Run thread on core 2
-    THREADPROCESSORID_3 = 3,   ///< Run thread on core 3
-    THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this
-
-    /// Allowed CPU mask
-    THREADPROCESSORID_DEFAULT_MASK = (1 << THREADPROCESSORID_0) | (1 << THREADPROCESSORID_1) |
-                                     (1 << THREADPROCESSORID_2) | (1 << THREADPROCESSORID_3)
-};
-
 enum class ThreadState : u16 {
     Initialized = 0,
     Waiting = 1,
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index e47da2b7f7..819e275ffa 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -39,7 +39,7 @@ namespace {
 void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) {
     const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart();
     auto thread_res = KThread::Create(system, ThreadType::User, "main", entry_point, priority, 0,
-                                      owner_process.GetIdealCore(), stack_top, &owner_process);
+                                      owner_process.GetIdealCoreId(), stack_top, &owner_process);
 
     std::shared_ptr<KThread> thread = std::move(thread_res).Unwrap();
 
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index db01d6c8ab..5a2cfdb36e 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -173,10 +173,15 @@ public:
     std::shared_ptr<ResourceLimit> GetResourceLimit() const;
 
     /// Gets the ideal CPU core ID for this process
-    u8 GetIdealCore() const {
+    u8 GetIdealCoreId() const {
         return ideal_core;
     }
 
+    /// Checks if the specified thread priority is valid.
+    bool CheckThreadPriority(s32 prio) const {
+        return ((1ULL << prio) & GetPriorityMask()) != 0;
+    }
+
     /// Gets the bitmask of allowed cores that this process' threads can run on.
     u64 GetCoreMask() const {
         return capabilities.GetCoreMask();
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 70a8ef34b1..2512bfd98f 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1443,54 +1443,40 @@ static void ExitProcess32(Core::System& system) {
     ExitProcess(system);
 }
 
+static constexpr bool IsValidCoreId(int32_t core_id) {
+    return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES));
+}
+
 /// Creates a new thread
 static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg,
-                               VAddr stack_top, u32 priority, s32 processor_id) {
+                               VAddr stack_bottom, u32 priority, s32 core_id) {
     LOG_DEBUG(Kernel_SVC,
-              "called entrypoint=0x{:08X}, arg=0x{:08X}, stacktop=0x{:08X}, "
-              "threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}",
-              entry_point, arg, stack_top, priority, processor_id, *out_handle);
-
-    auto* const current_process = system.Kernel().CurrentProcess();
-
-    if (processor_id == THREADPROCESSORID_IDEAL) {
-        // Set the target CPU to the one specified by the process.
-        processor_id = current_process->GetIdealCore();
-        ASSERT(processor_id != THREADPROCESSORID_IDEAL);
-    }
-
-    if (processor_id < THREADPROCESSORID_0 || processor_id > THREADPROCESSORID_3) {
-        LOG_ERROR(Kernel_SVC, "Invalid thread processor ID: {}", processor_id);
-        return ERR_INVALID_PROCESSOR_ID;
-    }
-
-    const u64 core_mask = current_process->GetCoreMask();
-    if ((core_mask | (1ULL << processor_id)) != core_mask) {
-        LOG_ERROR(Kernel_SVC, "Invalid thread core specified ({})", processor_id);
-        return ERR_INVALID_PROCESSOR_ID;
-    }
-
-    if (priority > Svc::LowestThreadPriority) {
-        LOG_ERROR(Kernel_SVC,
-                  "Invalid thread priority specified ({}). Must be within the range 0-64",
-                  priority);
-        return ERR_INVALID_THREAD_PRIORITY;
-    }
-
-    if (((1ULL << priority) & current_process->GetPriorityMask()) == 0) {
-        LOG_ERROR(Kernel_SVC, "Invalid thread priority specified ({})", priority);
-        return ERR_INVALID_THREAD_PRIORITY;
-    }
+              "called entry_point=0x{:08X}, arg=0x{:08X}, stack_bottom=0x{:08X}, "
+              "priority=0x{:08X}, core_id=0x{:08X}",
+              entry_point, arg, stack_bottom, priority, core_id);
 
+    // Adjust core id, if it's the default magic.
     auto& kernel = system.Kernel();
+    auto& process = *kernel.CurrentProcess();
+    if (core_id == Svc::IdealCoreUseProcessValue) {
+        core_id = process.GetIdealCoreId();
+    }
+
+    // Validate arguments.
+    R_UNLESS(IsValidCoreId(core_id), Svc::ResultInvalidCoreId);
+    R_UNLESS(((1ULL << core_id) & process.GetCoreMask()) != 0, Svc::ResultInvalidCoreId);
+
+    R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority,
+             Svc::ResultInvalidPriority);
+    R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
 
     ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Threads, 1));
 
     CASCADE_RESULT(std::shared_ptr<KThread> thread,
                    KThread::Create(system, ThreadType::User, "", entry_point, priority, arg,
-                                   processor_id, stack_top, current_process));
+                                   core_id, stack_bottom, &process));
 
-    const auto new_thread_handle = current_process->GetHandleTable().Create(thread);
+    const auto new_thread_handle = process.GetHandleTable().Create(thread);
     if (new_thread_handle.Failed()) {
         LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}",
                   new_thread_handle.Code().raw);
@@ -1872,10 +1858,10 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
 
     const auto* const current_process = system.Kernel().CurrentProcess();
 
-    if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) {
-        const u8 ideal_cpu_core = current_process->GetIdealCore();
+    if (core == static_cast<u32>(Svc::IdealCoreUseProcessValue)) {
+        const u8 ideal_cpu_core = current_process->GetIdealCoreId();
 
-        ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL));
+        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;
@@ -1903,8 +1889,8 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
                           affinity_mask);
                 return ERR_INVALID_COMBINATION;
             }
-        } else if (core != static_cast<u32>(THREADPROCESSORID_DONT_CARE) &&
-                   core != static_cast<u32>(THREADPROCESSORID_DONT_UPDATE)) {
+        } 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;
         }
diff --git a/src/core/hle/kernel/svc_results.h b/src/core/hle/kernel/svc_results.h
index 74adabc111..67bdf54247 100644
--- a/src/core/hle/kernel/svc_results.h
+++ b/src/core/hle/kernel/svc_results.h
@@ -12,6 +12,7 @@ constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59};
 constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102};
 constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106};
 constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112};
+constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113};
 constexpr ResultCode ResultInvalidHandle{ErrorModule::Kernel, 114};
 constexpr ResultCode ResultTimedOut{ErrorModule::Kernel, 117};
 constexpr ResultCode ResultCancelled{ErrorModule::Kernel, 118};
diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h
index 09b858f2a8..8909dbfaba 100644
--- a/src/core/hle/kernel/svc_types.h
+++ b/src/core/hle/kernel/svc_types.h
@@ -77,6 +77,10 @@ enum class ArbitrationType : u32 {
     WaitIfEqual = 2,
 };
 
+constexpr inline s32 IdealCoreDontCare = -1;
+constexpr inline s32 IdealCoreUseProcessValue = -2;
+constexpr inline s32 IdealCoreNoUpdate = -3;
+
 constexpr inline s32 LowestThreadPriority = 63;
 constexpr inline s32 HighestThreadPriority = 0;
 
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 0f03f4d90a..d6354b01d4 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -19,6 +19,7 @@
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/readable_event.h"
 #include "core/hle/kernel/svc_common.h"
+#include "core/hle/kernel/svc_types.h"
 #include "core/memory.h"
 
 namespace {
@@ -334,17 +335,11 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
 
     QString processor;
     switch (thread.GetProcessorID()) {
-    case Kernel::ThreadProcessorId::THREADPROCESSORID_IDEAL:
+    case Kernel::Svc::IdealCoreUseProcessValue:
         processor = tr("ideal");
         break;
-    case Kernel::ThreadProcessorId::THREADPROCESSORID_0:
-    case Kernel::ThreadProcessorId::THREADPROCESSORID_1:
-    case Kernel::ThreadProcessorId::THREADPROCESSORID_2:
-    case Kernel::ThreadProcessorId::THREADPROCESSORID_3:
-        processor = tr("core %1").arg(thread.GetProcessorID());
-        break;
     default:
-        processor = tr("Unknown processor %1").arg(thread.GetProcessorID());
+        processor = tr("core %1").arg(thread.GetProcessorID());
         break;
     }