diff options
| author | 2023-04-23 00:01:08 -0400 | |
|---|---|---|
| committer | 2023-06-07 21:44:42 -0400 | |
| commit | 8e56a84566036cfff0aa5c3d80ae1b051d2bd0bf (patch) | |
| tree | 2bb7be86aafe9986811758b508a7581d2efe8ac4 /src/core | |
| parent | nvnflinger: Acquire lock prior to signaling the vsync variable (diff) | |
| download | yuzu-8e56a84566036cfff0aa5c3d80ae1b051d2bd0bf.tar.gz yuzu-8e56a84566036cfff0aa5c3d80ae1b051d2bd0bf.tar.xz yuzu-8e56a84566036cfff0aa5c3d80ae1b051d2bd0bf.zip | |
core_timing: Use CNTPCT as the guest CPU tick
Previously, we were mixing the raw CPU frequency and CNTFRQ.
The raw CPU frequency (1020 MHz) should've never been used as CNTPCT (whose frequency is CNTFRQ) is the only counter available.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/core/core_timing.cpp | 35 | ||||
| -rw-r--r-- | src/core/core_timing.h | 11 | ||||
| -rw-r--r-- | src/core/core_timing_util.h | 58 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_scheduler.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc/svc_info.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hidbus.cpp | 1 |
7 files changed, 15 insertions, 100 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 99602699a..3df4094a7 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -16,7 +16,6 @@ add_library(core STATIC | |||
| 16 | core.h | 16 | core.h |
| 17 | core_timing.cpp | 17 | core_timing.cpp |
| 18 | core_timing.h | 18 | core_timing.h |
| 19 | core_timing_util.h | ||
| 20 | cpu_manager.cpp | 19 | cpu_manager.cpp |
| 21 | cpu_manager.h | 20 | cpu_manager.h |
| 22 | crypto/aes_util.cpp | 21 | crypto/aes_util.cpp |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 4f2692b05..9a1d5a69a 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | 16 | ||
| 17 | #include "common/microprofile.h" | 17 | #include "common/microprofile.h" |
| 18 | #include "core/core_timing.h" | 18 | #include "core/core_timing.h" |
| 19 | #include "core/core_timing_util.h" | ||
| 20 | #include "core/hardware_properties.h" | 19 | #include "core/hardware_properties.h" |
| 21 | 20 | ||
| 22 | namespace Core::Timing { | 21 | namespace Core::Timing { |
| @@ -45,9 +44,7 @@ struct CoreTiming::Event { | |||
| 45 | } | 44 | } |
| 46 | }; | 45 | }; |
| 47 | 46 | ||
| 48 | CoreTiming::CoreTiming() | 47 | CoreTiming::CoreTiming() : clock{Common::CreateOptimalClock()} {} |
| 49 | : cpu_clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)}, | ||
| 50 | event_clock{Common::CreateStandardWallClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {} | ||
| 51 | 48 | ||
| 52 | CoreTiming::~CoreTiming() { | 49 | CoreTiming::~CoreTiming() { |
| 53 | Reset(); | 50 | Reset(); |
| @@ -180,7 +177,7 @@ void CoreTiming::AddTicks(u64 ticks_to_add) { | |||
| 180 | void CoreTiming::Idle() { | 177 | void CoreTiming::Idle() { |
| 181 | if (!event_queue.empty()) { | 178 | if (!event_queue.empty()) { |
| 182 | const u64 next_event_time = event_queue.front().time; | 179 | const u64 next_event_time = event_queue.front().time; |
| 183 | const u64 next_ticks = nsToCycles(std::chrono::nanoseconds(next_event_time)) + 10U; | 180 | const u64 next_ticks = Common::WallClock::NSToCNTPCT(next_event_time) + 10U; |
| 184 | if (next_ticks > ticks) { | 181 | if (next_ticks > ticks) { |
| 185 | ticks = next_ticks; | 182 | ticks = next_ticks; |
| 186 | } | 183 | } |
| @@ -193,18 +190,11 @@ void CoreTiming::ResetTicks() { | |||
| 193 | downcount = MAX_SLICE_LENGTH; | 190 | downcount = MAX_SLICE_LENGTH; |
| 194 | } | 191 | } |
| 195 | 192 | ||
| 196 | u64 CoreTiming::GetCPUTicks() const { | ||
| 197 | if (is_multicore) [[likely]] { | ||
| 198 | return cpu_clock->GetCPUCycles(); | ||
| 199 | } | ||
| 200 | return ticks; | ||
| 201 | } | ||
| 202 | |||
| 203 | u64 CoreTiming::GetClockTicks() const { | 193 | u64 CoreTiming::GetClockTicks() const { |
| 204 | if (is_multicore) [[likely]] { | 194 | if (is_multicore) [[likely]] { |
| 205 | return cpu_clock->GetClockCycles(); | 195 | return clock->GetCNTPCT(); |
| 206 | } | 196 | } |
| 207 | return CpuCyclesToClockCycles(ticks); | 197 | return ticks; |
| 208 | } | 198 | } |
| 209 | 199 | ||
| 210 | std::optional<s64> CoreTiming::Advance() { | 200 | std::optional<s64> CoreTiming::Advance() { |
| @@ -297,9 +287,7 @@ void CoreTiming::ThreadLoop() { | |||
| 297 | } | 287 | } |
| 298 | 288 | ||
| 299 | paused_set = true; | 289 | paused_set = true; |
| 300 | event_clock->Pause(true); | ||
| 301 | pause_event.Wait(); | 290 | pause_event.Wait(); |
| 302 | event_clock->Pause(false); | ||
| 303 | } | 291 | } |
| 304 | } | 292 | } |
| 305 | 293 | ||
| @@ -315,25 +303,18 @@ void CoreTiming::Reset() { | |||
| 315 | has_started = false; | 303 | has_started = false; |
| 316 | } | 304 | } |
| 317 | 305 | ||
| 318 | std::chrono::nanoseconds CoreTiming::GetCPUTimeNs() const { | ||
| 319 | if (is_multicore) [[likely]] { | ||
| 320 | return cpu_clock->GetTimeNS(); | ||
| 321 | } | ||
| 322 | return CyclesToNs(ticks); | ||
| 323 | } | ||
| 324 | |||
| 325 | std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const { | 306 | std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const { |
| 326 | if (is_multicore) [[likely]] { | 307 | if (is_multicore) [[likely]] { |
| 327 | return event_clock->GetTimeNS(); | 308 | return clock->GetTimeNS(); |
| 328 | } | 309 | } |
| 329 | return CyclesToNs(ticks); | 310 | return std::chrono::nanoseconds{Common::WallClock::CNTPCTToNS(ticks)}; |
| 330 | } | 311 | } |
| 331 | 312 | ||
| 332 | std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const { | 313 | std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const { |
| 333 | if (is_multicore) [[likely]] { | 314 | if (is_multicore) [[likely]] { |
| 334 | return event_clock->GetTimeUS(); | 315 | return clock->GetTimeUS(); |
| 335 | } | 316 | } |
| 336 | return CyclesToUs(ticks); | 317 | return std::chrono::microseconds{Common::WallClock::CNTPCTToUS(ticks)}; |
| 337 | } | 318 | } |
| 338 | 319 | ||
| 339 | } // namespace Core::Timing | 320 | } // namespace Core::Timing |
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index e7c4a949f..fdacdd94a 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -116,15 +116,9 @@ public: | |||
| 116 | return downcount; | 116 | return downcount; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | /// Returns current time in emulated CPU cycles | 119 | /// Returns the current CNTPCT tick value. |
| 120 | u64 GetCPUTicks() const; | ||
| 121 | |||
| 122 | /// Returns current time in emulated in Clock cycles | ||
| 123 | u64 GetClockTicks() const; | 120 | u64 GetClockTicks() const; |
| 124 | 121 | ||
| 125 | /// Returns current time in nanoseconds. | ||
| 126 | std::chrono::nanoseconds GetCPUTimeNs() const; | ||
| 127 | |||
| 128 | /// Returns current time in microseconds. | 122 | /// Returns current time in microseconds. |
| 129 | std::chrono::microseconds GetGlobalTimeUs() const; | 123 | std::chrono::microseconds GetGlobalTimeUs() const; |
| 130 | 124 | ||
| @@ -142,8 +136,7 @@ private: | |||
| 142 | 136 | ||
| 143 | void Reset(); | 137 | void Reset(); |
| 144 | 138 | ||
| 145 | std::unique_ptr<Common::WallClock> cpu_clock; | 139 | std::unique_ptr<Common::WallClock> clock; |
| 146 | std::unique_ptr<Common::WallClock> event_clock; | ||
| 147 | 140 | ||
| 148 | s64 global_timer = 0; | 141 | s64 global_timer = 0; |
| 149 | 142 | ||
diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h deleted file mode 100644 index fe5aaefc7..000000000 --- a/src/core/core_timing_util.h +++ /dev/null | |||
| @@ -1,58 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <chrono> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hardware_properties.h" | ||
| 10 | |||
| 11 | namespace Core::Timing { | ||
| 12 | |||
| 13 | namespace detail { | ||
| 14 | constexpr u64 CNTFREQ_ADJUSTED = Hardware::CNTFREQ / 1000; | ||
| 15 | constexpr u64 BASE_CLOCK_RATE_ADJUSTED = Hardware::BASE_CLOCK_RATE / 1000; | ||
| 16 | } // namespace detail | ||
| 17 | |||
| 18 | [[nodiscard]] constexpr s64 msToCycles(std::chrono::milliseconds ms) { | ||
| 19 | return ms.count() * detail::BASE_CLOCK_RATE_ADJUSTED; | ||
| 20 | } | ||
| 21 | |||
| 22 | [[nodiscard]] constexpr s64 usToCycles(std::chrono::microseconds us) { | ||
| 23 | return us.count() * detail::BASE_CLOCK_RATE_ADJUSTED / 1000; | ||
| 24 | } | ||
| 25 | |||
| 26 | [[nodiscard]] constexpr s64 nsToCycles(std::chrono::nanoseconds ns) { | ||
| 27 | return ns.count() * detail::BASE_CLOCK_RATE_ADJUSTED / 1000000; | ||
| 28 | } | ||
| 29 | |||
| 30 | [[nodiscard]] constexpr u64 msToClockCycles(std::chrono::milliseconds ms) { | ||
| 31 | return static_cast<u64>(ms.count()) * detail::CNTFREQ_ADJUSTED; | ||
| 32 | } | ||
| 33 | |||
| 34 | [[nodiscard]] constexpr u64 usToClockCycles(std::chrono::microseconds us) { | ||
| 35 | return us.count() * detail::CNTFREQ_ADJUSTED / 1000; | ||
| 36 | } | ||
| 37 | |||
| 38 | [[nodiscard]] constexpr u64 nsToClockCycles(std::chrono::nanoseconds ns) { | ||
| 39 | return ns.count() * detail::CNTFREQ_ADJUSTED / 1000000; | ||
| 40 | } | ||
| 41 | |||
| 42 | [[nodiscard]] constexpr u64 CpuCyclesToClockCycles(u64 ticks) { | ||
| 43 | return ticks * detail::CNTFREQ_ADJUSTED / detail::BASE_CLOCK_RATE_ADJUSTED; | ||
| 44 | } | ||
| 45 | |||
| 46 | [[nodiscard]] constexpr std::chrono::milliseconds CyclesToMs(s64 cycles) { | ||
| 47 | return std::chrono::milliseconds(cycles / detail::BASE_CLOCK_RATE_ADJUSTED); | ||
| 48 | } | ||
| 49 | |||
| 50 | [[nodiscard]] constexpr std::chrono::nanoseconds CyclesToNs(s64 cycles) { | ||
| 51 | return std::chrono::nanoseconds(cycles * 1000000 / detail::BASE_CLOCK_RATE_ADJUSTED); | ||
| 52 | } | ||
| 53 | |||
| 54 | [[nodiscard]] constexpr std::chrono::microseconds CyclesToUs(s64 cycles) { | ||
| 55 | return std::chrono::microseconds(cycles * 1000 / detail::BASE_CLOCK_RATE_ADJUSTED); | ||
| 56 | } | ||
| 57 | |||
| 58 | } // namespace Core::Timing | ||
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index faa12b4f0..75ce5a23c 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -184,7 +184,8 @@ u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) { | |||
| 184 | prev_highest_thread != highest_thread) [[likely]] { | 184 | prev_highest_thread != highest_thread) [[likely]] { |
| 185 | if (prev_highest_thread != nullptr) [[likely]] { | 185 | if (prev_highest_thread != nullptr) [[likely]] { |
| 186 | IncrementScheduledCount(prev_highest_thread); | 186 | IncrementScheduledCount(prev_highest_thread); |
| 187 | prev_highest_thread->SetLastScheduledTick(m_kernel.System().CoreTiming().GetCPUTicks()); | 187 | prev_highest_thread->SetLastScheduledTick( |
| 188 | m_kernel.System().CoreTiming().GetClockTicks()); | ||
| 188 | } | 189 | } |
| 189 | if (m_state.should_count_idle) { | 190 | if (m_state.should_count_idle) { |
| 190 | if (highest_thread != nullptr) [[likely]] { | 191 | if (highest_thread != nullptr) [[likely]] { |
| @@ -351,7 +352,7 @@ void KScheduler::SwitchThread(KThread* next_thread) { | |||
| 351 | 352 | ||
| 352 | // Update the CPU time tracking variables. | 353 | // Update the CPU time tracking variables. |
| 353 | const s64 prev_tick = m_last_context_switch_time; | 354 | const s64 prev_tick = m_last_context_switch_time; |
| 354 | const s64 cur_tick = m_kernel.System().CoreTiming().GetCPUTicks(); | 355 | const s64 cur_tick = m_kernel.System().CoreTiming().GetClockTicks(); |
| 355 | const s64 tick_diff = cur_tick - prev_tick; | 356 | const s64 tick_diff = cur_tick - prev_tick; |
| 356 | cur_thread->AddCpuTime(m_core_id, tick_diff); | 357 | cur_thread->AddCpuTime(m_core_id, tick_diff); |
| 357 | if (cur_process != nullptr) { | 358 | if (cur_process != nullptr) { |
diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp index 2b2c878b5..445cdd87b 100644 --- a/src/core/hle/kernel/svc/svc_info.cpp +++ b/src/core/hle/kernel/svc/svc_info.cpp | |||
| @@ -199,9 +199,9 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle | |||
| 199 | if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) { | 199 | if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) { |
| 200 | const u64 thread_ticks = current_thread->GetCpuTime(); | 200 | const u64 thread_ticks = current_thread->GetCpuTime(); |
| 201 | 201 | ||
| 202 | out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks); | 202 | out_ticks = thread_ticks + (core_timing.GetClockTicks() - prev_ctx_ticks); |
| 203 | } else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) { | 203 | } else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) { |
| 204 | out_ticks = core_timing.GetCPUTicks() - prev_ctx_ticks; | 204 | out_ticks = core_timing.GetClockTicks() - prev_ctx_ticks; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | *result = out_ticks; | 207 | *result = out_ticks; |
diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp index 5604a6fda..80aac221b 100644 --- a/src/core/hle/service/hid/hidbus.cpp +++ b/src/core/hle/service/hid/hidbus.cpp | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | #include "common/settings.h" | 5 | #include "common/settings.h" |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| 8 | #include "core/core_timing_util.h" | ||
| 9 | #include "core/hid/hid_types.h" | 8 | #include "core/hid/hid_types.h" |
| 10 | #include "core/hle/kernel/k_event.h" | 9 | #include "core/hle/kernel/k_event.h" |
| 11 | #include "core/hle/kernel/k_readable_event.h" | 10 | #include "core/hle/kernel/k_readable_event.h" |