Home | History | Annotate | Download | only in time
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      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 #if defined(OS_ANDROID) && !defined(__LP64__)
     11 #include <time64.h>
     12 #endif
     13 #include <unistd.h>
     14 
     15 #include "base/logging.h"
     16 #include "base/numerics/safe_math.h"
     17 #include "base/time/time_override.h"
     18 #include "build/build_config.h"
     19 
     20 // Ensure the Fuchsia and Mac builds do not include this module. Instead,
     21 // non-POSIX implementation is used for sampling the system clocks.
     22 #if defined(OS_FUCHSIA) || defined(OS_MACOSX)
     23 #error "This implementation is for POSIX platforms other than Fuchsia or Mac."
     24 #endif
     25 
     26 namespace {
     27 
     28 int64_t ConvertTimespecToMicros(const struct timespec& ts) {
     29   // On 32-bit systems, the calculation cannot overflow int64_t.
     30   // 2**32 * 1000000 + 2**64 / 1000 < 2**63
     31   if (sizeof(ts.tv_sec) <= 4 && sizeof(ts.tv_nsec) <= 8) {
     32     int64_t result = ts.tv_sec;
     33     result *= base::Time::kMicrosecondsPerSecond;
     34     result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
     35     return result;
     36   } else {
     37     base::CheckedNumeric<int64_t> result(ts.tv_sec);
     38     result *= base::Time::kMicrosecondsPerSecond;
     39     result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
     40     return result.ValueOrDie();
     41   }
     42 }
     43 
     44 // Helper function to get results from clock_gettime() and convert to a
     45 // microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported
     46 // on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines
     47 // _POSIX_MONOTONIC_CLOCK to -1.
     48 #if (defined(OS_POSIX) && defined(_POSIX_MONOTONIC_CLOCK) && \
     49      _POSIX_MONOTONIC_CLOCK >= 0) ||                         \
     50     defined(OS_BSD) || defined(OS_ANDROID)
     51 int64_t ClockNow(clockid_t clk_id) {
     52   struct timespec ts;
     53   CHECK(clock_gettime(clk_id, &ts) == 0);
     54   return ConvertTimespecToMicros(ts);
     55 }
     56 #else  // _POSIX_MONOTONIC_CLOCK
     57 #error No usable tick clock function on this platform.
     58 #endif  // _POSIX_MONOTONIC_CLOCK
     59 
     60 }  // namespace
     61 
     62 namespace base {
     63 
     64 // Time -----------------------------------------------------------------------
     65 
     66 namespace subtle {
     67 Time TimeNowIgnoringOverride() {
     68   struct timeval tv;
     69   struct timezone tz = {0, 0};  // UTC
     70   CHECK(gettimeofday(&tv, &tz) == 0);
     71   // Combine seconds and microseconds in a 64-bit field containing microseconds
     72   // since the epoch.  That's enough for nearly 600 centuries.  Adjust from
     73   // Unix (1970) to Windows (1601) epoch.
     74   return Time() + TimeDelta::FromMicroseconds(
     75                       (tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) +
     76                       Time::kTimeTToMicrosecondsOffset);
     77 }
     78 
     79 Time TimeNowFromSystemTimeIgnoringOverride() {
     80   // Just use TimeNowIgnoringOverride() because it returns the system time.
     81   return TimeNowIgnoringOverride();
     82 }
     83 }  // namespace subtle
     84 
     85 // TimeTicks ------------------------------------------------------------------
     86 
     87 namespace subtle {
     88 TimeTicks TimeTicksNowIgnoringOverride() {
     89   return TimeTicks() + TimeDelta::FromMicroseconds(ClockNow(CLOCK_MONOTONIC));
     90 }
     91 }  // namespace subtle
     92 
     93 // static
     94 TimeTicks::Clock TimeTicks::GetClock() {
     95   return Clock::LINUX_CLOCK_MONOTONIC;
     96 }
     97 
     98 // static
     99 bool TimeTicks::IsHighResolution() {
    100   return true;
    101 }
    102 
    103 // static
    104 bool TimeTicks::IsConsistentAcrossProcesses() {
    105   return true;
    106 }
    107 
    108 // ThreadTicks ----------------------------------------------------------------
    109 
    110 namespace subtle {
    111 ThreadTicks ThreadTicksNowIgnoringOverride() {
    112 #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
    113     defined(OS_ANDROID)
    114   return ThreadTicks() +
    115          TimeDelta::FromMicroseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID));
    116 #else
    117   NOTREACHED();
    118   return ThreadTicks();
    119 #endif
    120 }
    121 }  // namespace subtle
    122 
    123 }  // namespace base
    124