about summary refs log tree commit diff
path: root/absl/base/internal/unscaledcycleclock.cc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/base/internal/unscaledcycleclock.cc')
-rw-r--r--absl/base/internal/unscaledcycleclock.cc37
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__)