diff --git a/src/butil/time.cpp b/src/butil/time.cpp index 2c726d9b52..1714a5b4e6 100644 --- a/src/butil/time.cpp +++ b/src/butil/time.cpp @@ -143,16 +143,22 @@ int64_t read_cpu_frequency(bool* invariant_tsc) { } // Return value must be >= 0 -int64_t read_invariant_cpu_frequency() { +static int64_t read_invariant_cpu_frequency() { bool invariant_tsc = false; - const int64_t freq = read_cpu_frequency(&invariant_tsc); + int64_t freq = -1; +#if defined(__aarch64__) + __asm__ __volatile__("mrs %0, CNTFRQ_EL0" : "=r"(freq)); +#else + freq = read_cpu_frequency(&invariant_tsc); if (!invariant_tsc || freq < 0) { return 0; } +#endif + return freq; } -int64_t invariant_cpu_freq = -1; +int64_t invariant_cpu_freq = read_invariant_cpu_frequency(); } // namespace detail } // namespace butil diff --git a/src/butil/time.h b/src/butil/time.h index c57000ea99..fa197e5b07 100644 --- a/src/butil/time.h +++ b/src/butil/time.h @@ -265,7 +265,7 @@ inline uint64_t clock_cycles() { #error "unsupported arch" #endif } -extern int64_t read_invariant_cpu_frequency(); + // Be positive iff: // 1 Intel x86_64 CPU (multiple cores) supporting constant_tsc and // nonstop_tsc(check flags in /proc/cpuinfo) @@ -279,7 +279,7 @@ extern int64_t invariant_cpu_freq; // note: Inlining shortens time cost per-call for 15ns in a loop of many // calls to this function. inline int64_t cpuwide_time_ns() { -#if !defined(BAIDU_INTERNAL) +#if !defined(BAIDU_INTERNAL) && !defined(__aarch64__) // nearly impossible to get the correct invariant cpu frequency on // different CPU and machines. CPU-ID rarely works and frequencies // in "model name" and "cpu Mhz" are both unreliable. @@ -298,14 +298,9 @@ inline int64_t cpuwide_time_ns() { const uint64_t remain = tsc % cpu_freq; // TODO: should be OK until CPU's frequency exceeds 16GHz. return remain * 1000000000L / cpu_freq + sec * 1000000000L; - } else if (!cpu_freq) { + } else { // Lack of necessary features, return system-wide monotonic time instead. return monotonic_time_ns(); - } else { - // Use a thread-unsafe method(OK to us) to initialize the freq - // to save a "if" test comparing to using a local static variable - detail::invariant_cpu_freq = detail::read_invariant_cpu_frequency(); - return cpuwide_time_ns(); } #endif // defined(BAIDU_INTERNAL) }