Skip to content

Commit

Permalink
base: Add override mechanism for Time/TimeTicks/ThreadTicks::Now.
Browse files Browse the repository at this point in the history
Allows clients to provide functions to override the return values of
Time::Now(), TimeTicks::Now(), ThreadTicks::Now().

Also adds a way to bypass the override in places where real timestamps
should be used even if an override is set.

Bug: 802217, 751993
Change-Id: I76ce536caf9bf0ef5e580abcc23215ce9851ee34
Reviewed-on: https://chromium-review.googlesource.com/867911
Commit-Queue: Eric Seckler <eseckler@chromium.org>
Reviewed-by: Gabriel Charette <gab@chromium.org>
Reviewed-by: Yuri Wiitala <miu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#531923}
  • Loading branch information
betasheet authored and Commit Bot committed Jan 25, 2018
1 parent ff96a21 commit a936793
Show file tree
Hide file tree
Showing 9 changed files with 473 additions and 103 deletions.
2 changes: 2 additions & 0 deletions base/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,8 @@ jumbo_component("base") {
"time/tick_clock.h",
"time/time.cc",
"time/time.h",
"time/time_override.cc",
"time/time_override.h",
"timer/elapsed_timer.cc",
"timer/elapsed_timer.h",
"timer/hi_res_timer_manager.h",
Expand Down
49 changes: 46 additions & 3 deletions base/time/time.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,26 @@
#include "base/no_destructor.h"
#include "base/strings/stringprintf.h"
#include "base/third_party/nspr/prtime.h"
#include "base/time/time_override.h"
#include "build/build_config.h"

namespace base {

namespace internal {

TimeNowFunction g_time_now_function = &subtle::TimeNowIgnoringOverride;

TimeNowFunction g_time_now_from_system_time_function =
&subtle::TimeNowFromSystemTimeIgnoringOverride;

TimeTicksNowFunction g_time_ticks_now_function =
&subtle::TimeTicksNowIgnoringOverride;

ThreadTicksNowFunction g_thread_ticks_now_function =
&subtle::ThreadTicksNowIgnoringOverride;

} // namespace internal

// TimeDelta ------------------------------------------------------------------

int TimeDelta::InDays() const {
Expand Down Expand Up @@ -134,6 +150,17 @@ std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) {

// Time -----------------------------------------------------------------------

// static
Time Time::Now() {
return internal::g_time_now_function();
}

// static
Time Time::NowFromSystemTime() {
// Just use g_time_now_function because it returns the system time.
return internal::g_time_now_from_system_time_function();
}

// static
Time Time::FromDeltaSinceWindowsEpoch(TimeDelta delta) {
return Time(delta.InMicroseconds());
Expand Down Expand Up @@ -298,10 +325,19 @@ std::ostream& operator<<(std::ostream& os, Time time) {
exploded.millisecond);
}

// Static
// TimeTicks ------------------------------------------------------------------

// static
TimeTicks TimeTicks::Now() {
return internal::g_time_ticks_now_function();
}

// static
TimeTicks TimeTicks::UnixEpoch() {
static const base::NoDestructor<base::TimeTicks> epoch(
[]() { return TimeTicks::Now() - (Time::Now() - Time::UnixEpoch()); }());
static const base::NoDestructor<base::TimeTicks> epoch([]() {
return subtle::TimeTicksNowIgnoringOverride() -
(subtle::TimeNowIgnoringOverride() - Time::UnixEpoch());
}());
return *epoch;
}

Expand All @@ -328,6 +364,13 @@ std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
return os << as_time_delta.InMicroseconds() << " bogo-microseconds";
}

// ThreadTicks ----------------------------------------------------------------

// static
ThreadTicks ThreadTicks::Now() {
return internal::g_thread_ticks_now_function();
}

std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) {
const TimeDelta as_time_delta = thread_ticks - ThreadTicks();
return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds";
Expand Down
35 changes: 22 additions & 13 deletions base/time/time_fuchsia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "base/compiler_specific.h"
#include "base/numerics/checked_math.h"
#include "base/time/time_override.h"

namespace base {

Expand All @@ -25,28 +26,32 @@ ALWAYS_INLINE int64_t ZxTimeToMicroseconds(zx_time_t nanos) {

// Time -----------------------------------------------------------------------

// static
Time Time::Now() {
namespace subtle {
Time TimeNowIgnoringOverride() {
const zx_time_t nanos_since_unix_epoch = zx_time_get(ZX_CLOCK_UTC);
CHECK(nanos_since_unix_epoch != 0);
// The following expression will overflow in the year 289938 A.D.:
return Time(ZxTimeToMicroseconds(nanos_since_unix_epoch) +
kTimeTToMicrosecondsOffset);
return Time() + TimeDelta::FromMicroseconds(
ZxTimeToMicroseconds(nanos_since_unix_epoch) +
Time::kTimeTToMicrosecondsOffset);
}

// static
Time Time::NowFromSystemTime() {
return Now();
Time TimeNowFromSystemTimeIgnoringOverride() {
// Just use TimeNowIgnoringOverride() because it returns the system time.
return TimeNowIgnoringOverride();
}
} // namespace subtle

// TimeTicks ------------------------------------------------------------------

// static
TimeTicks TimeTicks::Now() {
namespace subtle {
TimeTicks TimeTicksNowIgnoringOverride() {
const zx_time_t nanos_since_boot = zx_time_get(ZX_CLOCK_MONOTONIC);
CHECK(nanos_since_boot != 0);
return TimeTicks(ZxTimeToMicroseconds(nanos_since_boot));
return TimeTicks() +
TimeDelta::FromMicroseconds(ZxTimeToMicroseconds(nanos_since_boot));
}
} // namespace subtle

// static
TimeTicks::Clock TimeTicks::GetClock() {
Expand Down Expand Up @@ -74,11 +79,15 @@ zx_time_t TimeTicks::ToZxTime() const {
return result.ValueOrDie();
}

// static
ThreadTicks ThreadTicks::Now() {
// ThreadTicks ----------------------------------------------------------------

namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
const zx_time_t nanos_since_thread_started = zx_time_get(ZX_CLOCK_THREAD);
CHECK(nanos_since_thread_started != 0);
return ThreadTicks(ZxTimeToMicroseconds(nanos_since_thread_started));
return ThreadTicks() + TimeDelta::FromMicroseconds(
ZxTimeToMicroseconds(nanos_since_thread_started));
}
} // namespace subtle

} // namespace base
40 changes: 23 additions & 17 deletions base/time/time_mac.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "base/mac/scoped_mach_port.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/time/time_override.h"
#include "build/build_config.h"

#if defined(OS_IOS)
Expand Down Expand Up @@ -81,8 +82,9 @@ int64_t ComputeCurrentTicks() {
int kr = sysctl(mib, arraysize(mib), &boottime, &size, nullptr, 0);
DCHECK_EQ(KERN_SUCCESS, kr);
base::TimeDelta time_difference =
base::Time::Now() - (base::Time::FromTimeT(boottime.tv_sec) +
base::TimeDelta::FromMicroseconds(boottime.tv_usec));
base::subtle::TimeNowIgnoringOverride() -
(base::Time::FromTimeT(boottime.tv_sec) +
base::TimeDelta::FromMicroseconds(boottime.tv_usec));
return time_difference.InMicroseconds();
#else
// mach_absolute_time is it when it comes to ticks on the Mac. Other calls
Expand Down Expand Up @@ -135,10 +137,16 @@ namespace base {

// Time -----------------------------------------------------------------------

// static
Time Time::Now() {
return FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent());
namespace subtle {
Time TimeNowIgnoringOverride() {
return Time::FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent());
}

Time TimeNowFromSystemTimeIgnoringOverride() {
// Just use TimeNowIgnoringOverride() because it returns the system time.
return TimeNowIgnoringOverride();
}
} // namespace subtle

// static
Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) {
Expand All @@ -165,12 +173,6 @@ CFAbsoluteTime Time::ToCFAbsoluteTime() const {
kCFAbsoluteTimeIntervalSince1970;
}

// static
Time Time::NowFromSystemTime() {
// Just use Now() because Now() returns the system time.
return Now();
}

// Note: These implementations of Time::FromExploded() and Time::Explode() are
// only used on iOS now. Since Mac is now always 64-bit, we can use the POSIX
// versions of these functions as time_t is not capped at year 2038 on 64-bit
Expand Down Expand Up @@ -269,10 +271,11 @@ void Time::Explode(bool is_local, Exploded* exploded) const {

// TimeTicks ------------------------------------------------------------------

// static
TimeTicks TimeTicks::Now() {
return TimeTicks(ComputeCurrentTicks());
namespace subtle {
TimeTicks TimeTicksNowIgnoringOverride() {
return TimeTicks() + TimeDelta::FromMicroseconds(ComputeCurrentTicks());
}
} // namespace subtle

// static
bool TimeTicks::IsHighResolution() {
Expand Down Expand Up @@ -300,9 +303,12 @@ TimeTicks::Clock TimeTicks::GetClock() {
#endif // defined(OS_IOS)
}

// static
ThreadTicks ThreadTicks::Now() {
return ThreadTicks(ComputeThreadTicks());
// ThreadTicks ----------------------------------------------------------------

namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
return ThreadTicks() + TimeDelta::FromMicroseconds(ComputeThreadTicks());
}
} // namespace subtle

} // namespace base
35 changes: 21 additions & 14 deletions base/time/time_now_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "base/logging.h"
#include "base/numerics/safe_math.h"
#include "base/time/time_override.h"
#include "build/build_config.h"

// Ensure the Fuchsia and Mac builds do not include this module. Instead,
Expand Down Expand Up @@ -62,30 +63,32 @@ namespace base {

// Time -----------------------------------------------------------------------

// static
Time Time::Now() {
namespace subtle {
Time TimeNowIgnoringOverride() {
struct timeval tv;
struct timezone tz = {0, 0}; // UTC
CHECK(gettimeofday(&tv, &tz) == 0);
// Combine seconds and microseconds in a 64-bit field containing microseconds
// since the epoch. That's enough for nearly 600 centuries. Adjust from
// Unix (1970) to Windows (1601) epoch.
return Time((tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec) +
kTimeTToMicrosecondsOffset);
return Time() + TimeDelta::FromMicroseconds(
(tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) +
Time::kTimeTToMicrosecondsOffset);
}

// static
Time Time::NowFromSystemTime() {
// Just use Now() because Now() returns the system time.
return Now();
Time TimeNowFromSystemTimeIgnoringOverride() {
// Just use TimeNowIgnoringOverride() because it returns the system time.
return TimeNowIgnoringOverride();
}
} // namespace subtle

// TimeTicks ------------------------------------------------------------------

// static
TimeTicks TimeTicks::Now() {
return TimeTicks(ClockNow(CLOCK_MONOTONIC));
namespace subtle {
TimeTicks TimeTicksNowIgnoringOverride() {
return TimeTicks() + TimeDelta::FromMicroseconds(ClockNow(CLOCK_MONOTONIC));
}
} // namespace subtle

// static
TimeTicks::Clock TimeTicks::GetClock() {
Expand All @@ -102,15 +105,19 @@ bool TimeTicks::IsConsistentAcrossProcesses() {
return true;
}

// static
ThreadTicks ThreadTicks::Now() {
// ThreadTicks ----------------------------------------------------------------

namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
defined(OS_ANDROID)
return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID));
return ThreadTicks() +
TimeDelta::FromMicroseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID));
#else
NOTREACHED();
return ThreadTicks();
#endif
}
} // namespace subtle

} // namespace base
45 changes: 45 additions & 0 deletions base/time/time_override.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/time/time_override.h"

namespace base {
namespace subtle {

#if DCHECK_IS_ON()
// static
bool ScopedTimeClockOverrides::overrides_active_ = false;
#endif

ScopedTimeClockOverrides::ScopedTimeClockOverrides(
TimeNowFunction time_override,
TimeTicksNowFunction time_ticks_override,
ThreadTicksNowFunction thread_ticks_override) {
#if DCHECK_IS_ON()
DCHECK(!overrides_active_);
overrides_active_ = true;
#endif
if (time_override) {
internal::g_time_now_function = time_override;
internal::g_time_now_from_system_time_function = time_override;
}
if (time_ticks_override)
internal::g_time_ticks_now_function = time_ticks_override;
if (thread_ticks_override)
internal::g_thread_ticks_now_function = thread_ticks_override;
}

ScopedTimeClockOverrides::~ScopedTimeClockOverrides() {
internal::g_time_now_function = &TimeNowIgnoringOverride;
internal::g_time_now_from_system_time_function =
&TimeNowFromSystemTimeIgnoringOverride;
internal::g_time_ticks_now_function = &TimeTicksNowIgnoringOverride;
internal::g_thread_ticks_now_function = &ThreadTicksNowIgnoringOverride;
#if DCHECK_IS_ON()
overrides_active_ = false;
#endif
}

} // namespace subtle
} // namespace base
Loading

0 comments on commit a936793

Please sign in to comment.