tor-browser

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

time_now_posix.cc (4254B)


      1 // Copyright 2012 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/time/time.h"
      6 
      7 #include <stdint.h>
      8 #include <sys/time.h>
      9 #include <time.h>
     10 #include <unistd.h>
     11 
     12 #include "base/check.h"
     13 #include "base/notreached.h"
     14 #include "base/numerics/safe_math.h"
     15 #include "base/time/time_override.h"
     16 #include "build/build_config.h"
     17 #include "third_party/abseil-cpp/absl/types/optional.h"
     18 
     19 #if BUILDFLAG(IS_ANDROID) && !defined(__LP64__)
     20 #include <time64.h>
     21 #endif
     22 
     23 // Ensure the Fuchsia and Mac builds do not include this module. Instead,
     24 // non-POSIX implementation is used for sampling the system clocks.
     25 #if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_APPLE)
     26 #error "This implementation is for POSIX platforms other than Fuchsia or Mac."
     27 #endif
     28 
     29 namespace {
     30 
     31 int64_t ConvertTimespecToMicros(const struct timespec& ts) {
     32  // On 32-bit systems, the calculation cannot overflow int64_t.
     33  // 2**32 * 1000000 + 2**64 / 1000 < 2**63
     34  if (sizeof(ts.tv_sec) <= 4 && sizeof(ts.tv_nsec) <= 8) {
     35    int64_t result = ts.tv_sec;
     36    result *= base::Time::kMicrosecondsPerSecond;
     37    result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
     38    return result;
     39  }
     40  base::CheckedNumeric<int64_t> result(ts.tv_sec);
     41  result *= base::Time::kMicrosecondsPerSecond;
     42  result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
     43  return result.ValueOrDie();
     44 }
     45 
     46 // Helper function to get results from clock_gettime() and convert to a
     47 // microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported
     48 // on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines
     49 // _POSIX_MONOTONIC_CLOCK to -1.
     50 #if (BUILDFLAG(IS_POSIX) && defined(_POSIX_MONOTONIC_CLOCK) && \
     51     _POSIX_MONOTONIC_CLOCK >= 0) ||                           \
     52    BUILDFLAG(IS_BSD) || BUILDFLAG(IS_ANDROID)
     53 int64_t ClockNow(clockid_t clk_id) {
     54  struct timespec ts;
     55  CHECK(clock_gettime(clk_id, &ts) == 0);
     56  return ConvertTimespecToMicros(ts);
     57 }
     58 
     59 absl::optional<int64_t> MaybeClockNow(clockid_t clk_id) {
     60  struct timespec ts;
     61  int res = clock_gettime(clk_id, &ts);
     62  if (res == 0)
     63    return ConvertTimespecToMicros(ts);
     64  return absl::nullopt;
     65 }
     66 
     67 #else  // _POSIX_MONOTONIC_CLOCK
     68 #error No usable tick clock function on this platform.
     69 #endif  // _POSIX_MONOTONIC_CLOCK
     70 
     71 }  // namespace
     72 
     73 namespace base {
     74 
     75 // Time -----------------------------------------------------------------------
     76 
     77 namespace subtle {
     78 Time TimeNowIgnoringOverride() {
     79  struct timeval tv;
     80  struct timezone tz = {0, 0};  // UTC
     81  CHECK(gettimeofday(&tv, &tz) == 0);
     82  // Combine seconds and microseconds in a 64-bit field containing microseconds
     83  // since the epoch.  That's enough for nearly 600 centuries.  Adjust from
     84  // Unix (1970) to Windows (1601) epoch.
     85  return Time() +
     86         Microseconds((tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) +
     87                      Time::kTimeTToMicrosecondsOffset);
     88 }
     89 
     90 Time TimeNowFromSystemTimeIgnoringOverride() {
     91  // Just use TimeNowIgnoringOverride() because it returns the system time.
     92  return TimeNowIgnoringOverride();
     93 }
     94 }  // namespace subtle
     95 
     96 // TimeTicks ------------------------------------------------------------------
     97 
     98 namespace subtle {
     99 TimeTicks TimeTicksNowIgnoringOverride() {
    100  return TimeTicks() + Microseconds(ClockNow(CLOCK_MONOTONIC));
    101 }
    102 
    103 absl::optional<TimeTicks> MaybeTimeTicksNowIgnoringOverride() {
    104  absl::optional<int64_t> now = MaybeClockNow(CLOCK_MONOTONIC);
    105  if (now.has_value())
    106    return TimeTicks() + Microseconds(now.value());
    107  return absl::nullopt;
    108 }
    109 }  // namespace subtle
    110 
    111 // static
    112 TimeTicks::Clock TimeTicks::GetClock() {
    113  return Clock::LINUX_CLOCK_MONOTONIC;
    114 }
    115 
    116 // static
    117 bool TimeTicks::IsHighResolution() {
    118  return true;
    119 }
    120 
    121 // static
    122 bool TimeTicks::IsConsistentAcrossProcesses() {
    123  return true;
    124 }
    125 
    126 // ThreadTicks ----------------------------------------------------------------
    127 
    128 namespace subtle {
    129 ThreadTicks ThreadTicksNowIgnoringOverride() {
    130 #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
    131    BUILDFLAG(IS_ANDROID)
    132  return ThreadTicks() + Microseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID));
    133 #else
    134  NOTREACHED();
    135  return ThreadTicks();
    136 #endif
    137 }
    138 }  // namespace subtle
    139 
    140 }  // namespace base