|
|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
#include "tier1/reliabletimer.h"
|
|
|
|
|
|
|
|
int64 CReliableTimer::sm_nPerformanceFrequency = 0;
|
|
|
|
bool CReliableTimer::sm_bUseQPC = false;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include "winlite.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef POSIX
|
|
|
|
#include <time.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: Constructor
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
CReliableTimer::CReliableTimer()
|
|
|
|
{
|
|
|
|
m_nPerformanceCounterStart = 0;
|
|
|
|
m_nPerformanceCounterEnd = 0;
|
|
|
|
m_nPerformanceCounterLimit = 0;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
// calculate performance frequency the first time we use a timer
|
|
|
|
if ( 0 == sm_nPerformanceFrequency )
|
|
|
|
{
|
|
|
|
// Are we on a bad CPU?
|
|
|
|
sm_bUseQPC = false; // todo
|
|
|
|
const CPUInformation &cpu = *GetCPUInformation();
|
|
|
|
sm_bUseQPC = ( ( 0 == Q_stricmp( cpu.m_szProcessorID, "AuthenticAMD" ) )
|
|
|
|
&& ( cpu.m_nPhysicalProcessors > 1 )
|
|
|
|
&& !cpu.m_bSSE41 );
|
|
|
|
|
|
|
|
if ( sm_bUseQPC )
|
|
|
|
{
|
|
|
|
LARGE_INTEGER li;
|
|
|
|
QueryPerformanceFrequency( &li );
|
|
|
|
sm_nPerformanceFrequency = li.QuadPart;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sm_nPerformanceFrequency = g_ClockSpeed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#elif defined(_PS3)
|
|
|
|
// On PowerPC, the time base register increment frequency is implementation dependent, and doesn't have to be constant.
|
|
|
|
// On PS3, measured it to be just shy of 80Mhz on the PPU and doesn't seem to change
|
|
|
|
if ( sm_nPerformanceFrequency == 0 )
|
|
|
|
sm_nPerformanceFrequency = sys_time_get_timebase_frequency();
|
|
|
|
#else
|
|
|
|
// calculate performance frequency the first time we use a timer
|
|
|
|
if ( 0 == sm_nPerformanceFrequency )
|
|
|
|
{
|
|
|
|
sm_nPerformanceFrequency = g_ClockSpeed;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Purpose: Returns current QueryPerformanceCounter value
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int64 CReliableTimer::GetPerformanceCountNow()
|
|
|
|
{
|
|
|
|
//VPROF_BUDGET( "CReliableTimer::GetPerformanceCountNow", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
|
|
#ifdef _WIN32
|
|
|
|
if ( sm_bUseQPC )
|
|
|
|
{
|
|
|
|
LARGE_INTEGER li = {0};
|
|
|
|
QueryPerformanceCounter( &li );
|
|
|
|
return li.QuadPart;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CCycleCount CycleCount;
|
|
|
|
CycleCount.Sample();
|
|
|
|
return CycleCount.GetLongCycles();
|
|
|
|
}
|
|
|
|
#elif defined( _PS3 )
|
|
|
|
// use handy macro to grab tb
|
|
|
|
uint64 ulNow;
|
|
|
|
SYS_TIMEBASE_GET( ulNow );
|
|
|
|
return ulNow;
|
|
|
|
#elif (defined( __arm__ ) || defined( __aarch64__ )) && defined (POSIX)
|
|
|
|
struct timespec ts;
|
|
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
|
|
return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
|
|
|
|
#else
|
|
|
|
uint64 un64;
|
|
|
|
__asm__ __volatile__ (
|
|
|
|
"rdtsc\n\t"
|
|
|
|
: "=A" (un64) );
|
|
|
|
return (int64)un64;
|
|
|
|
#endif
|
|
|
|
}
|