diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index 98a6a157..d1d063b0 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -35,6 +35,11 @@ #define init_order(x) #endif +#if defined TRACY_HW_TIMER && __ARM_ARCH >= 6 +# include +# include +#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::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 init_order(103) s_queue( QueuePrealloc ); std::atomic 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(); diff --git a/client/TracyProfiler.hpp b/client/TracyProfiler.hpp index 8a0dca56..fdfaa62d 100644 --- a/client/TracyProfiler.hpp +++ b/client/TracyProfiler.hpp @@ -19,11 +19,7 @@ # include #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 ) );