summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar Lioncash2019-04-15 20:34:55 -0400
committerGravatar Lioncash2019-04-29 01:38:27 -0400
commitd672c6e759c560dbeff04c1b92ce46bb7a2f8ed8 (patch)
tree974a6a0992c6e5ab583d1a1e67c20028b7d7c765 /src/core/hle/kernel/svc.cpp
parentkernel/thread: Update thread processor ID flags (diff)
downloadyuzu-d672c6e759c560dbeff04c1b92ce46bb7a2f8ed8.tar.gz
yuzu-d672c6e759c560dbeff04c1b92ce46bb7a2f8ed8.tar.xz
yuzu-d672c6e759c560dbeff04c1b92ce46bb7a2f8ed8.zip
kernel/svc: Reorganize svcSetThreadCoreMask()
Makes the code much nicer to follow in terms of behavior and control flow. It also fixes a few bugs in the implementation. Notably, the thread's owner process shouldn't be accessed in order to retrieve the core mask or ideal core. This should be done through the current running process. The only reason this bug wasn't encountered yet is because we currently only support running one process, and thus every owner process will be the current process. We also weren't checking against the process' CPU core mask to see if an allowed core is specified or not. With this out of the way, it'll be less noisy to implement proper handling of the affinity flags internally within the kernel thread instances.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp71
1 files changed, 39 insertions, 32 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index bb12f9ac7..5ed00d451 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1744,52 +1744,59 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle,
1744} 1744}
1745 1745
1746static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core, 1746static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core,
1747 u64 mask) { 1747 u64 affinity_mask) {
1748 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:016X}, core=0x{:X}", thread_handle, 1748 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core=0x{:X}, affinity_mask=0x{:016X}",
1749 mask, core); 1749 thread_handle, core, affinity_mask);
1750 1750
1751 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1751 const auto* const current_process = system.Kernel().CurrentProcess();
1752 const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
1753 if (!thread) {
1754 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
1755 thread_handle);
1756 return ERR_INVALID_HANDLE;
1757 }
1758 1752
1759 if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) { 1753 if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) {
1760 const u8 ideal_cpu_core = thread->GetOwnerProcess()->GetIdealCore(); 1754 const u8 ideal_cpu_core = current_process->GetIdealCore();
1761 1755
1762 ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL)); 1756 ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL));
1763 1757
1764 // Set the target CPU to the ideal core specified by the process. 1758 // Set the target CPU to the ideal core specified by the process.
1765 core = ideal_cpu_core; 1759 core = ideal_cpu_core;
1766 mask = 1ULL << core; 1760 affinity_mask = 1ULL << core;
1767 } 1761 } else {
1768 1762 const u64 core_mask = current_process->GetCoreMask();
1769 if (mask == 0) { 1763
1770 LOG_ERROR(Kernel_SVC, "Mask is 0"); 1764 if ((core_mask | affinity_mask) != core_mask) {
1771 return ERR_INVALID_COMBINATION; 1765 LOG_ERROR(
1772 } 1766 Kernel_SVC,
1767 "Invalid processor ID specified (core_mask=0x{:08X}, affinity_mask=0x{:016X})",
1768 core_mask, affinity_mask);
1769 return ERR_INVALID_PROCESSOR_ID;
1770 }
1773 1771
1774 /// This value is used to only change the affinity mask without changing the current ideal core. 1772 if (affinity_mask == 0) {
1775 static constexpr u32 OnlyChangeMask = static_cast<u32>(-3); 1773 LOG_ERROR(Kernel_SVC, "Specfified affinity mask is zero.");
1774 return ERR_INVALID_COMBINATION;
1775 }
1776 1776
1777 if (core == OnlyChangeMask) { 1777 if (core < Core::NUM_CPU_CORES) {
1778 core = thread->GetIdealCore(); 1778 if ((affinity_mask & (1ULL << core)) == 0) {
1779 } else if (core >= Core::NUM_CPU_CORES && core != static_cast<u32>(THREADPROCESSORID_DONT_UPDATE)) { 1779 LOG_ERROR(Kernel_SVC,
1780 LOG_ERROR(Kernel_SVC, "Invalid core specified, got {}", core); 1780 "Core is not enabled for the current mask, core={}, mask={:016X}", core,
1781 return ERR_INVALID_PROCESSOR_ID; 1781 affinity_mask);
1782 return ERR_INVALID_COMBINATION;
1783 }
1784 } else if (core != static_cast<u32>(THREADPROCESSORID_DONT_CARE) &&
1785 core != static_cast<u32>(THREADPROCESSORID_DONT_UPDATE)) {
1786 LOG_ERROR(Kernel_SVC, "Invalid processor ID specified (core={}).", core);
1787 return ERR_INVALID_PROCESSOR_ID;
1788 }
1782 } 1789 }
1783 1790
1784 // Error out if the input core isn't enabled in the input mask. 1791 const auto& handle_table = current_process->GetHandleTable();
1785 if (core < Core::NUM_CPU_CORES && (mask & (1ull << core)) == 0) { 1792 const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
1786 LOG_ERROR(Kernel_SVC, "Core is not enabled for the current mask, core={}, mask={:016X}", 1793 if (!thread) {
1787 core, mask); 1794 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
1788 return ERR_INVALID_COMBINATION; 1795 thread_handle);
1796 return ERR_INVALID_HANDLE;
1789 } 1797 }
1790 1798
1791 thread->ChangeCore(core, mask); 1799 thread->ChangeCore(core, affinity_mask);
1792
1793 return RESULT_SUCCESS; 1800 return RESULT_SUCCESS;
1794} 1801}
1795 1802