diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index bb12f9ac7c..5ed00d451f 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1744,11 +1744,51 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, } static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core, - u64 mask) { - LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:016X}, core=0x{:X}", thread_handle, - mask, core); + 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& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); + const auto* const current_process = system.Kernel().CurrentProcess(); + + if (core == static_cast(THREADPROCESSORID_IDEAL)) { + const u8 ideal_cpu_core = current_process->GetIdealCore(); + + ASSERT(ideal_cpu_core != static_cast(THREADPROCESSORID_IDEAL)); + + // Set the target CPU to the ideal core specified by the process. + core = ideal_cpu_core; + affinity_mask = 1ULL << core; + } 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::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(THREADPROCESSORID_DONT_CARE) && + core != static_cast(THREADPROCESSORID_DONT_UPDATE)) { + LOG_ERROR(Kernel_SVC, "Invalid processor ID specified (core={}).", core); + return ERR_INVALID_PROCESSOR_ID; + } + } + + const auto& handle_table = current_process->GetHandleTable(); const SharedPtr thread = handle_table.Get(thread_handle); if (!thread) { LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}", @@ -1756,40 +1796,7 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, return ERR_INVALID_HANDLE; } - if (core == static_cast(THREADPROCESSORID_IDEAL)) { - const u8 ideal_cpu_core = thread->GetOwnerProcess()->GetIdealCore(); - - ASSERT(ideal_cpu_core != static_cast(THREADPROCESSORID_IDEAL)); - - // Set the target CPU to the ideal core specified by the process. - core = ideal_cpu_core; - mask = 1ULL << core; - } - - if (mask == 0) { - LOG_ERROR(Kernel_SVC, "Mask is 0"); - return ERR_INVALID_COMBINATION; - } - - /// This value is used to only change the affinity mask without changing the current ideal core. - static constexpr u32 OnlyChangeMask = static_cast(-3); - - if (core == OnlyChangeMask) { - core = thread->GetIdealCore(); - } else if (core >= Core::NUM_CPU_CORES && core != static_cast(THREADPROCESSORID_DONT_UPDATE)) { - LOG_ERROR(Kernel_SVC, "Invalid core specified, got {}", core); - return ERR_INVALID_PROCESSOR_ID; - } - - // Error out if the input core isn't enabled in the input mask. - if (core < Core::NUM_CPU_CORES && (mask & (1ull << core)) == 0) { - LOG_ERROR(Kernel_SVC, "Core is not enabled for the current mask, core={}, mask={:016X}", - core, mask); - return ERR_INVALID_COMBINATION; - } - - thread->ChangeCore(core, mask); - + thread->ChangeCore(core, affinity_mask); return RESULT_SUCCESS; }