From 3aa0d462598beb2021308eee1d757d74fe33b312 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 23 Jun 2026 06:31:25 +0200 Subject: [video_core, hle] remove redundant parent references in system structs (#3908) reworked a bit to remove references of parent objects and instead pass as arguments to methods to prevent useless reloads Signed-off-by: lizzie Co-authored-by: maufeat Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3908 Reviewed-by: Maufeat Reviewed-by: crueter --- src/core/hle/kernel/k_condition_variable.cpp | 100 +++++++++++++-------------- 1 file changed, 49 insertions(+), 51 deletions(-) (limited to 'src/core/hle/kernel/k_condition_variable.cpp') diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 1a7431df07..3cf8b28e17 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -66,14 +66,15 @@ bool UpdateLockAtomic(KernelCore& kernel, u32* out, KProcessAddress address, u32 class ThreadQueueImplForKConditionVariableWaitForAddress final : public KThreadQueue { public: explicit ThreadQueueImplForKConditionVariableWaitForAddress(KernelCore& kernel) - : KThreadQueue(kernel) {} + : KThreadQueue(kernel) + {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); + waiting_thread->GetLockOwner(kernel)->RemoveWaiter(kernel, waiting_thread); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; @@ -82,14 +83,15 @@ private: KConditionVariable::ThreadTree* m_tree; public: - explicit ThreadQueueImplForKConditionVariableWaitConditionVariable( - KernelCore& kernel, KConditionVariable::ThreadTree* t) - : KThreadQueue(kernel), m_tree(t) {} + explicit ThreadQueueImplForKConditionVariableWaitConditionVariable(KernelCore& kernel, KConditionVariable::ThreadTree* t) + : KThreadQueue(kernel) + , m_tree(t) + {} - void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { + void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter from its owner. - if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { - owner->RemoveWaiter(waiting_thread); + if (KThread* owner = waiting_thread->GetLockOwner(kernel); owner != nullptr) { + owner->RemoveWaiter(kernel, waiting_thread); } // If the thread is waiting on a condvar, remove it from the tree. @@ -99,14 +101,15 @@ public: } // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; } // namespace KConditionVariable::KConditionVariable(Core::System& system) - : m_system{system}, m_kernel{system.Kernel()} {} + : m_system{system} +{} KConditionVariable::~KConditionVariable() = default; @@ -119,8 +122,7 @@ Result KConditionVariable::SignalToAddress(KernelCore& kernel, KProcessAddress a // Remove waiter thread. bool has_waiters{}; - KThread* const next_owner_thread = - owner_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr); + KThread* const next_owner_thread = owner_thread->RemoveUserWaiterByKey(kernel, std::addressof(has_waiters), addr); // Determine the next tag. u32 next_value{}; @@ -144,15 +146,14 @@ Result KConditionVariable::SignalToAddress(KernelCore& kernel, KProcessAddress a // If necessary, signal the next owner thread. if (next_owner_thread != nullptr) { - next_owner_thread->EndWait(result); + next_owner_thread->EndWait(kernel, result); } R_RETURN(result); } } -Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, - u32 value) { +Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, u32 value) { KThread* cur_thread = GetCurrentThreadPointer(kernel); ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel); @@ -173,30 +174,30 @@ Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KPr // Get the lock owner thread. owner_thread = GetCurrentProcess(kernel) - .GetHandleTable() - .GetObjectWithoutPseudoHandle(handle) - .ReleasePointerUnsafe(); + .GetHandleTable() + .GetObjectWithoutPseudoHandle(kernel, handle) + .ReleasePointerUnsafe(); R_UNLESS(owner_thread != nullptr, ResultInvalidHandle); // Update the lock. cur_thread->SetUserAddressKey(addr, value); - owner_thread->AddWaiter(cur_thread); + owner_thread->AddWaiter(kernel, cur_thread); // Begin waiting. - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(kernel, std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); } // Close our reference to the owner thread, now that the wait is over. - owner_thread->Close(); + owner_thread->Close(kernel); // Get the wait result. R_RETURN(cur_thread->GetWaitResult()); } -void KConditionVariable::SignalImpl(KThread* thread) { +void KConditionVariable::SignalImpl(KernelCore& kernel, KThread* thread) { // Check pre-conditions. - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Update the tag. KProcessAddress address = thread->GetAddressKey(); @@ -211,35 +212,33 @@ void KConditionVariable::SignalImpl(KThread* thread) { // TODO(bunnei): We should call CanAccessAtomic(..) here. can_access = true; if (can_access) { - UpdateLockAtomic(m_kernel, std::addressof(prev_tag), address, own_tag, - Svc::HandleWaitMask); + UpdateLockAtomic(kernel, std::addressof(prev_tag), address, own_tag, Svc::HandleWaitMask); } } if (can_access) { if (prev_tag == Svc::InvalidHandle) { // If nobody held the lock previously, we're all good. - thread->EndWait(ResultSuccess); + thread->EndWait(kernel, ResultSuccess); } else { // Get the previous owner. - KThread* owner_thread = GetCurrentProcess(m_kernel) - .GetHandleTable() - .GetObjectWithoutPseudoHandle( - static_cast(prev_tag & ~Svc::HandleWaitMask)) - .ReleasePointerUnsafe(); + KThread* owner_thread = GetCurrentProcess(kernel) + .GetHandleTable() + .GetObjectWithoutPseudoHandle(kernel, Handle(prev_tag & ~Svc::HandleWaitMask)) + .ReleasePointerUnsafe(); if (owner_thread) { // Add the thread as a waiter on the owner. - owner_thread->AddWaiter(thread); - owner_thread->Close(); + owner_thread->AddWaiter(kernel, thread); + owner_thread->Close(kernel); } else { // The lock was tagged with a thread that doesn't exist. - thread->EndWait(ResultInvalidState); + thread->EndWait(kernel, ResultInvalidState); } } } else { // If the address wasn't accessible, note so. - thread->EndWait(ResultInvalidCurrentMemory); + thread->EndWait(kernel, ResultInvalidCurrentMemory); } } @@ -247,17 +246,16 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(m_system.Kernel()); auto it = m_tree.nfind_key({cv_key, -1}); - while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && - (it->GetConditionVariableKey() == cv_key)) { + while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) { KThread* target_thread = std::addressof(*it); it = m_tree.erase(it); target_thread->ClearConditionVariable(); - this->SignalImpl(target_thread); + this->SignalImpl(m_system.Kernel(), target_thread); ++num_waiters; } @@ -265,20 +263,20 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { // If we have no waiters, clear the has waiter flag. if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) { constexpr u32 HasNoWaiterFlag = 0; - WriteToUser(m_kernel, cv_key, HasNoWaiterFlag); + WriteToUser(m_system.Kernel(), cv_key, HasNoWaiterFlag); } } } Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout) { // Prepare to wait. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(m_system.Kernel()); KHardwareTimer* timer{}; - ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(m_kernel, + ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(m_system.Kernel(), std::addressof(m_tree)); { - KScopedSchedulerLockAndSleep slp(m_kernel, std::addressof(timer), cur_thread, timeout); + KScopedSchedulerLockAndSleep slp(m_system.Kernel(), std::addressof(timer), cur_thread, timeout); // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -291,7 +289,7 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti // Remove waiter thread. bool has_waiters{}; KThread* next_owner_thread = - cur_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr); + cur_thread->RemoveUserWaiterByKey(m_system.Kernel(), std::addressof(has_waiters), addr); // Update for the next owner thread. u32 next_value{}; @@ -303,18 +301,18 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti } // Wake up the next owner. - next_owner_thread->EndWait(ResultSuccess); + next_owner_thread->EndWait(m_system.Kernel(), ResultSuccess); } // Write to the cv key. { constexpr u32 HasWaiterFlag = 1; - WriteToUser(m_kernel, key, HasWaiterFlag); + WriteToUser(m_system.Kernel(), key, HasWaiterFlag); std::atomic_thread_fence(std::memory_order_seq_cst); } // Write the value to userspace. - if (!WriteToUser(m_kernel, addr, next_value)) { + if (!WriteToUser(m_system.Kernel(), addr, next_value)) { slp.CancelSleep(); R_THROW(ResultInvalidCurrentMemory); } @@ -329,7 +327,7 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti // Begin waiting. wait_queue.SetHardwareTimer(timer); - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(m_system.Kernel(), std::addressof(wait_queue)); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); } -- cgit v1.2.3