From ec6664f6d61f46569a2686b864ba3e9a0f85fc60 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 5 Mar 2019 11:54:06 -0500 Subject: kernel/address_arbiter: Convert the address arbiter into a class Places all of the functions for address arbiter operation into a class. This will be necessary for future deglobalizing efforts related to both the memory and system itself. --- src/core/hle/kernel/address_arbiter.cpp | 117 ++++++++++++++++---------------- 1 file changed, 58 insertions(+), 59 deletions(-) (limited to 'src/core/hle/kernel/address_arbiter.cpp') diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index a250d088d..f14283cca 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -9,6 +9,7 @@ #include "common/common_types.h" #include "core/core.h" #include "core/core_cpu.h" +#include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/process.h" @@ -17,53 +18,10 @@ #include "core/hle/result.h" #include "core/memory.h" -namespace Kernel::AddressArbiter { - -// Performs actual address waiting logic. -static ResultCode WaitForAddress(VAddr address, s64 timeout) { - SharedPtr current_thread = GetCurrentThread(); - current_thread->SetArbiterWaitAddress(address); - current_thread->SetStatus(ThreadStatus::WaitArb); - current_thread->InvalidateWakeupCallback(); - - current_thread->WakeAfterDelay(timeout); - - Core::System::GetInstance().CpuCore(current_thread->GetProcessorID()).PrepareReschedule(); - return RESULT_TIMEOUT; -} - -// Gets the threads waiting on an address. -static std::vector> GetThreadsWaitingOnAddress(VAddr address) { - const auto RetrieveWaitingThreads = [](std::size_t core_index, - std::vector>& waiting_threads, - VAddr arb_addr) { - const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); - const auto& thread_list = scheduler.GetThreadList(); - - for (const auto& thread : thread_list) { - if (thread->GetArbiterWaitAddress() == arb_addr) - waiting_threads.push_back(thread); - } - }; - - // Retrieve all threads that are waiting for this address. - std::vector> threads; - RetrieveWaitingThreads(0, threads, address); - RetrieveWaitingThreads(1, threads, address); - RetrieveWaitingThreads(2, threads, address); - RetrieveWaitingThreads(3, threads, address); - - // Sort them by priority, such that the highest priority ones come first. - std::sort(threads.begin(), threads.end(), - [](const SharedPtr& lhs, const SharedPtr& rhs) { - return lhs->GetPriority() < rhs->GetPriority(); - }); - - return threads; -} - +namespace Kernel { +namespace { // Wake up num_to_wake (or all) threads in a vector. -static void WakeThreads(std::vector>& waiting_threads, s32 num_to_wake) { +void WakeThreads(std::vector>& waiting_threads, s32 num_to_wake) { // Only process up to 'target' threads, unless 'target' is <= 0, in which case process // them all. std::size_t last = waiting_threads.size(); @@ -78,17 +36,20 @@ static void WakeThreads(std::vector>& waiting_threads, s32 num waiting_threads[i]->ResumeFromWait(); } } +} // Anonymous namespace -// Signals an address being waited on. -ResultCode SignalToAddress(VAddr address, s32 num_to_wake) { +AddressArbiter::AddressArbiter() = default; +AddressArbiter::~AddressArbiter() = default; + +ResultCode AddressArbiter::SignalToAddress(VAddr address, s32 num_to_wake) { std::vector> waiting_threads = GetThreadsWaitingOnAddress(address); WakeThreads(waiting_threads, num_to_wake); return RESULT_SUCCESS; } -// Signals an address being waited on and increments its value if equal to the value argument. -ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake) { +ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, + s32 num_to_wake) { // Ensure that we can write to the address. if (!Memory::IsValidVirtualAddress(address)) { return ERR_INVALID_ADDRESS_STATE; @@ -103,10 +64,8 @@ ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_ return SignalToAddress(address, num_to_wake); } -// Signals an address being waited on and modifies its value based on waiting thread count if equal -// to the value argument. -ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, - s32 num_to_wake) { +ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, + s32 num_to_wake) { // Ensure that we can write to the address. if (!Memory::IsValidVirtualAddress(address)) { return ERR_INVALID_ADDRESS_STATE; @@ -135,8 +94,8 @@ ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 valu return RESULT_SUCCESS; } -// Waits on an address if the value passed is less than the argument value, optionally decrementing. -ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement) { +ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, + bool should_decrement) { // Ensure that we can read the address. if (!Memory::IsValidVirtualAddress(address)) { return ERR_INVALID_ADDRESS_STATE; @@ -158,8 +117,7 @@ ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool return WaitForAddress(address, timeout); } -// Waits on an address if the value passed is equal to the argument value. -ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { +ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { // Ensure that we can read the address. if (!Memory::IsValidVirtualAddress(address)) { return ERR_INVALID_ADDRESS_STATE; @@ -175,4 +133,45 @@ ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { return WaitForAddress(address, timeout); } -} // namespace Kernel::AddressArbiter + +ResultCode AddressArbiter::WaitForAddress(VAddr address, s64 timeout) { + SharedPtr current_thread = GetCurrentThread(); + current_thread->SetArbiterWaitAddress(address); + current_thread->SetStatus(ThreadStatus::WaitArb); + current_thread->InvalidateWakeupCallback(); + + current_thread->WakeAfterDelay(timeout); + + Core::System::GetInstance().CpuCore(current_thread->GetProcessorID()).PrepareReschedule(); + return RESULT_TIMEOUT; +} + +std::vector> AddressArbiter::GetThreadsWaitingOnAddress(VAddr address) const { + const auto RetrieveWaitingThreads = [](std::size_t core_index, + std::vector>& waiting_threads, + VAddr arb_addr) { + const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); + const auto& thread_list = scheduler.GetThreadList(); + + for (const auto& thread : thread_list) { + if (thread->GetArbiterWaitAddress() == arb_addr) + waiting_threads.push_back(thread); + } + }; + + // Retrieve all threads that are waiting for this address. + std::vector> threads; + RetrieveWaitingThreads(0, threads, address); + RetrieveWaitingThreads(1, threads, address); + RetrieveWaitingThreads(2, threads, address); + RetrieveWaitingThreads(3, threads, address); + + // Sort them by priority, such that the highest priority ones come first. + std::sort(threads.begin(), threads.end(), + [](const SharedPtr& lhs, const SharedPtr& rhs) { + return lhs->GetPriority() < rhs->GetPriority(); + }); + + return threads; +} +} // namespace Kernel -- cgit v1.2.3 From 9d9676f62055e9a765796d113ec110259a576927 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 5 Mar 2019 12:22:13 -0500 Subject: kernel/address_arbiter: Minor tidying up - Invert conditions into guard clases where applicable. - Mark std::vector parameter of WakeThreads as const --- src/core/hle/kernel/address_arbiter.cpp | 36 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src/core/hle/kernel/address_arbiter.cpp') diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index f14283cca..daebbbd1d 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -21,12 +21,13 @@ namespace Kernel { namespace { // Wake up num_to_wake (or all) threads in a vector. -void WakeThreads(std::vector>& waiting_threads, s32 num_to_wake) { +void WakeThreads(const std::vector>& waiting_threads, s32 num_to_wake) { // Only process up to 'target' threads, unless 'target' is <= 0, in which case process // them all. std::size_t last = waiting_threads.size(); - if (num_to_wake > 0) + if (num_to_wake > 0) { last = num_to_wake; + } // Signal the waiting threads. for (std::size_t i = 0; i < last; i++) { @@ -42,8 +43,7 @@ AddressArbiter::AddressArbiter() = default; AddressArbiter::~AddressArbiter() = default; ResultCode AddressArbiter::SignalToAddress(VAddr address, s32 num_to_wake) { - std::vector> waiting_threads = GetThreadsWaitingOnAddress(address); - + const std::vector> waiting_threads = GetThreadsWaitingOnAddress(address); WakeThreads(waiting_threads, num_to_wake); return RESULT_SUCCESS; } @@ -55,12 +55,11 @@ ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 return ERR_INVALID_ADDRESS_STATE; } - if (static_cast(Memory::Read32(address)) == value) { - Memory::Write32(address, static_cast(value + 1)); - } else { + if (static_cast(Memory::Read32(address)) != value) { return ERR_INVALID_STATE; } + Memory::Write32(address, static_cast(value + 1)); return SignalToAddress(address, num_to_wake); } @@ -72,7 +71,7 @@ ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr a } // Get threads waiting on the address. - std::vector> waiting_threads = GetThreadsWaitingOnAddress(address); + const std::vector> waiting_threads = GetThreadsWaitingOnAddress(address); // Determine the modified value depending on the waiting count. s32 updated_value; @@ -84,12 +83,11 @@ ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr a updated_value = value; } - if (static_cast(Memory::Read32(address)) == value) { - Memory::Write32(address, static_cast(updated_value)); - } else { + if (static_cast(Memory::Read32(address)) != value) { return ERR_INVALID_STATE; } + Memory::Write32(address, static_cast(updated_value)); WakeThreads(waiting_threads, num_to_wake); return RESULT_SUCCESS; } @@ -101,14 +99,15 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6 return ERR_INVALID_ADDRESS_STATE; } - s32 cur_value = static_cast(Memory::Read32(address)); - if (cur_value < value) { - if (should_decrement) { - Memory::Write32(address, static_cast(cur_value - 1)); - } - } else { + const s32 cur_value = static_cast(Memory::Read32(address)); + if (cur_value >= value) { return ERR_INVALID_STATE; } + + if (should_decrement) { + Memory::Write32(address, static_cast(cur_value - 1)); + } + // Short-circuit without rescheduling, if timeout is zero. if (timeout == 0) { return RESULT_TIMEOUT; @@ -154,8 +153,9 @@ std::vector> AddressArbiter::GetThreadsWaitingOnAddress(VAddr const auto& thread_list = scheduler.GetThreadList(); for (const auto& thread : thread_list) { - if (thread->GetArbiterWaitAddress() == arb_addr) + if (thread->GetArbiterWaitAddress() == arb_addr) { waiting_threads.push_back(thread); + } } }; -- cgit v1.2.3 From c161389a0f0b0fe3b9d6400c45fd87152f2cb14c Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 5 Mar 2019 12:28:10 -0500 Subject: kernel/address_arbiter: Pass in system instance to constructor Allows getting rid of reliance on the global accessor functions and instead operating on the provided system instance. --- src/core/hle/kernel/address_arbiter.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/core/hle/kernel/address_arbiter.cpp') diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index daebbbd1d..9780a7849 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -39,7 +39,7 @@ void WakeThreads(const std::vector>& waiting_threads, s32 num_ } } // Anonymous namespace -AddressArbiter::AddressArbiter() = default; +AddressArbiter::AddressArbiter(Core::System& system) : system{system} {} AddressArbiter::~AddressArbiter() = default; ResultCode AddressArbiter::SignalToAddress(VAddr address, s32 num_to_wake) { @@ -134,22 +134,22 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t } ResultCode AddressArbiter::WaitForAddress(VAddr address, s64 timeout) { - SharedPtr current_thread = GetCurrentThread(); + SharedPtr current_thread = system.CurrentScheduler().GetCurrentThread(); current_thread->SetArbiterWaitAddress(address); current_thread->SetStatus(ThreadStatus::WaitArb); current_thread->InvalidateWakeupCallback(); current_thread->WakeAfterDelay(timeout); - Core::System::GetInstance().CpuCore(current_thread->GetProcessorID()).PrepareReschedule(); + system.CpuCore(current_thread->GetProcessorID()).PrepareReschedule(); return RESULT_TIMEOUT; } std::vector> AddressArbiter::GetThreadsWaitingOnAddress(VAddr address) const { - const auto RetrieveWaitingThreads = [](std::size_t core_index, - std::vector>& waiting_threads, - VAddr arb_addr) { - const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); + const auto RetrieveWaitingThreads = [this](std::size_t core_index, + std::vector>& waiting_threads, + VAddr arb_addr) { + const auto& scheduler = system.Scheduler(core_index); const auto& thread_list = scheduler.GetThreadList(); for (const auto& thread : thread_list) { -- cgit v1.2.3