diff options
Diffstat (limited to 'src/core/hle/kernel/k_address_arbiter.cpp')
-rw-r--r-- | src/core/hle/kernel/k_address_arbiter.cpp | 118 |
1 files changed, 46 insertions, 72 deletions
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index d9e702f13..d0e90fd60 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -7,9 +7,9 @@ #include "core/hle/kernel/k_address_arbiter.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" +#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/svc_results.h" -#include "core/hle/kernel/thread.h" #include "core/hle/kernel/time_manager.h" #include "core/memory.h" @@ -96,7 +96,7 @@ ResultCode KAddressArbiter::Signal(VAddr addr, s32 count) { auto it = thread_tree.nfind_light({addr, -1}); while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { - Thread* target_thread = std::addressof(*it); + KThread* target_thread = std::addressof(*it); target_thread->SetSyncedObject(nullptr, RESULT_SUCCESS); ASSERT(target_thread->IsWaitingForAddressArbiter()); @@ -118,14 +118,18 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 // Check the userspace value. s32 user_value{}; - R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1), - Svc::ResultInvalidCurrentMemory); - R_UNLESS(user_value == value, Svc::ResultInvalidState); + if (!UpdateIfEqual(system, &user_value, addr, value, value + 1)) { + LOG_ERROR(Kernel, "Invalid current memory!"); + return Svc::ResultInvalidCurrentMemory; + } + if (user_value != value) { + return Svc::ResultInvalidState; + } auto it = thread_tree.nfind_light({addr, -1}); while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { - Thread* target_thread = std::addressof(*it); + KThread* target_thread = std::addressof(*it); target_thread->SetSyncedObject(nullptr, RESULT_SUCCESS); ASSERT(target_thread->IsWaitingForAddressArbiter()); @@ -143,61 +147,34 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(kernel); + [[maybe_unused]] const KScopedSchedulerLock sl(kernel); auto it = thread_tree.nfind_light({addr, -1}); // Determine the updated value. s32 new_value{}; - if (/*GetTargetFirmware() >= TargetFirmware_7_0_0*/ true) { - if (count <= 0) { - if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { - new_value = value - 2; - } else { - new_value = value + 1; - } + if (count <= 0) { + if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) { + new_value = value - 2; } else { - if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { - auto tmp_it = it; - s32 tmp_num_waiters{}; - while ((++tmp_it != thread_tree.end()) && - (tmp_it->GetAddressArbiterKey() == addr)) { - if ((tmp_num_waiters++) >= count) { - break; - } - } - - if (tmp_num_waiters < count) { - new_value = value - 1; - } else { - new_value = value; - } - } else { - new_value = value + 1; - } + new_value = value + 1; } } else { - if (count <= 0) { - if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { - new_value = value - 1; - } else { - new_value = value + 1; - } - } else { + if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) { auto tmp_it = it; s32 tmp_num_waiters{}; - while ((tmp_it != thread_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && - (tmp_num_waiters < count + 1)) { - ++tmp_num_waiters; - ++tmp_it; + while (++tmp_it != thread_tree.end() && tmp_it->GetAddressArbiterKey() == addr) { + if (tmp_num_waiters++ >= count) { + break; + } } - if (tmp_num_waiters == 0) { - new_value = value + 1; - } else if (tmp_num_waiters <= count) { + if (tmp_num_waiters < count) { new_value = value - 1; } else { new_value = value; } + } else { + new_value = value + 1; } } @@ -205,17 +182,22 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 s32 user_value{}; bool succeeded{}; if (value != new_value) { - succeeded = UpdateIfEqual(system, std::addressof(user_value), addr, value, new_value); + succeeded = UpdateIfEqual(system, &user_value, addr, value, new_value); } else { - succeeded = ReadFromUser(system, std::addressof(user_value), addr); + succeeded = ReadFromUser(system, &user_value, addr); } - R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory); - R_UNLESS(user_value == value, Svc::ResultInvalidState); + if (!succeeded) { + LOG_ERROR(Kernel, "Invalid current memory!"); + return Svc::ResultInvalidCurrentMemory; + } + if (user_value != value) { + return Svc::ResultInvalidState; + } while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) { - Thread* target_thread = std::addressof(*it); + KThread* target_thread = std::addressof(*it); target_thread->SetSyncedObject(nullptr, RESULT_SUCCESS); ASSERT(target_thread->IsWaitingForAddressArbiter()); @@ -231,11 +213,10 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) { // Prepare to wait. - Thread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); - Handle timer = InvalidHandle; + KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); { - KScopedSchedulerLockAndSleep slp(kernel, timer, cur_thread, timeout); + KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -250,9 +231,9 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement s32 user_value{}; bool succeeded{}; if (decrement) { - succeeded = DecrementIfLessThan(system, std::addressof(user_value), addr, value); + succeeded = DecrementIfLessThan(system, &user_value, addr, value); } else { - succeeded = ReadFromUser(system, std::addressof(user_value), addr); + succeeded = ReadFromUser(system, &user_value, addr); } if (!succeeded) { @@ -273,17 +254,14 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement } // Set the arbiter. - cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); + cur_thread->SetAddressArbiter(&thread_tree, addr); thread_tree.insert(*cur_thread); cur_thread->SetState(ThreadState::Waiting); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } // Cancel the timer wait. - if (timer != InvalidHandle) { - auto& time_manager = kernel.TimeManager(); - time_manager.UnscheduleTimeEvent(timer); - } + kernel.TimeManager().UnscheduleTimeEvent(cur_thread); // Remove from the address arbiter. { @@ -297,16 +275,15 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement // Get the result. KSynchronizationObject* dummy{}; - return cur_thread->GetWaitResult(std::addressof(dummy)); + return cur_thread->GetWaitResult(&dummy); } ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { // Prepare to wait. - Thread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); - Handle timer = InvalidHandle; + KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); { - KScopedSchedulerLockAndSleep slp(kernel, timer, cur_thread, timeout); + KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; // Check that the thread isn't terminating. if (cur_thread->IsTerminationRequested()) { @@ -319,7 +296,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { // Read the value from userspace. s32 user_value{}; - if (!ReadFromUser(system, std::addressof(user_value), addr)) { + if (!ReadFromUser(system, &user_value, addr)) { slp.CancelSleep(); return Svc::ResultInvalidCurrentMemory; } @@ -337,17 +314,14 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { } // Set the arbiter. - cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); + cur_thread->SetAddressArbiter(&thread_tree, addr); thread_tree.insert(*cur_thread); cur_thread->SetState(ThreadState::Waiting); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); } // Cancel the timer wait. - if (timer != InvalidHandle) { - auto& time_manager = kernel.TimeManager(); - time_manager.UnscheduleTimeEvent(timer); - } + kernel.TimeManager().UnscheduleTimeEvent(cur_thread); // Remove from the address arbiter. { @@ -361,7 +335,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { // Get the result. KSynchronizationObject* dummy{}; - return cur_thread->GetWaitResult(std::addressof(dummy)); + return cur_thread->GetWaitResult(&dummy); } } // namespace Kernel |