[common] remove ptr indirection on WallClock (#3864)

also devirtualizes manually since compiler doesn't do it with LTO

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3864
Reviewed-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
lizzie 2026-05-15 22:06:38 +02:00 committed by crueter
parent a1f9e68f46
commit 975aa4e2f2
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
14 changed files with 300 additions and 404 deletions

View file

@ -57,15 +57,51 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
Reset();
on_thread_init = std::move(on_thread_init_);
event_fifo_id = 0;
shutting_down = false;
cpu_ticks = 0;
if (is_multicore) {
timer_thread.emplace([](CoreTiming& instance) {
timer_thread = std::jthread([this](std::stop_token stop_token) {
Common::SetCurrentThreadName("HostTiming");
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
instance.on_thread_init();
instance.ThreadLoop();
}, std::ref(*this));
on_thread_init();
has_started = true;
while (!stop_token.stop_requested()) {
while (!paused && !stop_token.stop_requested()) {
paused_set = false;
if (auto const next_time = Advance(); next_time) {
// There are more events left in the queue, wait until the next event.
auto wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time > 0) {
#ifdef _WIN32
while (!paused && !event.IsSet() && wait_time > 0) {
wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time >= timer_resolution_ns) {
Common::Windows::SleepForOneTick();
} else {
#ifdef ARCHITECTURE_x86_64
Common::X64::MicroSleep();
#else
std::this_thread::yield();
#endif
}
}
if (event.IsSet())
event.Reset();
#else
event.WaitFor(std::chrono::nanoseconds(wait_time));
#endif
}
} else {
// Queue is empty, wait until another event is scheduled and signals us to
// continue.
wait_set = true;
event.Wait();
}
wait_set = false;
}
paused_set = true;
pause_event.Wait();
}
});
}
}
@ -90,7 +126,7 @@ void CoreTiming::SyncPause(bool is_paused) {
}
Pause(is_paused);
if (timer_thread) {
if (timer_thread.joinable()) {
if (!is_paused) {
pause_event.Set();
}
@ -190,33 +226,22 @@ void CoreTiming::ResetTicks() {
}
u64 CoreTiming::GetClockTicks() const {
u64 fres;
if (is_multicore) [[likely]] {
fres = clock->GetCNTPCT();
} else {
fres = Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
u64 fres = is_multicore ? clock.GetCNTPCT() : Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
if (auto const overclock = Settings::values.fast_cpu_time.GetValue(); overclock != Settings::CpuClock::Off) {
fres = u64(f64(fres) * (1.7 + 0.3 * u32(overclock)));
}
const auto overclock = Settings::values.fast_cpu_time.GetValue();
if (overclock != Settings::CpuClock::Off) {
fres = (u64) ((double) fres * (1.7 + 0.3 * u32(overclock)));
}
if (Settings::values.sync_core_speed.GetValue()) {
const auto ticks = double(fres);
const auto speed_limit = double(Settings::SpeedLimit())*0.01;
return u64(ticks/speed_limit);
} else {
return fres;
}
if (::Settings::values.sync_core_speed.GetValue()) {
auto const ticks = f64(fres);
auto const speed_limit = f64(Settings::SpeedLimit()) * 0.01;
return u64(ticks / speed_limit);
}
return fres;
}
u64 CoreTiming::GetGPUTicks() const {
if (is_multicore) [[likely]] {
return clock->GetGPUTick();
}
return Common::WallClock::CPUTickToGPUTick(cpu_ticks);
return is_multicore
? clock.GetGPUTick()
: Common::WallClock::CPUTickToGPUTick(cpu_ticks);
}
std::optional<s64> CoreTiming::Advance() {
@ -278,75 +303,29 @@ std::optional<s64> CoreTiming::Advance() {
}
}
void CoreTiming::ThreadLoop() {
has_started = true;
while (!shutting_down) {
while (!paused) {
paused_set = false;
const auto next_time = Advance();
if (next_time) {
// There are more events left in the queue, wait until the next event.
auto wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time > 0) {
#ifdef _WIN32
while (!paused && !event.IsSet() && wait_time > 0) {
wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time >= timer_resolution_ns) {
Common::Windows::SleepForOneTick();
} else {
#ifdef ARCHITECTURE_x86_64
Common::X64::MicroSleep();
#else
std::this_thread::yield();
#endif
}
}
if (event.IsSet()) {
event.Reset();
}
#else
event.WaitFor(std::chrono::nanoseconds(wait_time));
#endif
}
} else {
// Queue is empty, wait until another event is scheduled and signals us to
// continue.
wait_set = true;
event.Wait();
}
wait_set = false;
}
paused_set = true;
pause_event.Wait();
}
}
void CoreTiming::Reset() {
paused = true;
shutting_down = true;
pause_event.Set();
event.Set();
if (timer_thread) {
timer_thread->join();
if (timer_thread.joinable()) {
timer_thread.request_stop();
timer_thread.join();
}
timer_thread.reset();
has_started = false;
}
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
if (is_multicore) [[likely]] {
return clock->GetTimeNS();
}
return std::chrono::nanoseconds{Common::WallClock::CPUTickToNS(cpu_ticks)};
/// @brief Returns current time in nanoseconds.
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const noexcept {
return is_multicore
? clock.GetTimeNS()
: std::chrono::nanoseconds{Common::WallClock::CPUTickToNS(cpu_ticks)};
}
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
if (is_multicore) [[likely]] {
return clock->GetTimeUS();
}
return std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
/// @brief Returns current time in microseconds.
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const noexcept {
return is_multicore
? clock.GetTimeUS()
: std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
}
#ifdef _WIN32