summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/core_timing.cpp55
-rw-r--r--src/core/core_timing.h6
-rw-r--r--src/core/hardware_properties.h8
3 files changed, 41 insertions, 28 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 3a63b52e3..742cfb996 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -6,6 +6,10 @@
6#include <string> 6#include <string>
7#include <tuple> 7#include <tuple>
8 8
9#ifdef _WIN32
10#include "common/windows/timer_resolution.h"
11#endif
12
9#include "common/microprofile.h" 13#include "common/microprofile.h"
10#include "core/core_timing.h" 14#include "core/core_timing.h"
11#include "core/core_timing_util.h" 15#include "core/core_timing_util.h"
@@ -38,7 +42,8 @@ struct CoreTiming::Event {
38}; 42};
39 43
40CoreTiming::CoreTiming() 44CoreTiming::CoreTiming()
41 : clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {} 45 : cpu_clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)},
46 event_clock{Common::CreateStandardWallClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {}
42 47
43CoreTiming::~CoreTiming() { 48CoreTiming::~CoreTiming() {
44 Reset(); 49 Reset();
@@ -185,15 +190,15 @@ void CoreTiming::ResetTicks() {
185} 190}
186 191
187u64 CoreTiming::GetCPUTicks() const { 192u64 CoreTiming::GetCPUTicks() const {
188 if (is_multicore) { 193 if (is_multicore) [[likely]] {
189 return clock->GetCPUCycles(); 194 return cpu_clock->GetCPUCycles();
190 } 195 }
191 return ticks; 196 return ticks;
192} 197}
193 198
194u64 CoreTiming::GetClockTicks() const { 199u64 CoreTiming::GetClockTicks() const {
195 if (is_multicore) { 200 if (is_multicore) [[likely]] {
196 return clock->GetClockCycles(); 201 return cpu_clock->GetClockCycles();
197 } 202 }
198 return CpuCyclesToClockCycles(ticks); 203 return CpuCyclesToClockCycles(ticks);
199} 204}
@@ -252,21 +257,20 @@ void CoreTiming::ThreadLoop() {
252 const auto next_time = Advance(); 257 const auto next_time = Advance();
253 if (next_time) { 258 if (next_time) {
254 // There are more events left in the queue, wait until the next event. 259 // There are more events left in the queue, wait until the next event.
255 const auto wait_time = *next_time - GetGlobalTimeNs().count(); 260 auto wait_time = *next_time - GetGlobalTimeNs().count();
256 if (wait_time > 0) { 261 if (wait_time > 0) {
257#ifdef _WIN32 262#ifdef _WIN32
258 // Assume a timer resolution of 1ms. 263 const auto timer_resolution_ns =
259 static constexpr s64 TimerResolutionNS = 1000000; 264 Common::Windows::GetCurrentTimerResolution().count();
260 265
261 // Sleep in discrete intervals of the timer resolution, and spin the rest. 266 while (!paused && !event.IsSet() && wait_time > 0) {
262 const auto sleep_time = wait_time - (wait_time % TimerResolutionNS); 267 wait_time = *next_time - GetGlobalTimeNs().count();
263 if (sleep_time > 0) {
264 event.WaitFor(std::chrono::nanoseconds(sleep_time));
265 }
266 268
267 while (!paused && !event.IsSet() && GetGlobalTimeNs().count() < *next_time) { 269 if (wait_time >= timer_resolution_ns) {
268 // Yield to reduce thread starvation. 270 Common::Windows::SleepForOneTick();
269 std::this_thread::yield(); 271 } else {
272 std::this_thread::yield();
273 }
270 } 274 }
271 275
272 if (event.IsSet()) { 276 if (event.IsSet()) {
@@ -285,9 +289,9 @@ void CoreTiming::ThreadLoop() {
285 } 289 }
286 290
287 paused_set = true; 291 paused_set = true;
288 clock->Pause(true); 292 event_clock->Pause(true);
289 pause_event.Wait(); 293 pause_event.Wait();
290 clock->Pause(false); 294 event_clock->Pause(false);
291 } 295 }
292} 296}
293 297
@@ -303,16 +307,23 @@ void CoreTiming::Reset() {
303 has_started = false; 307 has_started = false;
304} 308}
305 309
310std::chrono::nanoseconds CoreTiming::GetCPUTimeNs() const {
311 if (is_multicore) [[likely]] {
312 return cpu_clock->GetTimeNS();
313 }
314 return CyclesToNs(ticks);
315}
316
306std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const { 317std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
307 if (is_multicore) { 318 if (is_multicore) [[likely]] {
308 return clock->GetTimeNS(); 319 return event_clock->GetTimeNS();
309 } 320 }
310 return CyclesToNs(ticks); 321 return CyclesToNs(ticks);
311} 322}
312 323
313std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const { 324std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
314 if (is_multicore) { 325 if (is_multicore) [[likely]] {
315 return clock->GetTimeUS(); 326 return event_clock->GetTimeUS();
316 } 327 }
317 return CyclesToUs(ticks); 328 return CyclesToUs(ticks);
318} 329}
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index da366637b..4b89c0c39 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -122,6 +122,9 @@ public:
122 /// Returns current time in emulated in Clock cycles 122 /// Returns current time in emulated in Clock cycles
123 u64 GetClockTicks() const; 123 u64 GetClockTicks() const;
124 124
125 /// Returns current time in nanoseconds.
126 std::chrono::nanoseconds GetCPUTimeNs() const;
127
125 /// Returns current time in microseconds. 128 /// Returns current time in microseconds.
126 std::chrono::microseconds GetGlobalTimeUs() const; 129 std::chrono::microseconds GetGlobalTimeUs() const;
127 130
@@ -139,7 +142,8 @@ private:
139 142
140 void Reset(); 143 void Reset();
141 144
142 std::unique_ptr<Common::WallClock> clock; 145 std::unique_ptr<Common::WallClock> cpu_clock;
146 std::unique_ptr<Common::WallClock> event_clock;
143 147
144 s64 global_timer = 0; 148 s64 global_timer = 0;
145 149
diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h
index 45567b840..191c28bb4 100644
--- a/src/core/hardware_properties.h
+++ b/src/core/hardware_properties.h
@@ -13,11 +13,9 @@ namespace Core {
13 13
14namespace Hardware { 14namespace Hardware {
15 15
16// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz 16constexpr u64 BASE_CLOCK_RATE = 1'020'000'000; // Default CPU Frequency = 1020 MHz
17// The exact value used is of course unverified. 17constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz
18constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch cpu frequency is 1020MHz un/docked 18constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
19constexpr u64 CNTFREQ = 19200000; // Switch's hardware clock speed
20constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
21 19
22// Virtual to Physical core map. 20// Virtual to Physical core map.
23constexpr std::array<s32, Common::BitSize<u64>()> VirtualToPhysicalCoreMap{ 21constexpr std::array<s32, Common::BitSize<u64>()> VirtualToPhysicalCoreMap{