diff options
Diffstat (limited to 'absl/base')
-rw-r--r-- | absl/base/internal/unscaledcycleclock.cc | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc index a32936aeab4e..f1e7bbef844a 100644 --- a/absl/base/internal/unscaledcycleclock.cc +++ b/absl/base/internal/unscaledcycleclock.cc @@ -21,7 +21,12 @@ #endif #if defined(__powerpc__) || defined(__ppc__) +#ifdef __GLIBC__ #include <sys/platform/ppc.h> +#elif defined(__FreeBSD__) +#include <sys/sysctl.h> +#include <sys/types.h> +#endif #endif #include "absl/base/internal/sysinfo.h" @@ -57,11 +62,43 @@ double UnscaledCycleClock::Frequency() { #elif defined(__powerpc__) || defined(__ppc__) int64_t UnscaledCycleClock::Now() { +#ifdef __GLIBC__ return __ppc_get_timebase(); +#else +#ifdef __powerpc64__ + int64_t tbr; + asm volatile("mfspr %0, 268" : "=r"(tbr)); + return tbr; +#else + int32_t tbu, tbl, tmp; + asm volatile( + "0:\n" + "mftbu %[hi32]\n" + "mftb %[lo32]\n" + "mftbu %[tmp]\n" + "cmpw %[tmp],%[hi32]\n" + "bne 0b\n" + : [ hi32 ] "=r"(tbu), [ lo32 ] "=r"(tbl), [ tmp ] "=r"(tmp)); + return (static_cast<int64_t>(tbu) << 32) | tbl; +#endif +#endif } double UnscaledCycleClock::Frequency() { +#ifdef __GLIBC__ return __ppc_get_timebase_freq(); +#elif defined(__FreeBSD__) + static once_flag init_timebase_frequency_once; + static double timebase_frequency = 0.0; + base_internal::LowLevelCallOnce(&init_timebase_frequency_once, [&]() { + size_t length = sizeof(timebase_frequency); + sysctlbyname("kern.timecounter.tc.timebase.frequency", &timebase_frequency, + &length, nullptr, 0); + }); + return timebase_frequency; +#else +#error Must implement UnscaledCycleClock::Frequency() +#endif } #elif defined(__aarch64__) |