timing: wait for completion on unregister
This commit is contained in:
		| @@ -142,9 +142,11 @@ void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, | |||||||
| } | } | ||||||
|  |  | ||||||
| void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, | void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, | ||||||
|                                  std::uintptr_t user_data) { |                                  std::uintptr_t user_data, bool wait) { | ||||||
|     std::scoped_lock scope{basic_lock}; |     { | ||||||
|     const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { |         std::scoped_lock lk{basic_lock}; | ||||||
|  |         const auto itr = | ||||||
|  |             std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { | ||||||
|                 return e.type.lock().get() == event_type.get() && e.user_data == user_data; |                 return e.type.lock().get() == event_type.get() && e.user_data == user_data; | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
| @@ -155,6 +157,12 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Force any in-progress events to finish | ||||||
|  |     if (wait) { | ||||||
|  |         std::scoped_lock lk{advance_lock}; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| void CoreTiming::AddTicks(u64 ticks_to_add) { | void CoreTiming::AddTicks(u64 ticks_to_add) { | ||||||
|     ticks += ticks_to_add; |     ticks += ticks_to_add; | ||||||
|     downcount -= static_cast<s64>(ticks); |     downcount -= static_cast<s64>(ticks); | ||||||
| @@ -190,20 +198,6 @@ u64 CoreTiming::GetClockTicks() const { | |||||||
|     return CpuCyclesToClockCycles(ticks); |     return CpuCyclesToClockCycles(ticks); | ||||||
| } | } | ||||||
|  |  | ||||||
| void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) { |  | ||||||
|     std::scoped_lock lock{basic_lock}; |  | ||||||
|  |  | ||||||
|     const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { |  | ||||||
|         return e.type.lock().get() == event_type.get(); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // Removing random items breaks the invariant so we have to re-establish it. |  | ||||||
|     if (itr != event_queue.end()) { |  | ||||||
|         event_queue.erase(itr, event_queue.end()); |  | ||||||
|         std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| std::optional<s64> CoreTiming::Advance() { | std::optional<s64> CoreTiming::Advance() { | ||||||
|     std::scoped_lock lock{advance_lock, basic_lock}; |     std::scoped_lock lock{advance_lock, basic_lock}; | ||||||
|     global_timer = GetGlobalTimeNs().count(); |     global_timer = GetGlobalTimeNs().count(); | ||||||
|   | |||||||
| @@ -98,10 +98,13 @@ public: | |||||||
|                               const std::shared_ptr<EventType>& event_type, |                               const std::shared_ptr<EventType>& event_type, | ||||||
|                               std::uintptr_t user_data = 0, bool absolute_time = false); |                               std::uintptr_t user_data = 0, bool absolute_time = false); | ||||||
|  |  | ||||||
|     void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data); |     void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data, | ||||||
|  |                          bool wait = true); | ||||||
|  |  | ||||||
|     /// We only permit one event of each type in the queue at a time. |     void UnscheduleEventWithoutWait(const std::shared_ptr<EventType>& event_type, | ||||||
|     void RemoveEvent(const std::shared_ptr<EventType>& event_type); |                                     std::uintptr_t user_data) { | ||||||
|  |         UnscheduleEvent(event_type, user_data, false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     void AddTicks(u64 ticks_to_add); |     void AddTicks(u64 ticks_to_add); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,8 @@ void KHardwareTimer::Initialize() { | |||||||
| } | } | ||||||
|  |  | ||||||
| void KHardwareTimer::Finalize() { | void KHardwareTimer::Finalize() { | ||||||
|     this->DisableInterrupt(); |     m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this)); | ||||||
|  |     m_wakeup_time = std::numeric_limits<s64>::max(); | ||||||
|     m_event_type.reset(); |     m_event_type.reset(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -59,7 +60,8 @@ void KHardwareTimer::EnableInterrupt(s64 wakeup_time) { | |||||||
| } | } | ||||||
|  |  | ||||||
| void KHardwareTimer::DisableInterrupt() { | void KHardwareTimer::DisableInterrupt() { | ||||||
|     m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this)); |     m_kernel.System().CoreTiming().UnscheduleEventWithoutWait(m_event_type, | ||||||
|  |                                                               reinterpret_cast<uintptr_t>(this)); | ||||||
|     m_wakeup_time = std::numeric_limits<s64>::max(); |     m_wakeup_time = std::numeric_limits<s64>::max(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user