tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

unscaledcycleclock.cc (3275B)


      1 // Copyright 2017 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "absl/base/internal/unscaledcycleclock.h"
     16 
     17 #if ABSL_USE_UNSCALED_CYCLECLOCK
     18 
     19 #if defined(_WIN32)
     20 #include <intrin.h>
     21 #endif
     22 
     23 #if defined(__powerpc__) || defined(__ppc__)
     24 #ifdef __GLIBC__
     25 #include <sys/platform/ppc.h>
     26 #elif defined(__FreeBSD__)
     27 // clang-format off
     28 // This order does actually matter =(.
     29 #include <sys/types.h>
     30 #include <sys/sysctl.h>
     31 // clang-format on
     32 
     33 #include "absl/base/call_once.h"
     34 #endif
     35 #endif
     36 
     37 #include "absl/base/internal/sysinfo.h"
     38 
     39 namespace absl {
     40 ABSL_NAMESPACE_BEGIN
     41 namespace base_internal {
     42 
     43 #if defined(__i386__)
     44 
     45 int64_t UnscaledCycleClock::Now() {
     46  int64_t ret;
     47  __asm__ volatile("rdtsc" : "=A"(ret));
     48  return ret;
     49 }
     50 
     51 double UnscaledCycleClock::Frequency() {
     52  return base_internal::NominalCPUFrequency();
     53 }
     54 
     55 #elif defined(__x86_64__)
     56 
     57 double UnscaledCycleClock::Frequency() {
     58  return base_internal::NominalCPUFrequency();
     59 }
     60 
     61 #elif defined(__powerpc__) || defined(__ppc__)
     62 
     63 int64_t UnscaledCycleClock::Now() {
     64 #ifdef __GLIBC__
     65  return __ppc_get_timebase();
     66 #else
     67 #ifdef __powerpc64__
     68  int64_t tbr;
     69  asm volatile("mfspr %0, 268" : "=r"(tbr));
     70  return tbr;
     71 #else
     72  int32_t tbu, tbl, tmp;
     73  asm volatile(
     74      "mftbu %[hi32]\n"
     75      "mftb %[lo32]\n"
     76      "mftbu %[tmp]\n"
     77      "cmpw %[tmp],%[hi32]\n"
     78      "bne $-16\n"  // Retry on failure.
     79      : [hi32] "=r"(tbu), [lo32] "=r"(tbl), [tmp] "=r"(tmp));
     80  return (static_cast<int64_t>(tbu) << 32) | tbl;
     81 #endif
     82 #endif
     83 }
     84 
     85 double UnscaledCycleClock::Frequency() {
     86 #ifdef __GLIBC__
     87  return __ppc_get_timebase_freq();
     88 #elif defined(_AIX)
     89  // This is the same constant value as returned by
     90  // __ppc_get_timebase_freq().
     91  return static_cast<double>(512000000);
     92 #elif defined(__FreeBSD__)
     93  static once_flag init_timebase_frequency_once;
     94  static double timebase_frequency = 0.0;
     95  base_internal::LowLevelCallOnce(&init_timebase_frequency_once, [&]() {
     96    size_t length = sizeof(timebase_frequency);
     97    sysctlbyname("kern.timecounter.tc.timebase.frequency", &timebase_frequency,
     98                 &length, nullptr, 0);
     99  });
    100  return timebase_frequency;
    101 #else
    102 #error Must implement UnscaledCycleClock::Frequency()
    103 #endif
    104 }
    105 
    106 #elif defined(__aarch64__)
    107 
    108 double UnscaledCycleClock::Frequency() {
    109  uint64_t aarch64_timer_frequency;
    110  asm volatile("mrs %0, cntfrq_el0" : "=r"(aarch64_timer_frequency));
    111  return aarch64_timer_frequency;
    112 }
    113 
    114 #elif defined(_M_IX86) || defined(_M_X64)
    115 
    116 #pragma intrinsic(__rdtsc)
    117 
    118 int64_t UnscaledCycleClock::Now() { return __rdtsc(); }
    119 
    120 double UnscaledCycleClock::Frequency() {
    121  return base_internal::NominalCPUFrequency();
    122 }
    123 
    124 #endif
    125 
    126 }  // namespace base_internal
    127 ABSL_NAMESPACE_END
    128 }  // namespace absl
    129 
    130 #endif  // ABSL_USE_UNSCALED_CYCLECLOCK