about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkgotlinux <60880393+kgotlinux@users.noreply.github.com>2020-02-25T21·27+0100
committerGitHub <noreply@github.com>2020-02-25T21·27-0500
commit0033c9ea91a52ade7c6b725aa2ef3cbe15463421 (patch)
treeebd3c8565a05c8cac726f11835e25cad98144223
parent0d5ce2797eb695aee7e019e25323251ef6ffc277 (diff)
Fix build on FreeBSD/powerpc (#616)
* Fix build on FreeBSD/powerpc

Only glibc has __ppc_get_timebase(), __ppc_get_timebase_freq() and sys/platform/ppc.h.
-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 a32936aeab..f1e7bbef84 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__)