diff --git a/common/Timer.cpp b/common/Timer.cpp index c109c43a5c..e8b39c678d 100644 --- a/common/Timer.cpp +++ b/common/Timer.cpp @@ -21,6 +21,7 @@ #if defined(_WIN32) #include "RedtapeWindows.h" +#include "Threading.h" #elif defined(__APPLE__) #include #include @@ -212,13 +213,9 @@ namespace Common ThreadCPUTimer::Value ThreadCPUTimer::GetCurrentValue() const { #if defined(_WIN32) - FILETIME create, exit, user, kernel; - if (!m_thread_handle || !GetThreadTimes((HANDLE)m_thread_handle, &create, &exit, &user, &kernel)) - return 0; - - Value value = (static_cast(user.dwHighDateTime) << 32) | (static_cast(user.dwLowDateTime)); - value += (static_cast(kernel.dwHighDateTime) << 32) | (static_cast(kernel.dwLowDateTime)); - return value; + ULONG64 ret = 0; + QueryThreadCycleTime((HANDLE)m_thread_handle, &ret); + return ret; #elif defined(__APPLE__) thread_basic_info_data_t info; mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT; @@ -291,7 +288,16 @@ namespace Common double ThreadCPUTimer::GetUtilizationPercentage(Timer::Value time_diff, Value cpu_time_diff) { #if defined(_WIN32) - return ((static_cast(cpu_time_diff) * 10000.0) / (static_cast(time_diff) / s_counter_frequency)); + // we need to convert from the rdtsc domain to the QPC domain (may not necessarily match) + static bool ratio_initialized = false; + static double ratio = 0.0; + if (unlikely(!ratio_initialized)) + { + ratio = (static_cast(Threading::GetThreadTicksPerSecond()) / static_cast(GetTickFrequency())) / 100.0; + ratio_initialized = true; + } + + return (static_cast(cpu_time_diff) / (static_cast(time_diff) * ratio)); #elif defined(__APPLE__) // microseconds, but time_tiff is in nanoseconds, so multiply by 1000 * 100 return (static_cast(cpu_time_diff) * 100000.0) / static_cast(time_diff); @@ -304,8 +310,7 @@ namespace Common double ThreadCPUTimer::ConvertValueToSeconds(Value value) { #if defined(_WIN32) - // 100ns units - return (static_cast(value) / 10000000.0); + return (static_cast(value) / Threading::GetThreadTicksPerSecond()); #elif defined(__APPLE__) // microseconds return (static_cast(value) / 1000000.0); @@ -318,7 +323,7 @@ namespace Common double ThreadCPUTimer::ConvertValueToMilliseconds(Value value) { #if defined(_WIN32) - return (static_cast(value) / 10000.0); + return (static_cast(value) / (Threading::GetThreadTicksPerSecond() / 1000.0)); #elif defined(__APPLE__) return (static_cast(value) / 1000.0); #else @@ -329,7 +334,7 @@ namespace Common double ThreadCPUTimer::ConvertValueToNanoseconds(Value value) { #if defined(_WIN32) - return (static_cast(value) * 100.0); + return (static_cast(value) / (Threading::GetThreadTicksPerSecond() / 1000000000.0)); #elif defined(__APPLE__) return (static_cast(value) * 1000.0); #else diff --git a/common/Windows/WinThreads.cpp b/common/Windows/WinThreads.cpp index a4a6cb377d..8b0f381f61 100644 --- a/common/Windows/WinThreads.cpp +++ b/common/Windows/WinThreads.cpp @@ -47,39 +47,29 @@ __fi void Threading::DisableHiresScheduler() timeEndPeriod(1); } -// This hacky union would probably fail on some cpu platforms if the contents of FILETIME aren't -// packed (but for any x86 CPU and microsoft compiler, they will be). -union FileTimeSucks -{ - FILETIME filetime; - u64 u64time; -}; - u64 Threading::GetThreadCpuTime() { - FileTimeSucks user, kernel; - FILETIME dummy; - GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &kernel.filetime, &user.filetime); - return user.u64time + kernel.u64time; + u64 ret = 0; + QueryThreadCycleTime(GetCurrentThread(), &ret); + return ret; } u64 Threading::GetThreadTicksPerSecond() { - return 10000000; + // On x86, despite what the MS documentation says, this basically appears to be rdtsc. + // So, the frequency is our base clock speed (and stable regardless of power management). + static u64 frequency = 0; + if (unlikely(frequency == 0)) + frequency = x86caps.CachedMHz() * u64(1000000); + return frequency; } u64 Threading::pxThread::GetCpuTime() const { - if (!m_native_handle) - return 0; - - FileTimeSucks user, kernel; - FILETIME dummy; - - if (GetThreadTimes((HANDLE)m_native_handle, &dummy, &dummy, &kernel.filetime, &user.filetime)) - return user.u64time + kernel.u64time; - - return 0; // thread prolly doesn't exist anymore. + u64 ret = 0; + if (m_native_handle) + QueryThreadCycleTime((HANDLE)m_native_handle, &ret); + return ret; } void Threading::pxThread::_platform_specific_OnStartInThread()