2015-05-23 22:55:12 -06:00
|
|
|
// Copyright 2008 Dolphin Emulator Project
|
2021-07-04 19:22:19 -06:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2008-12-07 22:30:24 -07:00
|
|
|
|
2019-06-14 08:53:46 -06:00
|
|
|
#include "Common/Timer.h"
|
|
|
|
|
2020-07-12 11:36:58 -06:00
|
|
|
#include <chrono>
|
2008-12-07 22:30:24 -07:00
|
|
|
|
2010-01-21 12:55:01 -07:00
|
|
|
#ifdef _WIN32
|
2022-07-17 21:43:47 -06:00
|
|
|
#include <Windows.h>
|
2022-08-06 23:22:14 -06:00
|
|
|
#include <ctime>
|
2022-07-17 21:59:31 -06:00
|
|
|
#include <timeapi.h>
|
2010-11-19 20:24:51 -07:00
|
|
|
#else
|
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
2010-01-21 12:55:01 -07:00
|
|
|
|
2014-02-19 20:11:52 -07:00
|
|
|
#include "Common/CommonTypes.h"
|
2008-12-07 22:30:24 -07:00
|
|
|
|
2010-01-21 12:55:01 -07:00
|
|
|
namespace Common
|
|
|
|
{
|
2022-07-17 21:43:47 -06:00
|
|
|
template <typename Clock, typename Duration>
|
|
|
|
static typename Clock::rep time_now()
|
2010-07-21 22:15:11 -06:00
|
|
|
{
|
2022-07-17 21:43:47 -06:00
|
|
|
return std::chrono::time_point_cast<Duration>(Clock::now()).time_since_epoch().count();
|
2010-07-21 22:15:11 -06:00
|
|
|
}
|
2009-02-15 23:18:18 -07:00
|
|
|
|
2022-07-17 21:43:47 -06:00
|
|
|
template <typename Duration>
|
|
|
|
static auto steady_time_now()
|
2014-11-19 11:57:12 -07:00
|
|
|
{
|
2022-07-17 21:43:47 -06:00
|
|
|
return time_now<std::chrono::steady_clock, Duration>();
|
2014-11-19 11:57:12 -07:00
|
|
|
}
|
|
|
|
|
2022-07-17 21:43:47 -06:00
|
|
|
u64 Timer::NowUs()
|
2014-11-19 11:57:12 -07:00
|
|
|
{
|
2022-07-17 21:43:47 -06:00
|
|
|
return steady_time_now<std::chrono::microseconds>();
|
2014-11-19 11:57:12 -07:00
|
|
|
}
|
|
|
|
|
2022-07-17 21:43:47 -06:00
|
|
|
u64 Timer::NowMs()
|
2008-07-12 11:40:22 -06:00
|
|
|
{
|
2022-07-17 21:43:47 -06:00
|
|
|
return steady_time_now<std::chrono::milliseconds>();
|
2008-07-12 11:40:22 -06:00
|
|
|
}
|
2008-12-07 22:30:24 -07:00
|
|
|
|
2009-02-15 23:18:18 -07:00
|
|
|
void Timer::Start()
|
|
|
|
{
|
2022-07-17 21:43:47 -06:00
|
|
|
m_start_ms = NowMs();
|
|
|
|
m_end_ms = 0;
|
|
|
|
m_running = true;
|
2009-02-15 23:18:18 -07:00
|
|
|
}
|
2008-12-07 22:30:24 -07:00
|
|
|
|
2022-07-17 21:43:47 -06:00
|
|
|
void Timer::StartWithOffset(u64 offset)
|
2009-02-15 23:18:18 -07:00
|
|
|
{
|
2022-07-17 21:43:47 -06:00
|
|
|
Start();
|
2022-07-18 12:48:20 -06:00
|
|
|
m_start_ms -= offset;
|
2009-02-15 23:18:18 -07:00
|
|
|
}
|
|
|
|
|
2022-07-17 21:43:47 -06:00
|
|
|
void Timer::Stop()
|
2009-02-15 23:18:18 -07:00
|
|
|
{
|
2022-07-17 21:43:47 -06:00
|
|
|
m_end_ms = NowMs();
|
|
|
|
m_running = false;
|
2009-02-15 23:18:18 -07:00
|
|
|
}
|
2010-07-21 22:15:11 -06:00
|
|
|
|
2022-07-17 21:43:47 -06:00
|
|
|
u64 Timer::ElapsedMs() const
|
2009-02-15 23:18:18 -07:00
|
|
|
{
|
2022-07-18 12:48:20 -06:00
|
|
|
const u64 end = m_running ? NowMs() : m_end_ms;
|
|
|
|
// Can handle up to 1 rollover event (underflow produces correct result)
|
|
|
|
// If Start() has never been called, will return 0
|
|
|
|
return end - m_start_ms;
|
2008-07-12 11:40:22 -06:00
|
|
|
}
|
2008-12-13 04:57:01 -07:00
|
|
|
|
2009-02-22 05:43:25 -07:00
|
|
|
u64 Timer::GetLocalTimeSinceJan1970()
|
2008-12-13 04:57:01 -07:00
|
|
|
{
|
2022-08-06 23:25:30 -06:00
|
|
|
// TODO Would really, really like to use std::chrono here, but Windows did not support
|
|
|
|
// std::chrono::current_zone() until 19H1, and other compilers don't even provide support for
|
|
|
|
// timezone-related parts of chrono. Someday!
|
|
|
|
// see https://bugs.dolphin-emu.org/issues/13007#note-4
|
2010-08-26 13:24:47 -06:00
|
|
|
time_t sysTime, tzDiff, tzDST;
|
2008-12-13 04:57:01 -07:00
|
|
|
time(&sysTime);
|
2016-07-13 14:46:14 -06:00
|
|
|
tm* gmTime = localtime(&sysTime);
|
2010-08-26 13:24:47 -06:00
|
|
|
|
|
|
|
// Account for DST where needed
|
2014-03-10 05:30:55 -06:00
|
|
|
if (gmTime->tm_isdst == 1)
|
2010-08-26 13:24:47 -06:00
|
|
|
tzDST = 3600;
|
|
|
|
else
|
|
|
|
tzDST = 0;
|
|
|
|
|
2008-12-13 04:57:01 -07:00
|
|
|
// Lazy way to get local time in sec
|
|
|
|
gmTime = gmtime(&sysTime);
|
|
|
|
tzDiff = sysTime - mktime(gmTime);
|
|
|
|
|
2016-07-13 14:46:14 -06:00
|
|
|
return static_cast<u64>(sysTime + tzDiff + tzDST);
|
2008-12-13 04:57:01 -07:00
|
|
|
}
|
2009-01-14 23:48:15 -07:00
|
|
|
|
2022-07-17 21:43:47 -06:00
|
|
|
void Timer::IncreaseResolution()
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
2022-07-18 01:20:26 -06:00
|
|
|
// 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.. :')
|
2022-07-17 21:43:47 -06:00
|
|
|
timeBeginPeriod(1);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void Timer::RestoreResolution()
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
timeEndPeriod(1);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-03-28 02:57:34 -06:00
|
|
|
} // Namespace Common
|