Test if HW timer can be used on arm.

This commit is contained in:
Bartosz Taudul 2018-04-27 16:58:45 +02:00
parent 6a2311a7b7
commit 237aee30a8
2 changed files with 86 additions and 23 deletions

View File

@ -35,6 +35,11 @@
#define init_order(x)
#endif
#if defined TRACY_HW_TIMER && __ARM_ARCH >= 6
# include <signal.h>
# include <setjmp.h>
#endif
namespace tracy
{
@ -53,6 +58,69 @@ struct InitTimeWrapper
int64_t val;
};
#if defined TRACY_HW_TIMER && __ARM_ARCH >= 6
int64_t (*GetTimeImpl)();
int64_t GetTimeImplFallback()
{
return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
}
int64_t GetTimeImplCntvct()
{
int64_t t;
# ifdef __aarch64__
asm volatile ( "mrs %0, cntvct_el0" : "=r" (t) );
# else
asm volatile ( "mrrc p15, 1, %Q0, %R0, c14" : "=r" (t) );
# endif
return t;
}
static sigjmp_buf SigIllEnv;
static int SetupHwTimerFailed()
{
return sigsetjmp( SigIllEnv, 1 );
}
static void SetupHwTimerSigIllHandler( int signum )
{
siglongjmp( SigIllEnv, 1 );
}
static int64_t SetupHwTimer()
{
struct sigaction act, oldact;
memset( &act, 0, sizeof( act ) );
act.sa_handler = SetupHwTimerSigIllHandler;
if( sigaction( SIGILL, &act, &oldact ) )
{
GetTimeImpl = GetTimeImplFallback;
return Profiler::GetTime();
}
if( SetupHwTimerFailed() )
{
sigaction( SIGILL, &oldact, nullptr );
GetTimeImpl = GetTimeImplFallback;
return Profiler::GetTime();
}
GetTimeImplCntvct();
sigaction( SIGILL, &oldact, nullptr );
GetTimeImpl = GetTimeImplCntvct;
return Profiler::GetTime();
}
#else
static int64_t SetupHwTimer()
{
return Profiler::GetTime();
}
#endif
static const char* GetProcessName()
{
#if defined _MSC_VER
@ -96,7 +164,7 @@ thread_local ProducerWrapper init_order(108) s_token { s_queue.get_explicit_prod
# pragma init_seg( ".CRT$XCB" )
#endif
static InitTimeWrapper init_order(101) s_initTime { Profiler::GetTime() };
static InitTimeWrapper init_order(101) s_initTime { SetupHwTimer() };
static RPMallocInit init_order(102) s_rpmalloc_init;
moodycamel::ConcurrentQueue<QueueItem> init_order(103) s_queue( QueuePrealloc );
std::atomic<uint32_t> init_order(104) s_lockCounter( 0 );
@ -498,6 +566,14 @@ bool Profiler::HandleServerQuery()
void Profiler::CalibrateTimer()
{
#ifdef TRACY_HW_TIMER
# if __ARM_ARCH >= 6
if( GetTimeImpl == GetTimeImplFallback )
{
m_timerMul = 1.;
return;
}
# endif
std::atomic_signal_fence( std::memory_order_acq_rel );
const auto t0 = std::chrono::high_resolution_clock::now();
const auto r0 = GetTime();

View File

@ -19,11 +19,7 @@
# include <intrin.h>
#endif
#if defined _MSC_VER || defined __CYGWIN__ || ( ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 ) && !defined __ANDROID__ )
# define TRACY_HW_TIMER
#endif
#if defined __aarch64__ || __ARM_ARCH >= 6
#if defined _MSC_VER || defined __CYGWIN__ || ( ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 ) && !defined __ANDROID__ ) || __ARM_ARCH >= 6
# define TRACY_HW_TIMER
#endif
@ -56,6 +52,10 @@ struct GpuCtxWrapper
using Magic = moodycamel::ConcurrentQueueDefaultTraits::index_t;
#if __ARM_ARCH >= 6
extern int64_t (*GetTimeImpl)();
#endif
class Profiler;
extern Profiler s_profiler;
@ -68,16 +68,9 @@ public:
static tracy_force_inline int64_t GetTime( uint32_t& cpu )
{
#ifdef TRACY_HW_TIMER
# if defined __aarch64__
int64_t t;
# if __ARM_ARCH >= 6
cpu = 0xFFFFFFFF;
asm volatile ( "mrs %0, cntvct_el0" : "=r" (t) );
return t;
# elif __ARM_ARCH >= 6
int64_t t;
cpu = 0xFFFFFFFF;
asm volatile ( "mrrc p15, 1, %Q0, %R0, c14" : "=r" (t) );
return t;
return GetTimeImpl();
# elif defined _MSC_VER || defined __CYGWIN__
const auto t = int64_t( __rdtscp( &cpu ) );
return t;
@ -95,14 +88,8 @@ public:
static tracy_force_inline int64_t GetTime()
{
#ifdef TRACY_HW_TIMER
# if defined __aarch64__
int64_t t;
asm volatile ( "mrs %0, cntvct_el0" : "=r" (t) );
return t;
# elif __ARM_ARCH >= 6
int64_t t;
asm volatile ( "mrrc p15, 1, %Q0, %R0, c14" : "=r" (t) );
return t;
# if __ARM_ARCH >= 6
return GetTimeImpl();
# elif defined _MSC_VER || defined __CYGWIN__
unsigned int dontcare;
const auto t = int64_t( __rdtscp( &dontcare ) );