From e64fef109cf46bb2ecac4c25e91fac0773776c1b Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 7 Apr 2021 01:18:26 -0700 Subject: [PATCH] kern: update pinned thread priority rules --- .../include/mesosphere/kern_k_thread.hpp | 3 ++ .../libmesosphere/source/kern_k_thread.cpp | 42 ++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp index 0220b75ff..715bd0deb 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp @@ -209,6 +209,7 @@ namespace ams::kern { Result m_wait_result; Result m_debug_exception_result; s32 m_base_priority{}; + s32 m_base_priority_on_unpin{}; s32 m_physical_ideal_core_id{}; s32 m_virtual_ideal_core_id{}; s32 m_num_kernel_waiters{}; @@ -346,6 +347,8 @@ namespace ams::kern { void StartTermination(); void FinishTermination(); + + void IncreaseBasePriority(s32 priority); public: constexpr u64 GetThreadId() const { return m_thread_id; } diff --git a/libraries/libmesosphere/source/kern_k_thread.cpp b/libraries/libmesosphere/source/kern_k_thread.cpp index fd6ed1637..00220923b 100644 --- a/libraries/libmesosphere/source/kern_k_thread.cpp +++ b/libraries/libmesosphere/source/kern_k_thread.cpp @@ -19,6 +19,8 @@ namespace ams::kern { namespace { + constexpr inline s32 TerminatingThreadPriority = ams::svc::SystemThreadPriorityHighest - 1; + constexpr bool IsKernelAddressKey(KProcessAddress key) { const uintptr_t key_uptr = GetInteger(key); return KernelVirtualAddressSpaceBase <= key_uptr && key_uptr <= KernelVirtualAddressSpaceLast; @@ -426,6 +428,14 @@ namespace ams::kern { if (active_core != current_core || m_physical_affinity_mask.GetAffinityMask() != m_original_physical_affinity_mask.GetAffinityMask()) { KScheduler::OnThreadAffinityMaskChanged(this, m_original_physical_affinity_mask, active_core); } + + /* Set base priority-on-unpin. */ + const s32 old_base_priority = m_base_priority; + m_base_priority_on_unpin = old_base_priority; + + /* Set base priority to higher than any possible process priority. */ + m_base_priority = std::min(old_base_priority, __builtin_ctzll(this->GetOwnerProcess()->GetPriorityMask())); + RestorePriority(this); } /* Disallow performing thread suspension. */ @@ -476,6 +486,9 @@ namespace ams::kern { } KScheduler::OnThreadAffinityMaskChanged(this, old_mask, active_core); } + + m_base_priority = m_base_priority_on_unpin; + RestorePriority(this); } /* Allow performing thread suspension (if termination hasn't been requested). */ @@ -710,13 +723,38 @@ namespace ams::kern { KScopedSchedulerLock sl; + /* Determine the priority value to use. */ + const s32 target_priority = m_termination_requested.load() && priority >= TerminatingThreadPriority ? TerminatingThreadPriority : priority; + /* Change our base priority. */ - m_base_priority = priority; + if (this->GetStackParameters().is_pinned) { + m_base_priority_on_unpin = target_priority; + } else { + m_base_priority = target_priority; + } /* Perform a priority restoration. */ RestorePriority(this); } + void KThread::IncreaseBasePriority(s32 priority) { + MESOSPHERE_ASSERT_THIS(); + MESOSPHERE_ASSERT(ams::svc::HighestThreadPriority <= priority && priority <= ams::svc::LowestThreadPriority); + + /* Set our unpin base priority, if we're pinned. */ + if (this->GetStackParameters().is_pinned && m_base_priority_on_unpin > priority) { + m_base_priority_on_unpin = priority; + } + + /* Set our base priority. */ + if (m_base_priority > priority) { + m_base_priority = priority; + + /* Perform a priority restoration. */ + RestorePriority(this); + } + } + Result KThread::SetPriorityToIdle() { MESOSPHERE_ASSERT_THIS(); @@ -1187,7 +1225,7 @@ namespace ams::kern { /* Change the thread's priority to be higher than any system thread's. */ if (this->GetBasePriority() >= ams::svc::SystemThreadPriorityHighest) { - this->SetBasePriority(ams::svc::SystemThreadPriorityHighest - 1); + this->SetBasePriority(TerminatingThreadPriority); } /* If the thread is runnable, send a termination interrupt to other cores. */