Threading/Win32: Use QueryThreadCycleTime() for thread CPU time

This commit is contained in:
Connor McLaughlin 2022-05-02 15:15:47 +10:00 committed by refractionpcsx2
parent 7d81c979fe
commit 5eae7a6328
2 changed files with 30 additions and 35 deletions

View File

@ -21,6 +21,7 @@
#if defined(_WIN32)
#include "RedtapeWindows.h"
#include "Threading.h"
#elif defined(__APPLE__)
#include <mach/mach_init.h>
#include <mach/thread_act.h>
@ -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<Value>(user.dwHighDateTime) << 32) | (static_cast<Value>(user.dwLowDateTime));
value += (static_cast<Value>(kernel.dwHighDateTime) << 32) | (static_cast<Value>(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<double>(cpu_time_diff) * 10000.0) / (static_cast<double>(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<double>(Threading::GetThreadTicksPerSecond()) / static_cast<double>(GetTickFrequency())) / 100.0;
ratio_initialized = true;
}
return (static_cast<double>(cpu_time_diff) / (static_cast<double>(time_diff) * ratio));
#elif defined(__APPLE__)
// microseconds, but time_tiff is in nanoseconds, so multiply by 1000 * 100
return (static_cast<double>(cpu_time_diff) * 100000.0) / static_cast<double>(time_diff);
@ -304,8 +310,7 @@ namespace Common
double ThreadCPUTimer::ConvertValueToSeconds(Value value)
{
#if defined(_WIN32)
// 100ns units
return (static_cast<double>(value) / 10000000.0);
return (static_cast<double>(value) / Threading::GetThreadTicksPerSecond());
#elif defined(__APPLE__)
// microseconds
return (static_cast<double>(value) / 1000000.0);
@ -318,7 +323,7 @@ namespace Common
double ThreadCPUTimer::ConvertValueToMilliseconds(Value value)
{
#if defined(_WIN32)
return (static_cast<double>(value) / 10000.0);
return (static_cast<double>(value) / (Threading::GetThreadTicksPerSecond() / 1000.0));
#elif defined(__APPLE__)
return (static_cast<double>(value) / 1000.0);
#else
@ -329,7 +334,7 @@ namespace Common
double ThreadCPUTimer::ConvertValueToNanoseconds(Value value)
{
#if defined(_WIN32)
return (static_cast<double>(value) * 100.0);
return (static_cast<double>(value) / (Threading::GetThreadTicksPerSecond() / 1000000000.0));
#elif defined(__APPLE__)
return (static_cast<double>(value) * 1000.0);
#else

View File

@ -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()