// Copyright 2008 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "Common/Timer.h" #include #ifdef _WIN32 #include #include #else #include #endif #include "Common/CommonTypes.h" namespace Common { template static typename Clock::rep time_now() { return std::chrono::time_point_cast(Clock::now()).time_since_epoch().count(); } template static auto steady_time_now() { return time_now(); } u64 Timer::NowUs() { return steady_time_now(); } u64 Timer::NowMs() { return steady_time_now(); } void Timer::Start() { m_start_ms = NowMs(); m_end_ms = 0; m_running = true; } void Timer::StartWithOffset(u64 offset) { Start(); if (m_start_ms > offset) m_start_ms -= offset; } void Timer::Stop() { m_end_ms = NowMs(); m_running = false; } u64 Timer::ElapsedMs() const { // If we have not started yet, return zero if (m_start_ms == 0) return 0; if (m_running) { u64 now = NowMs(); if (m_start_ms >= now) return 0; return now - m_start_ms; } else { if (m_start_ms >= m_end_ms) return 0; return m_end_ms - m_start_ms; } } u64 Timer::GetLocalTimeSinceJan1970() { #ifdef _MSC_VER std::chrono::zoned_seconds seconds( std::chrono::current_zone(), std::chrono::time_point_cast(std::chrono::system_clock::now())); return seconds.get_local_time().time_since_epoch().count(); #else time_t sysTime, tzDiff, tzDST; time(&sysTime); tm* gmTime = localtime(&sysTime); // Account for DST where needed if (gmTime->tm_isdst == 1) tzDST = 3600; else tzDST = 0; // Lazy way to get local time in sec gmTime = gmtime(&sysTime); tzDiff = sysTime - mktime(gmTime); return static_cast(sysTime + tzDiff + tzDST); #endif } void Timer::IncreaseResolution() { #ifdef _WIN32 // Disable execution speed and timer resolution throttling process-wide. // This mainly will keep Dolphin marked as high performance if it's in the background. The OS // should make it high performance if it's in the foreground anyway (or for some specific // threads e.g. audio). // This is best-effort (i.e. the call may fail on older versions of Windows, where such throttling // doesn't exist, anyway), and we don't bother reverting once set. // This adjusts behavior on CPUs with "performance" and "efficiency" cores PROCESS_POWER_THROTTLING_STATE PowerThrottling{}; PowerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION; PowerThrottling.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED | PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION; PowerThrottling.StateMask = 0; SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottling, sizeof(PowerThrottling)); // Not actually sure how useful this is these days.. :') timeBeginPeriod(1); #endif } void Timer::RestoreResolution() { #ifdef _WIN32 timeEndPeriod(1); #endif } } // Namespace Common