source-engine/tier1/reliabletimer.cpp
2022-06-19 15:07:41 +03:00

102 lines
2.7 KiB
C++

//========= 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
}