From 8c9d258e6635b90dc63b639ea8ade98779b9ef30 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 25 Feb 2020 16:38:33 -0400 Subject: SVC: Correct SignalEvent, ClearEvent, ResetSignal, WaitSynchronization, CancelSynchronization, ArbitrateLock --- src/core/hle/kernel/synchronization.cpp | 118 +++++++++++++++++--------------- 1 file changed, 64 insertions(+), 54 deletions(-) (limited to 'src/core/hle/kernel/synchronization.cpp') diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index dc37fad1a7..b36e550a04 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp @@ -10,78 +10,88 @@ #include "core/hle/kernel/synchronization.h" #include "core/hle/kernel/synchronization_object.h" #include "core/hle/kernel/thread.h" +#include "core/hle/kernel/time_manager.h" namespace Kernel { -/// Default thread wakeup callback for WaitSynchronization -static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, std::shared_ptr thread, - std::shared_ptr object, - std::size_t index) { - ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch); - - if (reason == ThreadWakeupReason::Timeout) { - thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); - return true; - } - - ASSERT(reason == ThreadWakeupReason::Signal); - thread->SetWaitSynchronizationResult(RESULT_SUCCESS); - thread->SetWaitSynchronizationOutput(static_cast(index)); - return true; -} - Synchronization::Synchronization(Core::System& system) : system{system} {} void Synchronization::SignalObject(SynchronizationObject& obj) const { + SchedulerLock lock(system.Kernel()); if (obj.IsSignaled()) { - obj.WakeupAllWaitingThreads(); + for (auto thread : obj.GetWaitingThreads()) { + if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) { + thread->SetSynchronizationResults(&obj, RESULT_SUCCESS); + thread->ResumeFromWait(); + } + } } } std::pair Synchronization::WaitFor( std::vector>& sync_objects, s64 nano_seconds) { + auto& kernel = system.Kernel(); auto* const thread = system.CurrentScheduler().GetCurrentThread(); - // Find the first object that is acquirable in the provided list of objects - const auto itr = std::find_if(sync_objects.begin(), sync_objects.end(), - [thread](const std::shared_ptr& object) { - return object->IsSignaled(); - }); - - if (itr != sync_objects.end()) { - // We found a ready object, acquire it and set the result value - SynchronizationObject* object = itr->get(); - object->Acquire(thread); - const u32 index = static_cast(std::distance(sync_objects.begin(), itr)); - return {RESULT_SUCCESS, index}; + Handle event_handle = InvalidHandle; + { + SchedulerLockAndSleep lock(kernel, event_handle, thread, nano_seconds); + const auto itr = + std::find_if(sync_objects.begin(), sync_objects.end(), + [thread](const std::shared_ptr& object) { + return object->IsSignaled(); + }); + + if (itr != sync_objects.end()) { + // We found a ready object, acquire it and set the result value + SynchronizationObject* object = itr->get(); + object->Acquire(thread); + const u32 index = static_cast(std::distance(sync_objects.begin(), itr)); + lock.CancelSleep(); + return {RESULT_SUCCESS, index}; + } + + if (nano_seconds == 0) { + lock.CancelSleep(); + return {RESULT_TIMEOUT, InvalidHandle}; + } + + /// TODO(Blinkhawk): Check for termination pending + + if (thread->IsSyncCancelled()) { + thread->SetSyncCancelled(false); + lock.CancelSleep(); + return {ERR_SYNCHRONIZATION_CANCELED, InvalidHandle}; + } + + for (auto& object : sync_objects) { + object->AddWaitingThread(SharedFrom(thread)); + } + thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); + thread->SetStatus(ThreadStatus::WaitSynch); } - // No objects were ready to be acquired, prepare to suspend the thread. - - // If a timeout value of 0 was provided, just return the Timeout error code instead of - // suspending the thread. - if (nano_seconds == 0) { - return {RESULT_TIMEOUT, InvalidHandle}; + if (event_handle != InvalidHandle) { + auto& time_manager = kernel.TimeManager(); + time_manager.UnscheduleTimeEvent(event_handle); } - if (thread->IsSyncCancelled()) { - thread->SetSyncCancelled(false); - return {ERR_SYNCHRONIZATION_CANCELED, InvalidHandle}; + { + SchedulerLock lock(kernel); + ResultCode signaling_result = thread->GetSignalingResult(); + SynchronizationObject* signaling_object = thread->GetSignalingObject(); + if (signaling_result == RESULT_SUCCESS) { + const auto itr = std::find_if( + sync_objects.begin(), sync_objects.end(), + [signaling_object](const std::shared_ptr& object) { + return object.get() == signaling_object; + }); + ASSERT(itr != sync_objects.end()); + signaling_object->Acquire(thread); + const u32 index = static_cast(std::distance(sync_objects.begin(), itr)); + return {RESULT_SUCCESS, index}; + } + return {signaling_result, -1}; } - - for (auto& object : sync_objects) { - object->AddWaitingThread(SharedFrom(thread)); - } - - thread->SetSynchronizationObjects(std::move(sync_objects)); - thread->SetStatus(ThreadStatus::WaitSynch); - - // Create an event to wake the thread up after the specified nanosecond delay has passed - thread->WakeAfterDelay(nano_seconds); - thread->SetWakeupCallback(DefaultThreadWakeupCallback); - - system.PrepareReschedule(thread->GetProcessorID()); - - return {RESULT_TIMEOUT, InvalidHandle}; } } // namespace Kernel -- cgit v1.2.3 From 6605f8acfa1d4ccd2b36bede7c93d8b92acdf66e Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 26 Feb 2020 22:26:53 -0400 Subject: SVC: Correct WaitSynchronization, WaitProcessWideKey, SignalProcessWideKey. --- src/core/hle/kernel/process.cpp | 1 - src/core/hle/kernel/scheduler.cpp | 2 +- src/core/hle/kernel/svc.cpp | 75 ++++++++++++++++---------- src/core/hle/kernel/synchronization.cpp | 8 ++- src/core/hle/kernel/synchronization_object.cpp | 4 ++ src/core/hle/kernel/synchronization_object.h | 2 + src/core/hle/kernel/thread.cpp | 2 +- src/core/hle/kernel/time_manager.cpp | 18 ++++++- src/core/hle/kernel/time_manager.h | 5 ++ 9 files changed, 84 insertions(+), 33 deletions(-) (limited to 'src/core/hle/kernel/synchronization.cpp') diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index cd4b0aa606..ea5fe5b292 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -187,7 +187,6 @@ void Process::RemoveConditionVariableThread(std::shared_ptr thread) { } ++it; } - UNREACHABLE(); } std::vector> Process::GetConditionVariableThreads( diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 0e85ee69ed..758fa81881 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -632,7 +632,7 @@ void Scheduler::SwitchContext() { cpu_core.SaveContext(previous_thread->GetContext64()); // Save the TPIDR_EL0 system register in case it was modified. previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); - + cpu_core.ClearExclusiveState(); } if (previous_thread->GetStatus() == ThreadStatus::Running) { previous_thread->SetStatus(ThreadStatus::Ready); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 8634d3feb9..a5193063b4 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1541,33 +1541,50 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add return ERR_INVALID_ADDRESS; } - UNIMPLEMENTED(); - ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); - + auto& kernel = system.Kernel(); + Handle event_handle; + Thread* current_thread = system.CurrentScheduler().GetCurrentThread(); auto* const current_process = system.Kernel().CurrentProcess(); - const auto& handle_table = current_process->GetHandleTable(); - std::shared_ptr thread = handle_table.Get(thread_handle); - ASSERT(thread); + { + SchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds); + const auto& handle_table = current_process->GetHandleTable(); + std::shared_ptr thread = handle_table.Get(thread_handle); + ASSERT(thread); + + current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); + + const auto release_result = current_process->GetMutex().Release(mutex_addr); + if (release_result.IsError()) { + lock.CancelSleep(); + return release_result; + } - const auto release_result = current_process->GetMutex().Release(mutex_addr); - if (release_result.IsError()) { - return release_result; + if (nano_seconds == 0) { + lock.CancelSleep(); + return RESULT_TIMEOUT; + } + + current_thread->SetCondVarWaitAddress(condition_variable_addr); + current_thread->SetMutexWaitAddress(mutex_addr); + current_thread->SetWaitHandle(thread_handle); + current_thread->SetStatus(ThreadStatus::WaitCondVar); + current_process->InsertConditionVariableThread(SharedFrom(current_thread)); } - Thread* current_thread = system.CurrentScheduler().GetCurrentThread(); - current_thread->SetCondVarWaitAddress(condition_variable_addr); - current_thread->SetMutexWaitAddress(mutex_addr); - current_thread->SetWaitHandle(thread_handle); - current_thread->SetStatus(ThreadStatus::WaitCondVar); - current_thread->InvalidateWakeupCallback(); - current_process->InsertConditionVariableThread(SharedFrom(current_thread)); + if (event_handle != InvalidHandle) { + auto& time_manager = kernel.TimeManager(); + time_manager.UnscheduleTimeEvent(event_handle); + } - current_thread->WakeAfterDelay(nano_seconds); + { + SchedulerLock lock(kernel); + current_process->RemoveConditionVariableThread(SharedFrom(current_thread)); + } // Note: Deliberately don't attempt to inherit the lock owner's priority. - return RESULT_SUCCESS; + return current_thread->GetSignalingResult(); } /// Signal process wide key @@ -1577,10 +1594,10 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); - UNIMPLEMENTED(); - // Retrieve a list of all threads that are waiting for this condition variable. - auto* const current_process = system.Kernel().CurrentProcess(); + auto& kernel = system.Kernel(); + SchedulerLock lock(kernel); + auto* const current_process = kernel.CurrentProcess(); std::vector> waiting_threads = current_process->GetConditionVariableThreads(condition_variable_addr); @@ -1589,10 +1606,18 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ std::size_t last = waiting_threads.size(); if (target > 0) last = std::min(waiting_threads.size(), static_cast(target)); - + auto& time_manager = kernel.TimeManager(); for (std::size_t index = 0; index < last; ++index) { auto& thread = waiting_threads[index]; + if (thread->GetStatus() != ThreadStatus::WaitCondVar) { + last++; + last = std::min(waiting_threads.size(), last); + continue; + } + + time_manager.CancelTimeEvent(thread.get()); + ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr); // liberate Cond Var Thread. @@ -1630,17 +1655,13 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ } thread->SetLockOwner(nullptr); - thread->SetMutexWaitAddress(0); - thread->SetWaitHandle(0); - thread->SetWaitSynchronizationResult(RESULT_SUCCESS); + thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS); } else { // The mutex is already owned by some other thread, make this thread wait on it. const Handle owner_handle = static_cast(mutex_val & Mutex::MutexOwnerMask); const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); auto owner = handle_table.Get(owner_handle); ASSERT(owner); - ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar); - thread->InvalidateWakeupCallback(); thread->SetStatus(ThreadStatus::WaitMutex); owner->AddMutexWaiter(thread); diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index b36e550a04..c60c5bb422 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp @@ -17,12 +17,15 @@ namespace Kernel { Synchronization::Synchronization(Core::System& system) : system{system} {} void Synchronization::SignalObject(SynchronizationObject& obj) const { - SchedulerLock lock(system.Kernel()); + auto& kernel = system.Kernel(); + SchedulerLock lock(kernel); + auto& time_manager = kernel.TimeManager(); if (obj.IsSignaled()) { for (auto thread : obj.GetWaitingThreads()) { if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) { thread->SetSynchronizationResults(&obj, RESULT_SUCCESS); thread->ResumeFromWait(); + time_manager.CancelTimeEvent(thread.get()); } } } @@ -79,6 +82,9 @@ std::pair Synchronization::WaitFor( SchedulerLock lock(kernel); ResultCode signaling_result = thread->GetSignalingResult(); SynchronizationObject* signaling_object = thread->GetSignalingObject(); + for (auto& obj : sync_objects) { + obj->RemoveWaitingThread(SharedFrom(thread)); + } if (signaling_result == RESULT_SUCCESS) { const auto itr = std::find_if( sync_objects.begin(), sync_objects.end(), diff --git a/src/core/hle/kernel/synchronization_object.cpp b/src/core/hle/kernel/synchronization_object.cpp index 43f3eef185..be9e091068 100644 --- a/src/core/hle/kernel/synchronization_object.cpp +++ b/src/core/hle/kernel/synchronization_object.cpp @@ -102,6 +102,10 @@ void SynchronizationObject::WakeupAllWaitingThreads() { } } +void SynchronizationObject::ClearWaitingThreads() { + waiting_threads.clear(); +} + const std::vector>& SynchronizationObject::GetWaitingThreads() const { return waiting_threads; } diff --git a/src/core/hle/kernel/synchronization_object.h b/src/core/hle/kernel/synchronization_object.h index 0a0d069e0e..a35544ac13 100644 --- a/src/core/hle/kernel/synchronization_object.h +++ b/src/core/hle/kernel/synchronization_object.h @@ -68,6 +68,8 @@ public: /// Get a const reference to the waiting threads list for debug use const std::vector>& GetWaitingThreads() const; + void ClearWaitingThreads(); + protected: bool is_signaled{}; // Tells if this sync object is signalled; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index fb97535a3b..a645ee3a20 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -49,12 +49,12 @@ Thread::~Thread() = default; void Thread::Stop() { SchedulerLock lock(kernel); // Cancel any outstanding wakeup events for this thread + Signal(); Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), global_handle); kernel.GlobalHandleTable().Close(global_handle); global_handle = 0; SetStatus(ThreadStatus::Dead); - Signal(); owner_process->UnregisterThread(this); diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index 0b8f0d993b..dab5fc4c6f 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp @@ -8,15 +8,21 @@ #include "core/core_timing_util.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/time_manager.h" namespace Kernel { -TimeManager::TimeManager(Core::System& system) : system{system} { +TimeManager::TimeManager(Core::System& system_) : system{system_} { time_manager_event_type = Core::Timing::CreateEvent( "Kernel::TimeManagerCallback", [this](u64 thread_handle, [[maybe_unused]] s64 cycles_late) { + SchedulerLock lock(system.Kernel()); Handle proper_handle = static_cast(thread_handle); + if (cancelled_events[proper_handle]) { + return; + } + event_fired[proper_handle] = true; std::shared_ptr thread = this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); thread->OnWakeUp(); @@ -24,14 +30,16 @@ TimeManager::TimeManager(Core::System& system) : system{system} { } void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 nanoseconds) { + event_handle = timetask->GetGlobalHandle(); if (nanoseconds > 0) { ASSERT(timetask); - event_handle = timetask->GetGlobalHandle(); const s64 cycles = Core::Timing::nsToCycles(std::chrono::nanoseconds{nanoseconds}); system.CoreTiming().ScheduleEvent(cycles, time_manager_event_type, event_handle); } else { event_handle = InvalidHandle; } + cancelled_events[event_handle] = false; + event_fired[event_handle] = false; } void TimeManager::UnscheduleTimeEvent(Handle event_handle) { @@ -39,6 +47,12 @@ void TimeManager::UnscheduleTimeEvent(Handle event_handle) { return; } system.CoreTiming().UnscheduleEvent(time_manager_event_type, event_handle); + cancelled_events[event_handle] = true; +} + +void TimeManager::CancelTimeEvent(Thread* time_task) { + Handle event_handle = time_task->GetGlobalHandle(); + UnscheduleTimeEvent(event_handle); } } // namespace Kernel diff --git a/src/core/hle/kernel/time_manager.h b/src/core/hle/kernel/time_manager.h index eaec486d1a..3080ac8383 100644 --- a/src/core/hle/kernel/time_manager.h +++ b/src/core/hle/kernel/time_manager.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include "core/hle/kernel/object.h" @@ -35,9 +36,13 @@ public: /// Unschedule an existing time event void UnscheduleTimeEvent(Handle event_handle); + void CancelTimeEvent(Thread* time_task); + private: Core::System& system; std::shared_ptr time_manager_event_type; + std::unordered_map cancelled_events; + std::unordered_map event_fired; }; } // namespace Kernel -- cgit v1.2.3 From da260b9d2e9b81c039d2c1a6ae4a681f023ea07b Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 3 Mar 2020 13:02:50 -0400 Subject: Core: Correct HLE Event Callbacks and other issues. --- src/core/hle/kernel/hle_ipc.cpp | 19 +++++++++--------- src/core/hle/kernel/svc.cpp | 5 ++--- src/core/hle/kernel/synchronization.cpp | 1 + src/core/hle/kernel/thread.cpp | 35 ++++++++++++++++----------------- src/core/hle/kernel/thread.h | 16 ++++++++------- 5 files changed, 39 insertions(+), 37 deletions(-) (limited to 'src/core/hle/kernel/synchronization.cpp') diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 955d5fe1c6..e74d91670d 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -21,8 +21,8 @@ #include "core/hle/kernel/object.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/readable_event.h" -#include "core/hle/kernel/server_session.h" #include "core/hle/kernel/scheduler.h" +#include "core/hle/kernel/server_session.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/time_manager.h" #include "core/hle/kernel/writable_event.h" @@ -49,14 +49,6 @@ std::shared_ptr HLERequestContext::SleepClientThread( const std::string& reason, u64 timeout, WakeupCallback&& callback, std::shared_ptr writable_event) { // Put the client thread to sleep until the wait event is signaled or the timeout expires. - thread->SetHLECallback( - [context = *this, callback](ThreadWakeupReason reason, std::shared_ptr thread, - std::shared_ptr object, - std::size_t index) mutable -> bool { - callback(thread, context, reason); - context.WriteToOutgoingCommandBuffer(*thread); - return true; - }); if (!writable_event) { // Create event if not provided @@ -67,6 +59,15 @@ std::shared_ptr HLERequestContext::SleepClientThread( { Handle event_handle = InvalidHandle; SchedulerLockAndSleep lock(kernel, event_handle, thread.get(), timeout); + thread->SetHLECallback( + [context = *this, callback](std::shared_ptr thread) mutable -> bool { + ThreadWakeupReason reason = thread->GetSignalingResult() == RESULT_TIMEOUT + ? ThreadWakeupReason::Timeout + : ThreadWakeupReason::Signal; + callback(thread, context, reason); + context.WriteToOutgoingCommandBuffer(*thread); + return true; + }); const auto readable_event{writable_event->GetReadableEvent()}; writable_event->Clear(); thread->SetStatus(ThreadStatus::WaitHLEEvent); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 4c1040a3b9..9f46a17589 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -333,17 +333,16 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { thread->SetStatus(ThreadStatus::WaitIPC); session->SendSyncRequest(SharedFrom(thread), system.Memory()); } - ResultCode result = thread->GetSignalingResult(); if (thread->HasHLECallback()) { Handle event_handle = thread->GetHLETimeEvent(); if (event_handle != InvalidHandle) { auto& time_manager = system.Kernel().TimeManager(); time_manager.UnscheduleTimeEvent(event_handle); } - thread->InvokeHLECallback(ThreadWakeupReason::Timeout, SharedFrom(thread), nullptr, 0); + thread->InvokeHLECallback(SharedFrom(thread)); } - return result; + return RESULT_SUCCESS; } static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index c60c5bb422..4ee7ad93ca 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp @@ -28,6 +28,7 @@ void Synchronization::SignalObject(SynchronizationObject& obj) const { time_manager.CancelTimeEvent(thread.get()); } } + obj.ClearWaitingThreads(); } } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index a645ee3a20..16babe71a2 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -47,19 +47,21 @@ Thread::Thread(KernelCore& kernel) : SynchronizationObject{kernel} {} Thread::~Thread() = default; void Thread::Stop() { - SchedulerLock lock(kernel); - // Cancel any outstanding wakeup events for this thread - Signal(); - Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), - global_handle); - kernel.GlobalHandleTable().Close(global_handle); - global_handle = 0; - SetStatus(ThreadStatus::Dead); + { + SchedulerLock lock(kernel); + // Cancel any outstanding wakeup events for this thread + Signal(); + Core::System::GetInstance().CoreTiming().UnscheduleEvent( + kernel.ThreadWakeupCallbackEventType(), global_handle); + kernel.GlobalHandleTable().Close(global_handle); + SetStatus(ThreadStatus::Dead); - owner_process->UnregisterThread(this); + owner_process->UnregisterThread(this); - // Mark the TLS slot in the thread's page as free. - owner_process->FreeTLSRegion(tls_address); + // Mark the TLS slot in the thread's page as free. + owner_process->FreeTLSRegion(tls_address); + } + global_handle = 0; } void Thread::WakeAfterDelay(s64 nanoseconds) { @@ -112,8 +114,6 @@ void Thread::ResumeFromWait() { return; } - hle_callback = nullptr; - if (activity == ThreadActivity::Paused) { SetStatus(ThreadStatus::Paused); return; @@ -398,14 +398,13 @@ bool Thread::AllSynchronizationObjectsReady() const { bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr thread, std::shared_ptr object, std::size_t index) { - ASSERT(hle_callback); - return hle_callback(reason, std::move(thread), std::move(object), index); + ASSERT(wakeup_callback); + return wakeup_callback(reason, std::move(thread), std::move(object), index); } -bool Thread::InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr thread, - std::shared_ptr object, std::size_t index) { +bool Thread::InvokeHLECallback(std::shared_ptr thread) { ASSERT(hle_callback); - return hle_callback(reason, std::move(thread), std::move(object), index); + return hle_callback(std::move(thread)); } void Thread::SetActivity(ThreadActivity value) { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 04496f96ed..c4c9d69ec9 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -448,7 +448,7 @@ public: } bool HasWakeupCallback() const { - return hle_callback != nullptr; + return wakeup_callback != nullptr; } bool HasHLECallback() const { @@ -456,10 +456,10 @@ public: } void SetWakeupCallback(WakeupCallback callback) { - hle_callback = std::move(callback); + wakeup_callback = std::move(callback); } - void SetHLECallback(WakeupCallback callback) { + void SetHLECallback(HLECallback callback) { hle_callback = std::move(callback); } @@ -487,8 +487,7 @@ public: */ bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr thread, std::shared_ptr object, std::size_t index); - bool InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr thread, - std::shared_ptr object, std::size_t index); + bool InvokeHLECallback(std::shared_ptr thread); u32 GetIdealCore() const { return ideal_core; @@ -622,8 +621,11 @@ private: /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread /// was waiting via WaitSynchronization then the object will be the last object that became - /// available. In case of a timeout, the object will be nullptr. - WakeupCallback hle_callback; + /// available. In case of a timeout, the object will be nullptr. DEPRECATED + WakeupCallback wakeup_callback; + + /// Callback for HLE Events + HLECallback hle_callback; Handle hle_time_event; Scheduler* scheduler = nullptr; -- cgit v1.2.3 From 5e26654c5ad0ec650b9724e59cab165dcbcf66dc Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 3 Mar 2020 13:37:11 -0400 Subject: Kernel: Correct Signal on Thread Death and Setup Sync Objects on Thread for Debugging --- src/core/hle/kernel/synchronization.cpp | 3 +++ src/core/hle/kernel/thread.cpp | 15 +++++++-------- src/core/hle/kernel/thread.h | 14 +++++++------- 3 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src/core/hle/kernel/synchronization.cpp') diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index 4ee7ad93ca..ac43a70946 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp @@ -70,6 +70,8 @@ std::pair Synchronization::WaitFor( for (auto& object : sync_objects) { object->AddWaitingThread(SharedFrom(thread)); } + + thread->SetSynchronizationObjects(&sync_objects); thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); thread->SetStatus(ThreadStatus::WaitSynch); } @@ -83,6 +85,7 @@ std::pair Synchronization::WaitFor( SchedulerLock lock(kernel); ResultCode signaling_result = thread->GetSignalingResult(); SynchronizationObject* signaling_object = thread->GetSignalingObject(); + thread->SetSynchronizationObjects(nullptr); for (auto& obj : sync_objects) { obj->RemoveWaitingThread(SharedFrom(thread)); } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 16babe71a2..fb17518605 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -50,11 +50,11 @@ void Thread::Stop() { { SchedulerLock lock(kernel); // Cancel any outstanding wakeup events for this thread - Signal(); Core::System::GetInstance().CoreTiming().UnscheduleEvent( kernel.ThreadWakeupCallbackEventType(), global_handle); - kernel.GlobalHandleTable().Close(global_handle); SetStatus(ThreadStatus::Dead); + Signal(); + kernel.GlobalHandleTable().Close(global_handle); owner_process->UnregisterThread(this); @@ -81,7 +81,6 @@ void Thread::CancelWakeupTimer() { } void Thread::ResumeFromWait() { - ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects"); SchedulerLock lock(kernel); switch (status) { case ThreadStatus::Paused: @@ -219,7 +218,7 @@ ResultVal> Thread::Create(Core::System& system, ThreadTy thread->processor_id = processor_id; thread->ideal_core = processor_id; thread->affinity_mask = 1ULL << processor_id; - thread->wait_objects.clear(); + thread->wait_objects = nullptr; thread->mutex_wait_address = 0; thread->condvar_wait_address = 0; thread->wait_handle = 0; @@ -272,9 +271,9 @@ void Thread::SetSynchronizationResults(SynchronizationObject* object, ResultCode } s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr object) const { - ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything"); - const auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object); - return static_cast(std::distance(match, wait_objects.rend()) - 1); + ASSERT_MSG(!wait_objects->empty(), "Thread is not waiting for anything"); + const auto match = std::find(wait_objects->rbegin(), wait_objects->rend(), object); + return static_cast(std::distance(match, wait_objects->rend()) - 1); } VAddr Thread::GetCommandBufferAddress() const { @@ -389,7 +388,7 @@ void Thread::UpdatePriority() { } bool Thread::AllSynchronizationObjectsReady() const { - return std::none_of(wait_objects.begin(), wait_objects.end(), + return std::none_of(wait_objects->begin(), wait_objects->end(), [this](const std::shared_ptr& object) { return object->ShouldWait(this); }); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index c4c9d69ec9..7b6d1b4ec7 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -21,7 +21,7 @@ class Fiber; namespace Core { class System; -} +} // namespace Core namespace Kernel { @@ -386,18 +386,18 @@ public: } const ThreadSynchronizationObjects& GetSynchronizationObjects() const { - return wait_objects; + return *wait_objects; } - void SetSynchronizationObjects(ThreadSynchronizationObjects objects) { - wait_objects = std::move(objects); + void SetSynchronizationObjects(ThreadSynchronizationObjects* objects) { + wait_objects = objects; } void ClearSynchronizationObjects() { - for (const auto& waiting_object : wait_objects) { + for (const auto& waiting_object : *wait_objects) { waiting_object->RemoveWaitingThread(SharedFrom(this)); } - wait_objects.clear(); + wait_objects->clear(); } /// Determines whether all the objects this thread is waiting on are ready. @@ -595,7 +595,7 @@ private: /// Objects that the thread is waiting on, in the same order as they were /// passed to WaitSynchronization. - ThreadSynchronizationObjects wait_objects; + ThreadSynchronizationObjects* wait_objects; SynchronizationObject* signaling_object; ResultCode signaling_result{RESULT_SUCCESS}; -- cgit v1.2.3 From c1f6b99653263834d32876fc261d98bb0a4caa33 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 7 Mar 2020 10:24:46 -0400 Subject: SCC: Small corrections to CancelSynchronization --- src/core/hle/kernel/synchronization.cpp | 2 ++ src/core/hle/kernel/thread.cpp | 5 +++-- src/core/hle/kernel/thread.h | 9 +++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/synchronization.cpp') diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index ac43a70946..a7e3fbe92f 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp @@ -74,7 +74,9 @@ std::pair Synchronization::WaitFor( thread->SetSynchronizationObjects(&sync_objects); thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); thread->SetStatus(ThreadStatus::WaitSynch); + thread->SetWaitingSync(true); } + thread->SetWaitingSync(false); if (event_handle != InvalidHandle) { auto& time_manager = kernel.TimeManager(); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index fb17518605..e8962a0d8f 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -139,13 +139,14 @@ ResultCode Thread::Start() { void Thread::CancelWait() { SchedulerLock lock(kernel); - if (GetSchedulingStatus() != ThreadSchedStatus::Paused) { + if (GetSchedulingStatus() != ThreadSchedStatus::Paused || !is_waiting_on_sync) { is_sync_cancelled = true; return; } + //TODO(Blinkhawk): Implement cancel of server session is_sync_cancelled = false; SetSynchronizationResults(nullptr, ERR_SYNCHRONIZATION_CANCELED); - ResumeFromWait(); + SetStatus(ThreadStatus::Ready); } static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, u32 stack_top, diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index e8355bbd13..d8a983200c 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -556,6 +556,14 @@ public: waiting_for_arbitration = set; } + bool IsWaitingSync() const { + return is_waiting_on_sync; + } + + void SetWaitingSync(bool is_waiting) { + is_waiting_on_sync = is_waiting; + } + private: friend class GlobalScheduler; friend class Scheduler; @@ -650,6 +658,7 @@ private: u32 scheduling_state = 0; bool is_running = false; + bool is_waiting_on_sync = false; bool is_sync_cancelled = false; bool will_be_terminated{}; -- cgit v1.2.3 From d2a2c5f57bd4e155ffa8d99b86ae5afbd0ffc56b Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 7 Mar 2020 13:37:47 -0400 Subject: SVC: WaitSynchronization add Termination Pending Result. --- src/core/hle/kernel/errors.h | 1 + src/core/hle/kernel/synchronization.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/core/hle/kernel/synchronization.cpp') diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h index 29bfa3621f..d4e5d88cff 100644 --- a/src/core/hle/kernel/errors.h +++ b/src/core/hle/kernel/errors.h @@ -12,6 +12,7 @@ namespace Kernel { constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED{ErrorModule::Kernel, 7}; constexpr ResultCode ERR_INVALID_CAPABILITY_DESCRIPTOR{ErrorModule::Kernel, 14}; +constexpr ResultCode ERR_THREAD_TERMINATING{ErrorModule::Kernel, 59}; constexpr ResultCode ERR_INVALID_SIZE{ErrorModule::Kernel, 101}; constexpr ResultCode ERR_INVALID_ADDRESS{ErrorModule::Kernel, 102}; constexpr ResultCode ERR_OUT_OF_RESOURCES{ErrorModule::Kernel, 103}; diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index a7e3fbe92f..4323fc1208 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp @@ -59,7 +59,10 @@ std::pair Synchronization::WaitFor( return {RESULT_TIMEOUT, InvalidHandle}; } - /// TODO(Blinkhawk): Check for termination pending + if (thread->IsPendingTermination()) { + lock.CancelSleep(); + return {ERR_THREAD_TERMINATING, InvalidHandle}; + } if (thread->IsSyncCancelled()) { thread->SetSyncCancelled(false); -- cgit v1.2.3 From 24bc1f020a4bc605fcea7bca4c7f055660582942 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 8 Mar 2020 12:51:24 -0400 Subject: Kernel: Fixes, corrections and asserts to scheduler and different svcs. --- src/core/hle/kernel/address_arbiter.cpp | 27 ++++++++++++--------------- src/core/hle/kernel/kernel.cpp | 1 + src/core/hle/kernel/scheduler.cpp | 3 ++- src/core/hle/kernel/scheduler.h | 5 +++-- src/core/hle/kernel/svc.cpp | 27 ++++++++++++++------------- src/core/hle/kernel/synchronization.cpp | 10 ++++++---- src/core/hle/kernel/time_manager.cpp | 2 -- src/core/hle/kernel/time_manager.h | 1 - 8 files changed, 38 insertions(+), 38 deletions(-) (limited to 'src/core/hle/kernel/synchronization.cpp') diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 07acabc1d5..e8f22b598e 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -34,19 +34,9 @@ void AddressArbiter::WakeThreads(const std::vector>& wai // Signal the waiting threads. for (std::size_t i = 0; i < last; i++) { - if (waiting_threads[i]->GetStatus() != ThreadStatus::WaitArb) { - last++; - last = std::min(waiting_threads.size(), last); - continue; - } - - time_manager.CancelTimeEvent(waiting_threads[i].get()); - - ASSERT(waiting_threads[i]->GetStatus() == ThreadStatus::WaitArb); waiting_threads[i]->SetSynchronizationResults(nullptr, RESULT_SUCCESS); RemoveThread(waiting_threads[i]); waiting_threads[i]->WaitForArbitration(false); - waiting_threads[i]->SetArbiterWaitAddress(0); waiting_threads[i]->ResumeFromWait(); } } @@ -172,20 +162,25 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6 { SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout); + if (current_thread->IsPendingTermination()) { + lock.CancelSleep(); + return ERR_THREAD_TERMINATING; + } + // Ensure that we can read the address. if (!memory.IsValidVirtualAddress(address)) { lock.CancelSleep(); return ERR_INVALID_ADDRESS_STATE; } - /// TODO(Blinkhawk): Check termination pending. - s32 current_value = static_cast(memory.Read32(address)); if (current_value >= value) { lock.CancelSleep(); return ERR_INVALID_STATE; } + current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); + s32 decrement_value; const std::size_t current_core = system.CurrentCoreIndex(); @@ -207,7 +202,6 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6 return RESULT_TIMEOUT; } - current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); current_thread->SetArbiterWaitAddress(address); InsertThread(SharedFrom(current_thread)); current_thread->SetStatus(ThreadStatus::WaitArb); @@ -239,14 +233,17 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t { SchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout); + if (current_thread->IsPendingTermination()) { + lock.CancelSleep(); + return ERR_THREAD_TERMINATING; + } + // Ensure that we can read the address. if (!memory.IsValidVirtualAddress(address)) { lock.CancelSleep(); return ERR_INVALID_ADDRESS_STATE; } - /// TODO(Blinkhawk): Check termination pending. - s32 current_value = static_cast(memory.Read32(address)); if (current_value != value) { lock.CancelSleep(); diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index ba051a7d80..721ab1e708 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -49,6 +49,7 @@ namespace Kernel { * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time */ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_late) { + UNREACHABLE(); const auto proper_handle = static_cast(thread_handle); const auto& system = Core::System::GetInstance(); diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index ab17204bb4..5322f0aae3 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -133,6 +133,7 @@ u32 GlobalScheduler::SelectThreads() { u32 cores_needing_context_switch{}; for (u32 core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { Scheduler& sched = kernel.Scheduler(core); + ASSERT(top_threads[core] == nullptr || top_threads[core]->GetProcessorID() == core); if (update_thread(top_threads[core], sched)) { cores_needing_context_switch |= (1ul << core); } @@ -244,7 +245,7 @@ bool GlobalScheduler::YieldThreadAndWaitForLoadBalancing(Thread* yielding_thread winner = yielding_thread; } } else { - winner = scheduled_queue[i].front(); + winner = scheduled_queue[core_id].front(); } if (kernel.GetCurrentHostThreadID() != core_id) { diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 728cca8020..5e062bf595 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -16,7 +16,7 @@ #include "core/hle/kernel/thread.h" namespace Common { - class Fiber; +class Fiber; } namespace Core { @@ -133,7 +133,8 @@ private: /// and reschedules current core if needed. void Unlock(); - void EnableInterruptAndSchedule(u32 cores_pending_reschedule, Core::EmuThreadHandle global_thread); + void EnableInterruptAndSchedule(u32 cores_pending_reschedule, + Core::EmuThreadHandle global_thread); /** * Add a thread to the suggested queue of a cpu core. Suggested threads may be diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 371beed0d7..aad2ac5493 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1562,6 +1562,11 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT); + if (thread->IsPendingTermination()) { + lock.CancelSleep(); + return ERR_THREAD_TERMINATING; + } + const auto release_result = current_process->GetMutex().Release(mutex_addr); if (release_result.IsError()) { lock.CancelSleep(); @@ -1588,6 +1593,11 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add { SchedulerLock lock(kernel); + auto* owner = current_thread->GetLockOwner(); + if (owner != nullptr) { + owner->RemoveMutexWaiter(SharedFrom(current_thread)); + } + current_process->RemoveConditionVariableThread(SharedFrom(current_thread)); } // Note: Deliberately don't attempt to inherit the lock owner's priority. @@ -1618,19 +1628,10 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ for (std::size_t index = 0; index < last; ++index) { auto& thread = waiting_threads[index]; - if (thread->GetStatus() != ThreadStatus::WaitCondVar) { - last++; - last = std::min(waiting_threads.size(), last); - continue; - } - - time_manager.CancelTimeEvent(thread.get()); - ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr); // liberate Cond Var Thread. current_process->RemoveConditionVariableThread(thread); - thread->SetCondVarWaitAddress(0); const std::size_t current_core = system.CurrentCoreIndex(); auto& monitor = system.Monitor(); @@ -1655,9 +1656,6 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ monitor.ClearExclusive(); if (mutex_val == 0) { // We were able to acquire the mutex, resume this thread. - ASSERT(thread->GetStatus() == ThreadStatus::WaitCondVar); - thread->ResumeFromWait(); - auto* const lock_owner = thread->GetLockOwner(); if (lock_owner != nullptr) { lock_owner->RemoveMutexWaiter(thread); @@ -1665,13 +1663,16 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_ thread->SetLockOwner(nullptr); thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS); + thread->ResumeFromWait(); } else { // The mutex is already owned by some other thread, make this thread wait on it. const Handle owner_handle = static_cast(mutex_val & Mutex::MutexOwnerMask); const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); auto owner = handle_table.Get(owner_handle); ASSERT(owner); - thread->SetStatus(ThreadStatus::WaitMutex); + if (thread->GetStatus() == ThreadStatus::WaitCondVar) { + thread->SetStatus(ThreadStatus::WaitMutex); + } owner->AddMutexWaiter(thread); } diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index 4323fc1208..275bf11cc0 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp @@ -23,9 +23,10 @@ void Synchronization::SignalObject(SynchronizationObject& obj) const { if (obj.IsSignaled()) { for (auto thread : obj.GetWaitingThreads()) { if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) { + ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch); + ASSERT(thread->IsWaitingSync()); thread->SetSynchronizationResults(&obj, RESULT_SUCCESS); thread->ResumeFromWait(); - time_manager.CancelTimeEvent(thread.get()); } } obj.ClearWaitingThreads(); @@ -91,10 +92,11 @@ std::pair Synchronization::WaitFor( ResultCode signaling_result = thread->GetSignalingResult(); SynchronizationObject* signaling_object = thread->GetSignalingObject(); thread->SetSynchronizationObjects(nullptr); + auto shared_thread = SharedFrom(thread); for (auto& obj : sync_objects) { - obj->RemoveWaitingThread(SharedFrom(thread)); + obj->RemoveWaitingThread(shared_thread); } - if (signaling_result == RESULT_SUCCESS) { + if (signaling_object != nullptr) { const auto itr = std::find_if( sync_objects.begin(), sync_objects.end(), [signaling_object](const std::shared_ptr& object) { @@ -103,7 +105,7 @@ std::pair Synchronization::WaitFor( ASSERT(itr != sync_objects.end()); signaling_object->Acquire(thread); const u32 index = static_cast(std::distance(sync_objects.begin(), itr)); - return {RESULT_SUCCESS, index}; + return {signaling_result, index}; } return {signaling_result, -1}; } diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index dab5fc4c6f..cc228f5f70 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp @@ -22,7 +22,6 @@ TimeManager::TimeManager(Core::System& system_) : system{system_} { if (cancelled_events[proper_handle]) { return; } - event_fired[proper_handle] = true; std::shared_ptr thread = this->system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); thread->OnWakeUp(); @@ -39,7 +38,6 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 event_handle = InvalidHandle; } cancelled_events[event_handle] = false; - event_fired[event_handle] = false; } void TimeManager::UnscheduleTimeEvent(Handle event_handle) { diff --git a/src/core/hle/kernel/time_manager.h b/src/core/hle/kernel/time_manager.h index 3080ac8383..307a187658 100644 --- a/src/core/hle/kernel/time_manager.h +++ b/src/core/hle/kernel/time_manager.h @@ -42,7 +42,6 @@ private: Core::System& system; std::shared_ptr time_manager_event_type; std::unordered_map cancelled_events; - std::unordered_map event_fired; }; } // namespace Kernel -- cgit v1.2.3 From d2aa227e0d2f14fdc74e6d869f48261ffc06bc9c Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 9 Mar 2020 10:51:05 -0400 Subject: Synchronization: Correct wide Assertion. --- src/core/hle/kernel/synchronization.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/synchronization.cpp') diff --git a/src/core/hle/kernel/synchronization.cpp b/src/core/hle/kernel/synchronization.cpp index 275bf11cc0..851b702a55 100644 --- a/src/core/hle/kernel/synchronization.cpp +++ b/src/core/hle/kernel/synchronization.cpp @@ -23,8 +23,10 @@ void Synchronization::SignalObject(SynchronizationObject& obj) const { if (obj.IsSignaled()) { for (auto thread : obj.GetWaitingThreads()) { if (thread->GetSchedulingStatus() == ThreadSchedStatus::Paused) { - ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch); - ASSERT(thread->IsWaitingSync()); + if (thread->GetStatus() != ThreadStatus::WaitHLEEvent) { + ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch); + ASSERT(thread->IsWaitingSync()); + } thread->SetSynchronizationResults(&obj, RESULT_SUCCESS); thread->ResumeFromWait(); } -- cgit v1.2.3