time_now_posix.cc 4.2 KB

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