diff options
| -rw-r--r-- | src/core/core_timing.cpp | 42 | ||||
| -rw-r--r-- | src/core/core_timing.h | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_hardware_timer.cpp | 6 |
3 files changed, 28 insertions, 29 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 0e7b5f943..6bac6722f 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -142,16 +142,24 @@ void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, | |||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, | 144 | void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, |
| 145 | std::uintptr_t user_data) { | 145 | std::uintptr_t user_data, bool wait) { |
| 146 | std::scoped_lock scope{basic_lock}; | 146 | { |
| 147 | const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { | 147 | std::scoped_lock lk{basic_lock}; |
| 148 | return e.type.lock().get() == event_type.get() && e.user_data == user_data; | 148 | const auto itr = |
| 149 | }); | 149 | std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { |
| 150 | 150 | return e.type.lock().get() == event_type.get() && e.user_data == user_data; | |
| 151 | // Removing random items breaks the invariant so we have to re-establish it. | 151 | }); |
| 152 | if (itr != event_queue.end()) { | 152 | |
| 153 | event_queue.erase(itr, event_queue.end()); | 153 | // Removing random items breaks the invariant so we have to re-establish it. |
| 154 | std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | 154 | if (itr != event_queue.end()) { |
| 155 | event_queue.erase(itr, event_queue.end()); | ||
| 156 | std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | // Force any in-progress events to finish | ||
| 161 | if (wait) { | ||
| 162 | std::scoped_lock lk{advance_lock}; | ||
| 155 | } | 163 | } |
| 156 | } | 164 | } |
| 157 | 165 | ||
| @@ -190,20 +198,6 @@ u64 CoreTiming::GetClockTicks() const { | |||
| 190 | return CpuCyclesToClockCycles(ticks); | 198 | return CpuCyclesToClockCycles(ticks); |
| 191 | } | 199 | } |
| 192 | 200 | ||
| 193 | void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) { | ||
| 194 | std::scoped_lock lock{basic_lock}; | ||
| 195 | |||
| 196 | const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { | ||
| 197 | return e.type.lock().get() == event_type.get(); | ||
| 198 | }); | ||
| 199 | |||
| 200 | // Removing random items breaks the invariant so we have to re-establish it. | ||
| 201 | if (itr != event_queue.end()) { | ||
| 202 | event_queue.erase(itr, event_queue.end()); | ||
| 203 | std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | std::optional<s64> CoreTiming::Advance() { | 201 | std::optional<s64> CoreTiming::Advance() { |
| 208 | std::scoped_lock lock{advance_lock, basic_lock}; | 202 | std::scoped_lock lock{advance_lock, basic_lock}; |
| 209 | global_timer = GetGlobalTimeNs().count(); | 203 | global_timer = GetGlobalTimeNs().count(); |
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index b5925193c..da366637b 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -98,10 +98,13 @@ public: | |||
| 98 | const std::shared_ptr<EventType>& event_type, | 98 | const std::shared_ptr<EventType>& event_type, |
| 99 | std::uintptr_t user_data = 0, bool absolute_time = false); | 99 | std::uintptr_t user_data = 0, bool absolute_time = false); |
| 100 | 100 | ||
| 101 | void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data); | 101 | void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data, |
| 102 | bool wait = true); | ||
| 102 | 103 | ||
| 103 | /// We only permit one event of each type in the queue at a time. | 104 | void UnscheduleEventWithoutWait(const std::shared_ptr<EventType>& event_type, |
| 104 | void RemoveEvent(const std::shared_ptr<EventType>& event_type); | 105 | std::uintptr_t user_data) { |
| 106 | UnscheduleEvent(event_type, user_data, false); | ||
| 107 | } | ||
| 105 | 108 | ||
| 106 | void AddTicks(u64 ticks_to_add); | 109 | void AddTicks(u64 ticks_to_add); |
| 107 | 110 | ||
diff --git a/src/core/hle/kernel/k_hardware_timer.cpp b/src/core/hle/kernel/k_hardware_timer.cpp index 6bba79ea0..4dcd53821 100644 --- a/src/core/hle/kernel/k_hardware_timer.cpp +++ b/src/core/hle/kernel/k_hardware_timer.cpp | |||
| @@ -18,7 +18,8 @@ void KHardwareTimer::Initialize() { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | void KHardwareTimer::Finalize() { | 20 | void KHardwareTimer::Finalize() { |
| 21 | this->DisableInterrupt(); | 21 | m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this)); |
| 22 | m_wakeup_time = std::numeric_limits<s64>::max(); | ||
| 22 | m_event_type.reset(); | 23 | m_event_type.reset(); |
| 23 | } | 24 | } |
| 24 | 25 | ||
| @@ -59,7 +60,8 @@ void KHardwareTimer::EnableInterrupt(s64 wakeup_time) { | |||
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | void KHardwareTimer::DisableInterrupt() { | 62 | void KHardwareTimer::DisableInterrupt() { |
| 62 | m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this)); | 63 | m_kernel.System().CoreTiming().UnscheduleEventWithoutWait(m_event_type, |
| 64 | reinterpret_cast<uintptr_t>(this)); | ||
| 63 | m_wakeup_time = std::numeric_limits<s64>::max(); | 65 | m_wakeup_time = std::numeric_limits<s64>::max(); |
| 64 | } | 66 | } |
| 65 | 67 | ||