From 8c16b90eaecad4c8f00aea27641cf92bbc455997 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 6 Dec 2017 09:06:45 -0500 Subject: [PATCH] HLE/AddressArbiter: Remove threads that were awoken by timeout from the arbiter's waitlist when using WaitIfLessThanWithTimeout and DecrementAndWaitIfLessThanWithTimeout. Fixes a regression introduced in #3096 --- src/core/hle/kernel/address_arbiter.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 5970d71c8..687887568 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -77,6 +77,15 @@ SharedPtr AddressArbiter::Create(std::string name) { ResultCode AddressArbiter::ArbitrateAddress(SharedPtr thread, ArbitrationType type, VAddr address, s32 value, u64 nanoseconds) { + + auto timeout_callback = [this](ThreadWakeupReason reason, SharedPtr thread, + SharedPtr object) { + ASSERT(reason == ThreadWakeupReason::Timeout); + // Remove the newly-awakened thread from the Arbiter's waiting list. + waiting_threads.erase(std::remove(waiting_threads.begin(), waiting_threads.end(), thread), + waiting_threads.end()); + }; + switch (type) { // Signal thread(s) waiting for arbitrate address... @@ -99,6 +108,7 @@ ResultCode AddressArbiter::ArbitrateAddress(SharedPtr thread, Arbitratio break; case ArbitrationType::WaitIfLessThanWithTimeout: if ((s32)Memory::Read32(address) < value) { + thread->wakeup_callback = timeout_callback; thread->WakeAfterDelay(nanoseconds); WaitThread(std::move(thread), address); } @@ -117,6 +127,7 @@ ResultCode AddressArbiter::ArbitrateAddress(SharedPtr thread, Arbitratio if (memory_value < value) { // Only change the memory value if the thread should wait Memory::Write32(address, (s32)memory_value - 1); + thread->wakeup_callback = timeout_callback; thread->WakeAfterDelay(nanoseconds); WaitThread(std::move(thread), address); }