Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 14:04:28 +01:00
parent 81b91f4139
commit f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions

View file

@ -0,0 +1,4 @@
gab@chromium.org
miu@chromium.org
# COMPONENT: Internals>Core

View file

@ -0,0 +1,11 @@
// Copyright (c) 2012 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/clock.h"
namespace base {
Clock::~Clock() = default;
} // namespace base

View file

@ -0,0 +1,40 @@
// Copyright (c) 2012 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.
#ifndef BASE_TIME_CLOCK_H_
#define BASE_TIME_CLOCK_H_
#include "base/base_export.h"
#include "base/time/time.h"
namespace base {
// A Clock is an interface for objects that vend Times. It is
// intended to be able to test the behavior of classes with respect to
// time.
//
// See DefaultClock (base/time/default_clock.h) for the default
// implementation that simply uses Time::Now().
//
// (An implementation that uses Time::SystemTime() should be added as
// needed.)
//
// See SimpleTestClock (base/test/simple_test_clock.h) for a simple
// test implementation.
//
// See TickClock (base/time/tick_clock.h) for the equivalent interface for
// TimeTicks.
class BASE_EXPORT Clock {
public:
virtual ~Clock();
// Now() must be safe to call from any thread. The caller cannot
// make any ordering assumptions about the returned Time. For
// example, the system clock may change to an earlier time.
virtual Time Now() const = 0;
};
} // namespace base
#endif // BASE_TIME_CLOCK_H_

View file

@ -0,0 +1,23 @@
// Copyright (c) 2012 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/default_clock.h"
#include "base/no_destructor.h"
namespace base {
DefaultClock::~DefaultClock() = default;
Time DefaultClock::Now() const {
return Time::Now();
}
// static
DefaultClock* DefaultClock::GetInstance() {
static base::NoDestructor<DefaultClock> instance;
return instance.get();
}
} // namespace base

View file

@ -0,0 +1,28 @@
// Copyright (c) 2012 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.
#ifndef BASE_TIME_DEFAULT_CLOCK_H_
#define BASE_TIME_DEFAULT_CLOCK_H_
#include "base/base_export.h"
#include "base/compiler_specific.h"
#include "base/time/clock.h"
namespace base {
// DefaultClock is a Clock implementation that uses Time::Now().
class BASE_EXPORT DefaultClock : public Clock {
public:
~DefaultClock() override;
// Simply returns Time::Now().
Time Now() const override;
// Returns a shared instance of DefaultClock. This is thread-safe.
static DefaultClock* GetInstance();
};
} // namespace base
#endif // BASE_TIME_DEFAULT_CLOCK_H_

View file

@ -0,0 +1,23 @@
// Copyright (c) 2012 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/default_tick_clock.h"
#include "base/no_destructor.h"
namespace base {
DefaultTickClock::~DefaultTickClock() = default;
TimeTicks DefaultTickClock::NowTicks() const {
return TimeTicks::Now();
}
// static
const DefaultTickClock* DefaultTickClock::GetInstance() {
static const base::NoDestructor<DefaultTickClock> default_tick_clock;
return default_tick_clock.get();
}
} // namespace base

View file

@ -0,0 +1,32 @@
// Copyright (c) 2012 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.
#ifndef BASE_TIME_DEFAULT_TICK_CLOCK_H_
#define BASE_TIME_DEFAULT_TICK_CLOCK_H_
#include "base/base_export.h"
#include "base/time/tick_clock.h"
namespace base {
// DefaultTickClock is a TickClock implementation that uses TimeTicks::Now().
// This is typically used by components that expose a SetTickClockForTesting().
// Note: Overriding Time/TimeTicks altogether via
// TaskEnvironment::TimeSource::MOCK_TIME is now the preferred of
// overriding time in unit tests. As such, there shouldn't be many new use cases
// for TickClock/DefaultTickClock anymore.
class BASE_EXPORT DefaultTickClock : public TickClock {
public:
~DefaultTickClock() override;
// Simply returns TimeTicks::Now().
TimeTicks NowTicks() const override;
// Returns a shared instance of DefaultTickClock. This is thread-safe.
static const DefaultTickClock* GetInstance();
};
} // namespace base
#endif // BASE_TIME_DEFAULT_TICK_CLOCK_H_

View file

@ -0,0 +1,11 @@
// Copyright (c) 2012 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/tick_clock.h"
namespace base {
TickClock::~TickClock() = default;
} // namespace base

View file

@ -0,0 +1,40 @@
// Copyright (c) 2012 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.
#ifndef BASE_TIME_TICK_CLOCK_H_
#define BASE_TIME_TICK_CLOCK_H_
#include "base/base_export.h"
#include "base/time/time.h"
namespace base {
// A TickClock is an interface for objects that vend TimeTicks. It is
// intended to be able to test the behavior of classes with respect to
// non-decreasing time.
//
// See DefaultTickClock (base/time/default_tick_clock.h) for the default
// implementation that simply uses TimeTicks::Now().
//
// (Other implementations that use TimeTicks::NowFromSystemTime() should
// be added as needed.)
//
// See SimpleTestTickClock (base/test/simple_test_tick_clock.h) for a
// simple test implementation.
//
// See Clock (base/time/clock.h) for the equivalent interface for Times.
class BASE_EXPORT TickClock {
public:
virtual ~TickClock();
// NowTicks() must be safe to call from any thread. The caller may
// assume that NowTicks() is monotonic (but not strictly monotonic).
// In other words, the returned TimeTicks will never decrease with
// time, although they might "stand still".
virtual TimeTicks NowTicks() const = 0;
};
} // namespace base
#endif // BASE_TIME_TICK_CLOCK_H_

View file

@ -0,0 +1,490 @@
// Copyright (c) 2012 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.h"
#include <cmath>
#include <ios>
#include <limits>
#include <ostream>
#include <sstream>
#include "base/logging.h"
#include "base/macros.h"
#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 {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<int>::max();
}
if (is_min()) {
// Preserve min to prevent underflow.
return std::numeric_limits<int>::min();
}
return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
}
int TimeDelta::InDaysFloored() const {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<int>::max();
}
if (is_min()) {
// Preserve min to prevent underflow.
return std::numeric_limits<int>::min();
}
int result = delta_ / Time::kMicrosecondsPerDay;
int64_t remainder = delta_ - (result * Time::kMicrosecondsPerDay);
if (remainder < 0) {
--result; // Use floor(), not trunc() rounding behavior.
}
return result;
}
int TimeDelta::InHours() const {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<int>::max();
}
if (is_min()) {
// Preserve min to prevent underflow.
return std::numeric_limits<int>::min();
}
return static_cast<int>(delta_ / Time::kMicrosecondsPerHour);
}
int TimeDelta::InMinutes() const {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<int>::max();
}
if (is_min()) {
// Preserve min to prevent underflow.
return std::numeric_limits<int>::min();
}
return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute);
}
double TimeDelta::InSecondsF() const {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<double>::infinity();
}
if (is_min()) {
// Preserve min to prevent underflow.
return -std::numeric_limits<double>::infinity();
}
return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
}
int64_t TimeDelta::InSeconds() const {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<int64_t>::max();
}
if (is_min()) {
// Preserve min to prevent underflow.
return std::numeric_limits<int64_t>::min();
}
return delta_ / Time::kMicrosecondsPerSecond;
}
double TimeDelta::InMillisecondsF() const {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<double>::infinity();
}
if (is_min()) {
// Preserve min to prevent underflow.
return -std::numeric_limits<double>::infinity();
}
return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
}
int64_t TimeDelta::InMilliseconds() const {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<int64_t>::max();
}
if (is_min()) {
// Preserve min to prevent underflow.
return std::numeric_limits<int64_t>::min();
}
return delta_ / Time::kMicrosecondsPerMillisecond;
}
int64_t TimeDelta::InMillisecondsRoundedUp() const {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<int64_t>::max();
}
if (is_min()) {
// Preserve min to prevent underflow.
return std::numeric_limits<int64_t>::min();
}
int64_t result = delta_ / Time::kMicrosecondsPerMillisecond;
int64_t remainder = delta_ - (result * Time::kMicrosecondsPerMillisecond);
if (remainder > 0) {
++result; // Use ceil(), not trunc() rounding behavior.
}
return result;
}
double TimeDelta::InMicrosecondsF() const {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<double>::infinity();
}
if (is_min()) {
// Preserve min to prevent underflow.
return -std::numeric_limits<double>::infinity();
}
return static_cast<double>(delta_);
}
int64_t TimeDelta::InNanoseconds() const {
if (is_max()) {
// Preserve max to prevent overflow.
return std::numeric_limits<int64_t>::max();
}
if (is_min()) {
// Preserve min to prevent underflow.
return std::numeric_limits<int64_t>::min();
}
return delta_ * Time::kNanosecondsPerMicrosecond;
}
std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) {
return os << time_delta.InSecondsF() << " s";
}
// 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());
}
TimeDelta Time::ToDeltaSinceWindowsEpoch() const {
return TimeDelta::FromMicroseconds(us_);
}
// static
Time Time::FromTimeT(time_t tt) {
if (tt == 0)
return Time(); // Preserve 0 so we can tell it doesn't exist.
if (tt == std::numeric_limits<time_t>::max())
return Max();
return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSeconds(tt);
}
time_t Time::ToTimeT() const {
if (is_null())
return 0; // Preserve 0 so we can tell it doesn't exist.
if (is_max()) {
// Preserve max without offset to prevent overflow.
return std::numeric_limits<time_t>::max();
}
if (is_min()) {
// Preserve min without offset to prevent underflow.
return std::numeric_limits<time_t>::min();
}
if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) {
DLOG(WARNING) << "Overflow when converting base::Time with internal " <<
"value " << us_ << " to time_t.";
return std::numeric_limits<time_t>::max();
}
return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond;
}
// static
Time Time::FromDoubleT(double dt) {
if (dt == 0 || std::isnan(dt))
return Time(); // Preserve 0 so we can tell it doesn't exist.
return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSecondsD(dt);
}
double Time::ToDoubleT() const {
if (is_null())
return 0; // Preserve 0 so we can tell it doesn't exist.
if (is_max()) {
// Preserve max without offset to prevent overflow.
return std::numeric_limits<double>::infinity();
}
if (is_min()) {
// Preserve min without offset to prevent underflow.
return -std::numeric_limits<double>::infinity();
}
return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
static_cast<double>(kMicrosecondsPerSecond));
}
#if defined(OS_POSIX)
// static
Time Time::FromTimeSpec(const timespec& ts) {
return FromDoubleT(ts.tv_sec +
static_cast<double>(ts.tv_nsec) /
base::Time::kNanosecondsPerSecond);
}
#endif
// static
Time Time::FromJsTime(double ms_since_epoch) {
// The epoch is a valid time, so this constructor doesn't interpret
// 0 as the null time.
return Time(kTimeTToMicrosecondsOffset) +
TimeDelta::FromMillisecondsD(ms_since_epoch);
}
double Time::ToJsTime() const {
if (is_null()) {
// Preserve 0 so the invalid result doesn't depend on the platform.
return 0;
}
return ToJsTimeIgnoringNull();
}
double Time::ToJsTimeIgnoringNull() const {
if (is_max()) {
// Preserve max without offset to prevent overflow.
return std::numeric_limits<double>::infinity();
}
if (is_min()) {
// Preserve min without offset to prevent underflow.
return -std::numeric_limits<double>::infinity();
}
return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
kMicrosecondsPerMillisecond);
}
Time Time::FromJavaTime(int64_t ms_since_epoch) {
return base::Time::UnixEpoch() +
base::TimeDelta::FromMilliseconds(ms_since_epoch);
}
int64_t Time::ToJavaTime() const {
if (is_null()) {
// Preserve 0 so the invalid result doesn't depend on the platform.
return 0;
}
if (is_max()) {
// Preserve max without offset to prevent overflow.
return std::numeric_limits<int64_t>::max();
}
if (is_min()) {
// Preserve min without offset to prevent underflow.
return std::numeric_limits<int64_t>::min();
}
return ((us_ - kTimeTToMicrosecondsOffset) /
kMicrosecondsPerMillisecond);
}
// static
Time Time::UnixEpoch() {
Time time;
time.us_ = kTimeTToMicrosecondsOffset;
return time;
}
Time Time::Midnight(bool is_local) const {
Exploded exploded;
Explode(is_local, &exploded);
exploded.hour = 0;
exploded.minute = 0;
exploded.second = 0;
exploded.millisecond = 0;
Time out_time;
if (FromExploded(is_local, exploded, &out_time)) {
return out_time;
} else if (is_local) {
// Hitting this branch means 00:00:00am of the current day
// does not exist (due to Daylight Saving Time in some countries
// where clocks are shifted at midnight). In this case, midnight
// should be defined as 01:00:00am.
exploded.hour = 1;
if (FromExploded(is_local, exploded, &out_time))
return out_time;
}
// This function must not fail.
NOTREACHED();
return Time();
}
// static
bool Time::FromStringInternal(const char* time_string,
bool is_local,
Time* parsed_time) {
DCHECK((time_string != nullptr) && (parsed_time != nullptr));
if (time_string[0] == '\0')
return false;
PRTime result_time = 0;
PRStatus result = PR_ParseTimeString(time_string,
is_local ? PR_FALSE : PR_TRUE,
&result_time);
if (PR_SUCCESS != result)
return false;
result_time += kTimeTToMicrosecondsOffset;
*parsed_time = Time(result_time);
return true;
}
// static
bool Time::ExplodedMostlyEquals(const Exploded& lhs, const Exploded& rhs) {
return lhs.year == rhs.year && lhs.month == rhs.month &&
lhs.day_of_month == rhs.day_of_month && lhs.hour == rhs.hour &&
lhs.minute == rhs.minute && lhs.second == rhs.second &&
lhs.millisecond == rhs.millisecond;
}
// static
bool Time::FromMillisecondsSinceUnixEpoch(int64_t unix_milliseconds,
Time* time) {
// Adjust the provided time from milliseconds since the Unix epoch (1970) to
// microseconds since the Windows epoch (1601), avoiding overflows.
base::CheckedNumeric<int64_t> checked_microseconds_win_epoch =
unix_milliseconds;
checked_microseconds_win_epoch *= kMicrosecondsPerMillisecond;
checked_microseconds_win_epoch += kTimeTToMicrosecondsOffset;
if (!checked_microseconds_win_epoch.IsValid()) {
*time = base::Time(0);
return false;
}
*time = Time(checked_microseconds_win_epoch.ValueOrDie());
return true;
}
int64_t Time::ToRoundedDownMillisecondsSinceUnixEpoch() const {
// Adjust from Windows epoch (1601) to Unix epoch (1970).
int64_t microseconds = us_ - kTimeTToMicrosecondsOffset;
// Round the microseconds towards -infinity.
if (microseconds >= 0) {
// In this case, rounding towards -infinity means rounding towards 0.
return microseconds / kMicrosecondsPerMillisecond;
} else {
return (microseconds + 1) / kMicrosecondsPerMillisecond - 1;
}
}
std::ostream& operator<<(std::ostream& os, Time time) {
Time::Exploded exploded;
time.UTCExplode(&exploded);
// Use StringPrintf because iostreams formatting is painful.
return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC",
exploded.year,
exploded.month,
exploded.day_of_month,
exploded.hour,
exploded.minute,
exploded.second,
exploded.millisecond);
}
// TimeTicks ------------------------------------------------------------------
// static
TimeTicks TimeTicks::Now() {
return internal::g_time_ticks_now_function();
}
// static
TimeTicks TimeTicks::UnixEpoch() {
static const base::NoDestructor<base::TimeTicks> epoch([]() {
return subtle::TimeTicksNowIgnoringOverride() -
(subtle::TimeNowIgnoringOverride() - Time::UnixEpoch());
}());
return *epoch;
}
TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
TimeDelta tick_interval) const {
// |interval_offset| is the offset from |this| to the next multiple of
// |tick_interval| after |tick_phase|, possibly negative if in the past.
TimeDelta interval_offset = (tick_phase - *this) % tick_interval;
// If |this| is exactly on the interval (i.e. offset==0), don't adjust.
// Otherwise, if |tick_phase| was in the past, adjust forward to the next
// tick after |this|.
if (!interval_offset.is_zero() && tick_phase < *this)
interval_offset += tick_interval;
return *this + interval_offset;
}
std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
// This function formats a TimeTicks object as "bogo-microseconds".
// The origin and granularity of the count are platform-specific, and may very
// from run to run. Although bogo-microseconds usually roughly correspond to
// real microseconds, the only real guarantee is that the number never goes
// down during a single run.
const TimeDelta as_time_delta = time_ticks - TimeTicks();
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";
}
// Time::Exploded -------------------------------------------------------------
inline bool is_in_range(int value, int lo, int hi) {
return lo <= value && value <= hi;
}
bool Time::Exploded::HasValidValues() const {
return is_in_range(month, 1, 12) &&
is_in_range(day_of_week, 0, 6) &&
is_in_range(day_of_month, 1, 31) &&
is_in_range(hour, 0, 23) &&
is_in_range(minute, 0, 59) &&
is_in_range(second, 0, 60) &&
is_in_range(millisecond, 0, 999);
}
} // namespace base

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,26 @@
// 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.h"
namespace base {
// static
TimeTicks TimeTicks::FromUptimeMillis(int64_t uptime_millis_value) {
// The implementation of the SystemClock.uptimeMillis() in AOSP uses the same
// clock as base::TimeTicks::Now(): clock_gettime(CLOCK_MONOTONIC), see in
// platform/system/code:
// 1. libutils/SystemClock.cpp
// 2. libutils/Timers.cpp
//
// We are not aware of any motivations for Android OEMs to modify the AOSP
// implementation of either uptimeMillis() or clock_gettime(CLOCK_MONOTONIC),
// so we assume that there are no such customizations.
//
// Under these assumptions the conversion is as safe as copying the value of
// base::TimeTicks::Now() with a loss of sub-millisecond precision.
return TimeTicks(uptime_millis_value * Time::kMicrosecondsPerMillisecond);
}
} // namespace base

View file

@ -0,0 +1,67 @@
// Copyright (c) 2012 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.h"
#include <stdint.h>
#include <sys/time.h>
#include <time.h>
#include <limits>
#include "base/logging.h"
namespace base {
// static
TimeDelta TimeDelta::FromTimeSpec(const timespec& ts) {
return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond +
ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
}
struct timespec TimeDelta::ToTimeSpec() const {
int64_t microseconds = InMicroseconds();
time_t seconds = 0;
if (microseconds >= Time::kMicrosecondsPerSecond) {
seconds = InSeconds();
microseconds -= seconds * Time::kMicrosecondsPerSecond;
}
struct timespec result = {
seconds,
static_cast<long>(microseconds * Time::kNanosecondsPerMicrosecond)};
return result;
}
// static
Time Time::FromTimeVal(struct timeval t) {
DCHECK_LT(t.tv_usec, static_cast<int>(Time::kMicrosecondsPerSecond));
DCHECK_GE(t.tv_usec, 0);
if (t.tv_usec == 0 && t.tv_sec == 0)
return Time();
if (t.tv_usec == static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1 &&
t.tv_sec == std::numeric_limits<time_t>::max())
return Max();
return Time((static_cast<int64_t>(t.tv_sec) * Time::kMicrosecondsPerSecond) +
t.tv_usec + kTimeTToMicrosecondsOffset);
}
struct timeval Time::ToTimeVal() const {
struct timeval result;
if (is_null()) {
result.tv_sec = 0;
result.tv_usec = 0;
return result;
}
if (is_max()) {
result.tv_sec = std::numeric_limits<time_t>::max();
result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1;
return result;
}
int64_t us = us_ - kTimeTToMicrosecondsOffset;
result.tv_sec = us / Time::kMicrosecondsPerSecond;
result.tv_usec = us % Time::kMicrosecondsPerSecond;
return result;
}
} // namespace base

View file

@ -0,0 +1,96 @@
// Copyright 2019 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.h"
#include <memory>
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "third_party/icu/source/i18n/unicode/calendar.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
namespace base {
static_assert(
sizeof(Time::Exploded::year) == sizeof(int32_t),
"The sizes of Time::Exploded members and ICU date fields do not match.");
namespace {
// Returns a new icu::Calendar instance for the local time zone if |is_local|
// and for GMT otherwise. Returns null on error.
std::unique_ptr<icu::Calendar> CreateCalendar(bool is_local) {
UErrorCode status = U_ZERO_ERROR;
std::unique_ptr<icu::Calendar> calendar =
base::WrapUnique(is_local ? icu::Calendar::createInstance(status)
: icu::Calendar::createInstance(
*icu::TimeZone::getGMT(), status));
CHECK(U_SUCCESS(status));
return calendar;
}
} // namespace
void Time::Explode(bool is_local, Exploded* exploded) const {
std::unique_ptr<icu::Calendar> calendar = CreateCalendar(is_local);
UErrorCode status = U_ZERO_ERROR;
calendar->setTime(ToRoundedDownMillisecondsSinceUnixEpoch(), status);
DCHECK(U_SUCCESS(status));
exploded->year = calendar->get(UCAL_YEAR, status);
DCHECK(U_SUCCESS(status));
// ICU's UCalendarMonths is 0-based. E.g., 0 for January.
exploded->month = calendar->get(UCAL_MONTH, status) + 1;
DCHECK(U_SUCCESS(status));
// ICU's UCalendarDaysOfWeek is 1-based. E.g., 1 for Sunday.
exploded->day_of_week = calendar->get(UCAL_DAY_OF_WEEK, status) - 1;
DCHECK(U_SUCCESS(status));
exploded->day_of_month = calendar->get(UCAL_DAY_OF_MONTH, status);
DCHECK(U_SUCCESS(status));
exploded->hour = calendar->get(UCAL_HOUR_OF_DAY, status);
DCHECK(U_SUCCESS(status));
exploded->minute = calendar->get(UCAL_MINUTE, status);
DCHECK(U_SUCCESS(status));
exploded->second = calendar->get(UCAL_SECOND, status);
DCHECK(U_SUCCESS(status));
exploded->millisecond = calendar->get(UCAL_MILLISECOND, status);
DCHECK(U_SUCCESS(status));
}
// static
bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
// ICU's UCalendarMonths is 0-based. E.g., 0 for January.
CheckedNumeric<int> month = exploded.month;
month--;
if (!month.IsValid()) {
*time = Time(0);
return false;
}
std::unique_ptr<icu::Calendar> calendar = CreateCalendar(is_local);
// Cause getTime() to report an error if invalid dates, such as the 31st day
// of February, are specified.
calendar->setLenient(false);
calendar->set(exploded.year, month.ValueOrDie(), exploded.day_of_month,
exploded.hour, exploded.minute, exploded.second);
calendar->set(UCAL_MILLISECOND, exploded.millisecond);
// Ignore exploded.day_of_week
UErrorCode status = U_ZERO_ERROR;
UDate date = calendar->getTime(status);
if (U_FAILURE(status)) {
*time = Time(0);
return false;
}
return FromMillisecondsSinceUnixEpoch(date, time);
}
} // namespace base

View file

@ -0,0 +1,113 @@
// Copyright (c) 2019 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.h"
#include <CoreFoundation/CFDate.h>
#include <CoreFoundation/CFCalendar.h>
#include <CoreFoundation/CFTimeZone.h>
#include "base/mac/scoped_cftyperef.h"
#if __LP64__
#error Use posix implementation on 64-bit platforms.
#endif // __LP64__
namespace base {
// 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
// builds. The POSIX functions are preferred since they don't suffer from some
// performance problems that are present in these implementations.
// See crbug.com/781601, crbug.com/985061 for more details.
// static
bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
base::ScopedCFTypeRef<CFTimeZoneRef> time_zone(
is_local
? CFTimeZoneCopySystem()
: CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0));
base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier(
kCFAllocatorDefault, kCFGregorianCalendar));
CFCalendarSetTimeZone(gregorian, time_zone);
CFAbsoluteTime absolute_time;
// 'S' is not defined in componentDesc in Apple documentation, but can be
// found at http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c
CFCalendarComposeAbsoluteTime(
gregorian, &absolute_time, "yMdHmsS", exploded.year, exploded.month,
exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
exploded.millisecond);
CFAbsoluteTime seconds = absolute_time + kCFAbsoluteTimeIntervalSince1970;
// CFAbsolutTime is typedef of double. Convert seconds to
// microseconds and then cast to int64. If
// it cannot be suited to int64, then fail to avoid overflows.
double microseconds =
(seconds * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset;
if (microseconds > std::numeric_limits<int64_t>::max() ||
microseconds < std::numeric_limits<int64_t>::min()) {
*time = Time(0);
return false;
}
base::Time converted_time = Time(static_cast<int64_t>(microseconds));
// If |exploded.day_of_month| is set to 31
// on a 28-30 day month, it will return the first day of the next month.
// Thus round-trip the time and compare the initial |exploded| with
// |utc_to_exploded| time.
base::Time::Exploded to_exploded;
if (!is_local)
converted_time.UTCExplode(&to_exploded);
else
converted_time.LocalExplode(&to_exploded);
if (ExplodedMostlyEquals(to_exploded, exploded)) {
*time = converted_time;
return true;
}
*time = Time(0);
return false;
}
void Time::Explode(bool is_local, Exploded* exploded) const {
// Avoid rounding issues, by only putting the integral number of seconds
// (rounded towards -infinity) into a |CFAbsoluteTime| (which is a |double|).
int64_t microsecond = us_ % kMicrosecondsPerSecond;
if (microsecond < 0)
microsecond += kMicrosecondsPerSecond;
CFAbsoluteTime seconds = ((us_ - microsecond - kTimeTToMicrosecondsOffset) /
kMicrosecondsPerSecond) -
kCFAbsoluteTimeIntervalSince1970;
base::ScopedCFTypeRef<CFTimeZoneRef> time_zone(
is_local
? CFTimeZoneCopySystem()
: CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0));
base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier(
kCFAllocatorDefault, kCFGregorianCalendar));
CFCalendarSetTimeZone(gregorian, time_zone);
int second, day_of_week;
// 'E' sets the day of week, but is not defined in componentDesc in Apple
// documentation. It can be found in open source code here:
// http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c
CFCalendarDecomposeAbsoluteTime(gregorian, seconds, "yMdHmsE",
&exploded->year, &exploded->month,
&exploded->day_of_month, &exploded->hour,
&exploded->minute, &second, &day_of_week);
// Make sure seconds are rounded down towards -infinity.
exploded->second = floor(second);
// |Exploded|'s convention for day of week is 0 = Sunday, i.e. different
// from CF's 1 = Sunday.
exploded->day_of_week = (day_of_week - 1) % 7;
// Calculate milliseconds ourselves, since we rounded the |seconds|, making
// sure to round towards -infinity.
exploded->millisecond =
(microsecond >= 0) ? microsecond / kMicrosecondsPerMillisecond
: ((microsecond + 1) / kMicrosecondsPerMillisecond - 1);
}
} // namespace base

View file

@ -0,0 +1,286 @@
// Copyright (c) 2012 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.h"
#include <stdint.h>
#include <sys/time.h>
#include <time.h>
#if defined(OS_ANDROID) && !defined(__LP64__)
#include <time64.h>
#endif
#include <unistd.h>
#include <limits>
#include "base/numerics/safe_math.h"
#include "base/synchronization/lock.h"
#include "build/build_config.h"
#if defined(OS_ANDROID)
#include "base/os_compat_android.h"
#elif defined(OS_NACL)
#include "base/os_compat_nacl.h"
#endif
#if defined(OS_MACOSX) || defined(OS_IOS)
static_assert(sizeof(time_t) >= 8, "Y2038 problem!");
#endif
namespace {
// This prevents a crash on traversing the environment global and looking up
// the 'TZ' variable in libc. See: crbug.com/390567.
base::Lock* GetSysTimeToTimeStructLock() {
static auto* lock = new base::Lock();
return lock;
}
// Define a system-specific SysTime that wraps either to a time_t or
// a time64_t depending on the host system, and associated convertion.
// See crbug.com/162007
#if defined(OS_ANDROID) && !defined(__LP64__)
typedef time64_t SysTime;
SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
base::AutoLock locked(*GetSysTimeToTimeStructLock());
if (is_local)
return mktime64(timestruct);
else
return timegm64(timestruct);
}
void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
base::AutoLock locked(*GetSysTimeToTimeStructLock());
if (is_local)
localtime64_r(&t, timestruct);
else
gmtime64_r(&t, timestruct);
}
#elif defined(OS_AIX)
// The function timegm is not available on AIX.
time_t aix_timegm(struct tm* tm) {
time_t ret;
char* tz;
tz = getenv("TZ");
if (tz) {
tz = strdup(tz);
}
setenv("TZ", "GMT0", 1);
tzset();
ret = mktime(tm);
if (tz) {
setenv("TZ", tz, 1);
free(tz);
} else {
unsetenv("TZ");
}
tzset();
return ret;
}
typedef time_t SysTime;
SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
base::AutoLock locked(*GetSysTimeToTimeStructLock());
if (is_local)
return mktime(timestruct);
else
return aix_timegm(timestruct);
}
void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
base::AutoLock locked(*GetSysTimeToTimeStructLock());
if (is_local)
localtime_r(&t, timestruct);
else
gmtime_r(&t, timestruct);
}
#else
typedef time_t SysTime;
SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
base::AutoLock locked(*GetSysTimeToTimeStructLock());
return is_local ? mktime(timestruct) : timegm(timestruct);
}
void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
base::AutoLock locked(*GetSysTimeToTimeStructLock());
if (is_local)
localtime_r(&t, timestruct);
else
gmtime_r(&t, timestruct);
}
#endif // defined(OS_ANDROID) && !defined(__LP64__)
} // namespace
namespace base {
void Time::Explode(bool is_local, Exploded* exploded) const {
// The following values are all rounded towards -infinity.
int64_t milliseconds = ToRoundedDownMillisecondsSinceUnixEpoch();
SysTime seconds; // Seconds since epoch.
int millisecond; // Exploded millisecond value (0-999).
// If the microseconds were negative, the rounded down milliseconds will also
// be negative. For example, -1 us becomes -1 ms.
if (milliseconds >= 0) {
// Rounding towards -infinity <=> rounding towards 0, in this case.
seconds = milliseconds / kMillisecondsPerSecond;
millisecond = milliseconds % kMillisecondsPerSecond;
} else {
// Round these *down* (towards -infinity).
seconds = (milliseconds + 1) / kMillisecondsPerSecond - 1;
// Make this nonnegative (and between 0 and 999 inclusive).
millisecond = milliseconds % kMillisecondsPerSecond;
if (millisecond < 0)
millisecond += kMillisecondsPerSecond;
}
struct tm timestruct;
SysTimeToTimeStruct(seconds, &timestruct, is_local);
exploded->year = timestruct.tm_year + 1900;
exploded->month = timestruct.tm_mon + 1;
exploded->day_of_week = timestruct.tm_wday;
exploded->day_of_month = timestruct.tm_mday;
exploded->hour = timestruct.tm_hour;
exploded->minute = timestruct.tm_min;
exploded->second = timestruct.tm_sec;
exploded->millisecond = millisecond;
}
// static
bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
CheckedNumeric<int> month = exploded.month;
month--;
CheckedNumeric<int> year = exploded.year;
year -= 1900;
if (!month.IsValid() || !year.IsValid()) {
*time = Time(0);
return false;
}
struct tm timestruct;
timestruct.tm_sec = exploded.second;
timestruct.tm_min = exploded.minute;
timestruct.tm_hour = exploded.hour;
timestruct.tm_mday = exploded.day_of_month;
timestruct.tm_mon = month.ValueOrDie();
timestruct.tm_year = year.ValueOrDie();
timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this
timestruct.tm_yday = 0; // mktime/timegm ignore this
timestruct.tm_isdst = -1; // attempt to figure it out
#if !defined(OS_NACL) && !defined(OS_SOLARIS) && !defined(OS_AIX)
timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore
timestruct.tm_zone = nullptr; // not a POSIX field, so mktime/timegm ignore
#endif
SysTime seconds;
// Certain exploded dates do not really exist due to daylight saving times,
// and this causes mktime() to return implementation-defined values when
// tm_isdst is set to -1. On Android, the function will return -1, while the
// C libraries of other platforms typically return a liberally-chosen value.
// Handling this requires the special code below.
// SysTimeFromTimeStruct() modifies the input structure, save current value.
struct tm timestruct0 = timestruct;
seconds = SysTimeFromTimeStruct(&timestruct, is_local);
if (seconds == -1) {
// Get the time values with tm_isdst == 0 and 1, then select the closest one
// to UTC 00:00:00 that isn't -1.
timestruct = timestruct0;
timestruct.tm_isdst = 0;
int64_t seconds_isdst0 = SysTimeFromTimeStruct(&timestruct, is_local);
timestruct = timestruct0;
timestruct.tm_isdst = 1;
int64_t seconds_isdst1 = SysTimeFromTimeStruct(&timestruct, is_local);
// seconds_isdst0 or seconds_isdst1 can be -1 for some timezones.
// E.g. "CLST" (Chile Summer Time) returns -1 for 'tm_isdt == 1'.
if (seconds_isdst0 < 0)
seconds = seconds_isdst1;
else if (seconds_isdst1 < 0)
seconds = seconds_isdst0;
else
seconds = std::min(seconds_isdst0, seconds_isdst1);
}
// Handle overflow. Clamping the range to what mktime and timegm might
// return is the best that can be done here. It's not ideal, but it's better
// than failing here or ignoring the overflow case and treating each time
// overflow as one second prior to the epoch.
int64_t milliseconds = 0;
if (seconds == -1 && (exploded.year < 1969 || exploded.year > 1970)) {
// If exploded.year is 1969 or 1970, take -1 as correct, with the
// time indicating 1 second prior to the epoch. (1970 is allowed to handle
// time zone and DST offsets.) Otherwise, return the most future or past
// time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC.
//
// The minimum and maximum representible times that mktime and timegm could
// return are used here instead of values outside that range to allow for
// proper round-tripping between exploded and counter-type time
// representations in the presence of possible truncation to time_t by
// division and use with other functions that accept time_t.
//
// When representing the most distant time in the future, add in an extra
// 999ms to avoid the time being less than any other possible value that
// this function can return.
// On Android, SysTime is int64_t, special care must be taken to avoid
// overflows.
const int64_t min_seconds = (sizeof(SysTime) < sizeof(int64_t))
? std::numeric_limits<SysTime>::min()
: std::numeric_limits<int32_t>::min();
const int64_t max_seconds = (sizeof(SysTime) < sizeof(int64_t))
? std::numeric_limits<SysTime>::max()
: std::numeric_limits<int32_t>::max();
if (exploded.year < 1969) {
milliseconds = min_seconds * kMillisecondsPerSecond;
} else {
milliseconds = max_seconds * kMillisecondsPerSecond;
milliseconds += (kMillisecondsPerSecond - 1);
}
} else {
CheckedNumeric<int64_t> checked_millis = seconds;
checked_millis *= kMillisecondsPerSecond;
checked_millis += exploded.millisecond;
if (!checked_millis.IsValid()) {
*time = Time(0);
return false;
}
milliseconds = checked_millis.ValueOrDie();
}
Time converted_time;
if (!FromMillisecondsSinceUnixEpoch(milliseconds, &converted_time)) {
*time = base::Time(0);
return false;
}
// If |exploded.day_of_month| is set to 31 on a 28-30 day month, it will
// return the first day of the next month. Thus round-trip the time and
// compare the initial |exploded| with |utc_to_exploded| time.
Time::Exploded to_exploded;
if (!is_local)
converted_time.UTCExplode(&to_exploded);
else
converted_time.LocalExplode(&to_exploded);
if (ExplodedMostlyEquals(to_exploded, exploded)) {
*time = converted_time;
return true;
}
*time = Time(0);
return false;
}
} // namespace base

View file

@ -0,0 +1,96 @@
// Copyright 2017 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.h"
#include <zircon/syscalls.h>
#include "base/fuchsia/fuchsia_logging.h"
#include "base/time/time_override.h"
namespace base {
// Time -----------------------------------------------------------------------
namespace subtle {
Time TimeNowIgnoringOverride() {
zx_time_t nanos_since_unix_epoch;
zx_status_t status = zx_clock_get(ZX_CLOCK_UTC, &nanos_since_unix_epoch);
ZX_CHECK(status == ZX_OK, status);
// The following expression will overflow in the year 289938 A.D.:
return Time::FromZxTime(nanos_since_unix_epoch);
}
Time TimeNowFromSystemTimeIgnoringOverride() {
// Just use TimeNowIgnoringOverride() because it returns the system time.
return TimeNowIgnoringOverride();
}
} // namespace subtle
// TimeTicks ------------------------------------------------------------------
namespace subtle {
TimeTicks TimeTicksNowIgnoringOverride() {
const zx_time_t nanos_since_boot = zx_clock_get_monotonic();
CHECK(nanos_since_boot != 0);
return TimeTicks::FromZxTime(nanos_since_boot);
}
} // namespace subtle
// static
TimeDelta TimeDelta::FromZxDuration(zx_duration_t nanos) {
return TimeDelta::FromNanoseconds(nanos);
}
zx_duration_t TimeDelta::ToZxDuration() const {
return InNanoseconds();
}
// static
Time Time::FromZxTime(zx_time_t nanos_since_unix_epoch) {
return Time::UnixEpoch() + TimeDelta::FromNanoseconds(nanos_since_unix_epoch);
}
zx_time_t Time::ToZxTime() const {
return (*this - Time::UnixEpoch()).InNanoseconds();
}
// static
TimeTicks::Clock TimeTicks::GetClock() {
return Clock::FUCHSIA_ZX_CLOCK_MONOTONIC;
}
// static
bool TimeTicks::IsHighResolution() {
return true;
}
// static
bool TimeTicks::IsConsistentAcrossProcesses() {
return true;
}
// static
TimeTicks TimeTicks::FromZxTime(zx_time_t nanos_since_boot) {
return TimeTicks() + TimeDelta::FromNanoseconds(nanos_since_boot);
}
zx_time_t TimeTicks::ToZxTime() const {
return (*this - TimeTicks()).InNanoseconds();
}
// ThreadTicks ----------------------------------------------------------------
namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
zx_time_t nanos_since_thread_started;
zx_status_t status =
zx_clock_get(ZX_CLOCK_THREAD, &nanos_since_thread_started);
ZX_CHECK(status == ZX_OK, status);
DCHECK(nanos_since_thread_started != 0);
return ThreadTicks() + TimeDelta::FromNanoseconds(nanos_since_thread_started);
}
} // namespace subtle
} // namespace base

View file

@ -0,0 +1,219 @@
// Copyright (c) 2012 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.h"
#include <CoreFoundation/CFDate.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include "base/logging.h"
#include "base/mac/mach_logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_mach_port.h"
#include "base/numerics/safe_conversions.h"
#include "base/stl_util.h"
#include "base/time/time_override.h"
#include "build/build_config.h"
#if defined(OS_IOS)
#include <time.h>
#include "base/ios/ios_util.h"
#endif
namespace {
#if defined(OS_MACOSX) && !defined(OS_IOS)
int64_t MachAbsoluteTimeToTicks(uint64_t mach_absolute_time) {
static mach_timebase_info_data_t timebase_info;
if (timebase_info.denom == 0) {
// Zero-initialization of statics guarantees that denom will be 0 before
// calling mach_timebase_info. mach_timebase_info will never set denom to
// 0 as that would be invalid, so the zero-check can be used to determine
// whether mach_timebase_info has already been called. This is
// recommended by Apple's QA1398.
kern_return_t kr = mach_timebase_info(&timebase_info);
MACH_DCHECK(kr == KERN_SUCCESS, kr) << "mach_timebase_info";
}
// timebase_info converts absolute time tick units into nanoseconds. Convert
// to microseconds up front to stave off overflows.
base::CheckedNumeric<uint64_t> result(mach_absolute_time /
base::Time::kNanosecondsPerMicrosecond);
result *= timebase_info.numer;
result /= timebase_info.denom;
// Don't bother with the rollover handling that the Windows version does.
// With numer and denom = 1 (the expected case), the 64-bit absolute time
// reported in nanoseconds is enough to last nearly 585 years.
return base::checked_cast<int64_t>(result.ValueOrDie());
}
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
// Returns monotonically growing number of ticks in microseconds since some
// unspecified starting point.
int64_t ComputeCurrentTicks() {
#if defined(OS_IOS)
// iOS 10 supports clock_gettime(CLOCK_MONOTONIC, ...), which is
// around 15 times faster than sysctl() call. Use it if possible;
// otherwise, fall back to sysctl().
if (__builtin_available(iOS 10, *)) {
struct timespec tp;
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
return (int64_t)tp.tv_sec * 1000000 + tp.tv_nsec / 1000;
}
}
// On iOS mach_absolute_time stops while the device is sleeping. Instead use
// now - KERN_BOOTTIME to get a time difference that is not impacted by clock
// changes. KERN_BOOTTIME will be updated by the system whenever the system
// clock change.
struct timeval boottime;
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
size_t size = sizeof(boottime);
int kr = sysctl(mib, base::size(mib), &boottime, &size, nullptr, 0);
DCHECK_EQ(KERN_SUCCESS, kr);
base::TimeDelta time_difference =
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
// with less precision (such as TickCount) just call through to
// mach_absolute_time.
return MachAbsoluteTimeToTicks(mach_absolute_time());
#endif // defined(OS_IOS)
}
int64_t ComputeThreadTicks() {
#if defined(OS_IOS)
NOTREACHED();
return 0;
#else
// The pthreads library keeps a cached reference to the thread port, which
// does not have to be released like mach_thread_self() does.
mach_port_t thread_port = pthread_mach_thread_np(pthread_self());
if (thread_port == MACH_PORT_NULL) {
DLOG(ERROR) << "Failed to get pthread_mach_thread_np()";
return 0;
}
mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT;
thread_basic_info_data_t thread_info_data;
kern_return_t kr = thread_info(
thread_port,
THREAD_BASIC_INFO,
reinterpret_cast<thread_info_t>(&thread_info_data),
&thread_info_count);
MACH_DCHECK(kr == KERN_SUCCESS, kr) << "thread_info";
base::CheckedNumeric<int64_t> absolute_micros(
thread_info_data.user_time.seconds +
thread_info_data.system_time.seconds);
absolute_micros *= base::Time::kMicrosecondsPerSecond;
absolute_micros += (thread_info_data.user_time.microseconds +
thread_info_data.system_time.microseconds);
return absolute_micros.ValueOrDie();
#endif // defined(OS_IOS)
}
} // namespace
namespace base {
// The Time routines in this file use Mach and CoreFoundation APIs, since the
// POSIX definition of time_t in Mac OS X wraps around after 2038--and
// there are already cookie expiration dates, etc., past that time out in
// the field. Using CFDate prevents that problem, and using mach_absolute_time
// for TimeTicks gives us nice high-resolution interval timing.
// Time -----------------------------------------------------------------------
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) {
static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity,
"CFAbsoluteTime must have an infinity value");
if (t == 0)
return Time(); // Consider 0 as a null Time.
if (t == std::numeric_limits<CFAbsoluteTime>::infinity())
return Max();
return Time(static_cast<int64_t>((t + kCFAbsoluteTimeIntervalSince1970) *
kMicrosecondsPerSecond) +
kTimeTToMicrosecondsOffset);
}
CFAbsoluteTime Time::ToCFAbsoluteTime() const {
static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity,
"CFAbsoluteTime must have an infinity value");
if (is_null())
return 0; // Consider 0 as a null Time.
if (is_max())
return std::numeric_limits<CFAbsoluteTime>::infinity();
return (static_cast<CFAbsoluteTime>(us_ - kTimeTToMicrosecondsOffset) /
kMicrosecondsPerSecond) -
kCFAbsoluteTimeIntervalSince1970;
}
// TimeTicks ------------------------------------------------------------------
namespace subtle {
TimeTicks TimeTicksNowIgnoringOverride() {
return TimeTicks() + TimeDelta::FromMicroseconds(ComputeCurrentTicks());
}
} // namespace subtle
// static
bool TimeTicks::IsHighResolution() {
return true;
}
// static
bool TimeTicks::IsConsistentAcrossProcesses() {
return true;
}
#if defined(OS_MACOSX) && !defined(OS_IOS)
// static
TimeTicks TimeTicks::FromMachAbsoluteTime(uint64_t mach_absolute_time) {
return TimeTicks(MachAbsoluteTimeToTicks(mach_absolute_time));
}
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
// static
TimeTicks::Clock TimeTicks::GetClock() {
#if defined(OS_IOS)
return Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME;
#else
return Clock::MAC_MACH_ABSOLUTE_TIME;
#endif // defined(OS_IOS)
}
// ThreadTicks ----------------------------------------------------------------
namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
return ThreadTicks() + TimeDelta::FromMicroseconds(ComputeThreadTicks());
}
} // namespace subtle
} // namespace base

View file

@ -0,0 +1,122 @@
// Copyright (c) 2012 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.h"
#include <stdint.h>
#include <sys/time.h>
#include <time.h>
#if defined(OS_ANDROID) && !defined(__LP64__)
#include <time64.h>
#endif
#include <unistd.h>
#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,
// non-POSIX implementation is used for sampling the system clocks.
#if defined(OS_FUCHSIA) || defined(OS_MACOSX)
#error "This implementation is for POSIX platforms other than Fuchsia or Mac."
#endif
namespace {
int64_t ConvertTimespecToMicros(const struct timespec& ts) {
// On 32-bit systems, the calculation cannot overflow int64_t.
// 2**32 * 1000000 + 2**64 / 1000 < 2**63
if (sizeof(ts.tv_sec) <= 4 && sizeof(ts.tv_nsec) <= 8) {
int64_t result = ts.tv_sec;
result *= base::Time::kMicrosecondsPerSecond;
result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
return result;
}
base::CheckedNumeric<int64_t> result(ts.tv_sec);
result *= base::Time::kMicrosecondsPerSecond;
result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
return result.ValueOrDie();
}
// Helper function to get results from clock_gettime() and convert to a
// microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported
// on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines
// _POSIX_MONOTONIC_CLOCK to -1.
#if (defined(OS_POSIX) && defined(_POSIX_MONOTONIC_CLOCK) && \
_POSIX_MONOTONIC_CLOCK >= 0) || \
defined(OS_BSD) || defined(OS_ANDROID)
int64_t ClockNow(clockid_t clk_id) {
struct timespec ts;
CHECK(clock_gettime(clk_id, &ts) == 0);
return ConvertTimespecToMicros(ts);
}
#else // _POSIX_MONOTONIC_CLOCK
#error No usable tick clock function on this platform.
#endif // _POSIX_MONOTONIC_CLOCK
} // namespace
namespace base {
// Time -----------------------------------------------------------------------
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() + TimeDelta::FromMicroseconds(
(tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) +
Time::kTimeTToMicrosecondsOffset);
}
Time TimeNowFromSystemTimeIgnoringOverride() {
// Just use TimeNowIgnoringOverride() because it returns the system time.
return TimeNowIgnoringOverride();
}
} // namespace subtle
// TimeTicks ------------------------------------------------------------------
namespace subtle {
TimeTicks TimeTicksNowIgnoringOverride() {
return TimeTicks() + TimeDelta::FromMicroseconds(ClockNow(CLOCK_MONOTONIC));
}
} // namespace subtle
// static
TimeTicks::Clock TimeTicks::GetClock() {
return Clock::LINUX_CLOCK_MONOTONIC;
}
// static
bool TimeTicks::IsHighResolution() {
return true;
}
// static
bool TimeTicks::IsConsistentAcrossProcesses() {
return true;
}
// ThreadTicks ----------------------------------------------------------------
namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
defined(OS_ANDROID)
return ThreadTicks() +
TimeDelta::FromMicroseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID));
#else
NOTREACHED();
return ThreadTicks();
#endif
}
} // namespace subtle
} // namespace base

View file

@ -0,0 +1,39 @@
// 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 {
// static
bool ScopedTimeClockOverrides::overrides_active_ = false;
ScopedTimeClockOverrides::ScopedTimeClockOverrides(
TimeNowFunction time_override,
TimeTicksNowFunction time_ticks_override,
ThreadTicksNowFunction thread_ticks_override) {
DCHECK(!overrides_active_);
overrides_active_ = true;
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;
overrides_active_ = false;
}
} // namespace subtle
} // namespace base

View file

@ -0,0 +1,74 @@
// 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.
#ifndef BASE_TIME_TIME_OVERRIDE_H_
#define BASE_TIME_TIME_OVERRIDE_H_
#include "base/base_export.h"
#include "base/time/time.h"
namespace base {
using TimeNowFunction = decltype(&Time::Now);
using TimeTicksNowFunction = decltype(&TimeTicks::Now);
using ThreadTicksNowFunction = decltype(&ThreadTicks::Now);
// Time overrides should be used with extreme caution. Discuss with //base/time
// OWNERS before adding a new one.
namespace subtle {
// Override the return value of Time::Now and Time::NowFromSystemTime /
// TimeTicks::Now / ThreadTicks::Now to emulate time, e.g. for tests or to
// modify progression of time. Note that the override should be set while
// single-threaded and before the first call to Now() to avoid threading issues
// and inconsistencies in returned values. Nested overrides are not allowed.
class BASE_EXPORT ScopedTimeClockOverrides {
public:
// Pass |nullptr| for any override if it shouldn't be overriden.
ScopedTimeClockOverrides(TimeNowFunction time_override,
TimeTicksNowFunction time_ticks_override,
ThreadTicksNowFunction thread_ticks_override);
// Restores the platform default Now() functions.
~ScopedTimeClockOverrides();
static bool overrides_active() { return overrides_active_; }
private:
static bool overrides_active_;
DISALLOW_COPY_AND_ASSIGN(ScopedTimeClockOverrides);
};
// These methods return the platform default Time::Now / TimeTicks::Now /
// ThreadTicks::Now values even while an override is in place. These methods
// should only be used in places where emulated time should be disregarded. For
// example, they can be used to implement test timeouts for tests that may
// override time.
BASE_EXPORT Time TimeNowIgnoringOverride();
BASE_EXPORT Time TimeNowFromSystemTimeIgnoringOverride();
BASE_EXPORT TimeTicks TimeTicksNowIgnoringOverride();
BASE_EXPORT ThreadTicks ThreadTicksNowIgnoringOverride();
} // namespace subtle
namespace internal {
// These function pointers are used by platform-independent implementations of
// the Now() methods and ScopedTimeClockOverrides. They are set to point to the
// respective NowIgnoringOverride functions by default, but can also be set by
// platform-specific code to select a default implementation at runtime, thereby
// avoiding the indirection via the NowIgnoringOverride functions. Note that the
// pointers can be overridden and later reset to the NowIgnoringOverride
// functions by ScopedTimeClockOverrides.
extern TimeNowFunction g_time_now_function;
extern TimeNowFunction g_time_now_from_system_time_function;
extern TimeTicksNowFunction g_time_ticks_now_function;
extern ThreadTicksNowFunction g_thread_ticks_now_function;
} // namespace internal
} // namespace base
#endif // BASE_TIME_TIME_OVERRIDE_H_

View file

@ -0,0 +1,20 @@
// 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_to_iso8601.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
namespace base {
std::string TimeToISO8601(const Time& t) {
Time::Exploded exploded;
t.UTCExplode(&exploded);
return StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year,
exploded.month, exploded.day_of_month, exploded.hour,
exploded.minute, exploded.second, exploded.millisecond);
}
} // namespace base

View file

@ -0,0 +1,20 @@
// 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.
#ifndef BASE_TIME_TIME_TO_ISO8601_H_
#define BASE_TIME_TIME_TO_ISO8601_H_
#include <string>
#include "base/base_export.h"
namespace base {
class Time;
BASE_EXPORT std::string TimeToISO8601(const base::Time& t);
} // namespace base
#endif // BASE_TIME_TIME_TO_ISO8601_H_

View file

@ -0,0 +1,810 @@
// Copyright (c) 2012 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.
// Windows Timer Primer
//
// A good article: http://www.ddj.com/windows/184416651
// A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258
//
// The default windows timer, GetSystemTimeAsFileTime is not very precise.
// It is only good to ~15.5ms.
//
// QueryPerformanceCounter is the logical choice for a high-precision timer.
// However, it is known to be buggy on some hardware. Specifically, it can
// sometimes "jump". On laptops, QPC can also be very expensive to call.
// It's 3-4x slower than timeGetTime() on desktops, but can be 10x slower
// on laptops. A unittest exists which will show the relative cost of various
// timers on any system.
//
// The next logical choice is timeGetTime(). timeGetTime has a precision of
// 1ms, but only if you call APIs (timeBeginPeriod()) which affect all other
// applications on the system. By default, precision is only 15.5ms.
// Unfortunately, we don't want to call timeBeginPeriod because we don't
// want to affect other applications. Further, on mobile platforms, use of
// faster multimedia timers can hurt battery life. See the intel
// article about this here:
// http://softwarecommunity.intel.com/articles/eng/1086.htm
//
// To work around all this, we're going to generally use timeGetTime(). We
// will only increase the system-wide timer if we're not running on battery
// power.
#include "base/time/time.h"
#include <windows.foundation.h>
#include <windows.h>
#include <mmsystem.h>
#include <stdint.h>
#include "base/atomicops.h"
#include "base/bit_cast.h"
#include "base/cpu.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/synchronization/lock.h"
#include "base/threading/platform_thread.h"
#include "base/time/time_override.h"
#include "base/time/time_win_features.h"
namespace base {
namespace {
// From MSDN, FILETIME "Contains a 64-bit value representing the number of
// 100-nanosecond intervals since January 1, 1601 (UTC)."
int64_t FileTimeToMicroseconds(const FILETIME& ft) {
// Need to bit_cast to fix alignment, then divide by 10 to convert
// 100-nanoseconds to microseconds. This only works on little-endian
// machines.
return bit_cast<int64_t, FILETIME>(ft) / 10;
}
void MicrosecondsToFileTime(int64_t us, FILETIME* ft) {
DCHECK_GE(us, 0LL) << "Time is less than 0, negative values are not "
"representable in FILETIME";
// Multiply by 10 to convert microseconds to 100-nanoseconds. Bit_cast will
// handle alignment problems. This only works on little-endian machines.
*ft = bit_cast<FILETIME, int64_t>(us * 10);
}
int64_t CurrentWallclockMicroseconds() {
FILETIME ft;
::GetSystemTimeAsFileTime(&ft);
return FileTimeToMicroseconds(ft);
}
// Time between resampling the un-granular clock for this API.
constexpr TimeDelta kMaxTimeToAvoidDrift = TimeDelta::FromSeconds(60);
int64_t g_initial_time = 0;
TimeTicks g_initial_ticks;
void InitializeClock() {
g_initial_ticks = subtle::TimeTicksNowIgnoringOverride();
g_initial_time = CurrentWallclockMicroseconds();
}
// Interval to use when on DC power.
UINT g_battery_power_interval_ms = 4;
// Track the last value passed to timeBeginPeriod so that we can cancel that
// call by calling timeEndPeriod with the same value. A value of zero means that
// the timer frequency is not currently raised.
UINT g_last_interval_requested_ms = 0;
// Track if MinTimerIntervalHighResMs() or MinTimerIntervalLowResMs() is active.
// For most purposes this could also be named g_is_on_ac_power.
bool g_high_res_timer_enabled = false;
// How many times the high resolution timer has been called.
uint32_t g_high_res_timer_count = 0;
// Start time of the high resolution timer usage monitoring. This is needed
// to calculate the usage as percentage of the total elapsed time.
TimeTicks g_high_res_timer_usage_start;
// The cumulative time the high resolution timer has been in use since
// |g_high_res_timer_usage_start| moment.
TimeDelta g_high_res_timer_usage;
// Timestamp of the last activation change of the high resolution timer. This
// is used to calculate the cumulative usage.
TimeTicks g_high_res_timer_last_activation;
// The lock to control access to the above set of variables.
Lock* GetHighResLock() {
static auto* lock = new Lock();
return lock;
}
// The two values that ActivateHighResolutionTimer uses to set the systemwide
// timer interrupt frequency on Windows. These control how precise timers are
// but also have a big impact on battery life.
// Used when a faster timer has been requested (g_high_res_timer_count > 0) and
// the computer is running on AC power (plugged in) so that it's okay to go to
// the highest frequency.
UINT MinTimerIntervalHighResMs() {
return 1;
}
// Used when a faster timer has been requested (g_high_res_timer_count > 0) and
// the computer is running on DC power (battery) so that we don't want to raise
// the timer frequency as much.
UINT MinTimerIntervalLowResMs() {
return g_battery_power_interval_ms;
}
// Calculate the desired timer interrupt interval. Note that zero means that the
// system default should be used.
UINT GetIntervalMs() {
if (!g_high_res_timer_count)
return 0; // Use the default, typically 15.625
if (g_high_res_timer_enabled)
return MinTimerIntervalHighResMs();
return MinTimerIntervalLowResMs();
}
// Compare the currently requested timer interrupt interval to the last interval
// requested and update if necessary (by cancelling the old request and making a
// new request). If there is no change then do nothing.
void UpdateTimerIntervalLocked() {
UINT new_interval = GetIntervalMs();
if (new_interval == g_last_interval_requested_ms)
return;
if (g_last_interval_requested_ms) {
// Record how long the timer interrupt frequency was raised.
g_high_res_timer_usage += subtle::TimeTicksNowIgnoringOverride() -
g_high_res_timer_last_activation;
// Reset the timer interrupt back to the default.
timeEndPeriod(g_last_interval_requested_ms);
}
g_last_interval_requested_ms = new_interval;
if (g_last_interval_requested_ms) {
// Record when the timer interrupt was raised.
g_high_res_timer_last_activation = subtle::TimeTicksNowIgnoringOverride();
timeBeginPeriod(g_last_interval_requested_ms);
}
}
// Returns the current value of the performance counter.
uint64_t QPCNowRaw() {
LARGE_INTEGER perf_counter_now = {};
// According to the MSDN documentation for QueryPerformanceCounter(), this
// will never fail on systems that run XP or later.
// https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx
::QueryPerformanceCounter(&perf_counter_now);
return perf_counter_now.QuadPart;
}
bool SafeConvertToWord(int in, WORD* out) {
CheckedNumeric<WORD> result = in;
*out = result.ValueOrDefault(std::numeric_limits<WORD>::max());
return result.IsValid();
}
} // namespace
// Time -----------------------------------------------------------------------
namespace subtle {
Time TimeNowIgnoringOverride() {
if (g_initial_time == 0)
InitializeClock();
// We implement time using the high-resolution timers so that we can get
// timeouts which are smaller than 10-15ms. If we just used
// CurrentWallclockMicroseconds(), we'd have the less-granular timer.
//
// To make this work, we initialize the clock (g_initial_time) and the
// counter (initial_ctr). To compute the initial time, we can check
// the number of ticks that have elapsed, and compute the delta.
//
// To avoid any drift, we periodically resync the counters to the system
// clock.
while (true) {
TimeTicks ticks = TimeTicksNowIgnoringOverride();
// Calculate the time elapsed since we started our timer
TimeDelta elapsed = ticks - g_initial_ticks;
// Check if enough time has elapsed that we need to resync the clock.
if (elapsed > kMaxTimeToAvoidDrift) {
InitializeClock();
continue;
}
return Time() + elapsed + TimeDelta::FromMicroseconds(g_initial_time);
}
}
Time TimeNowFromSystemTimeIgnoringOverride() {
// Force resync.
InitializeClock();
return Time() + TimeDelta::FromMicroseconds(g_initial_time);
}
} // namespace subtle
// static
Time Time::FromFileTime(FILETIME ft) {
if (bit_cast<int64_t, FILETIME>(ft) == 0)
return Time();
if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() &&
ft.dwLowDateTime == std::numeric_limits<DWORD>::max())
return Max();
return Time(FileTimeToMicroseconds(ft));
}
FILETIME Time::ToFileTime() const {
if (is_null())
return bit_cast<FILETIME, int64_t>(0);
if (is_max()) {
FILETIME result;
result.dwHighDateTime = std::numeric_limits<DWORD>::max();
result.dwLowDateTime = std::numeric_limits<DWORD>::max();
return result;
}
FILETIME utc_ft;
MicrosecondsToFileTime(us_, &utc_ft);
return utc_ft;
}
void Time::ReadMinTimerIntervalLowResMs() {
AutoLock lock(*GetHighResLock());
// Read the setting for what interval to use on battery power.
g_battery_power_interval_ms =
base::FeatureList::IsEnabled(base::kSlowDCTimerInterruptsWin) ? 8 : 4;
UpdateTimerIntervalLocked();
}
// static
// Enable raising of the system-global timer interrupt frequency to 1 kHz (when
// enable is true, which happens when on AC power) or some lower frequency when
// on battery power (when enable is false). If the g_high_res_timer_enabled
// setting hasn't actually changed or if if there are no outstanding requests
// (if g_high_res_timer_count is zero) then do nothing.
// TL;DR - call this when going from AC to DC power or vice-versa.
void Time::EnableHighResolutionTimer(bool enable) {
AutoLock lock(*GetHighResLock());
g_high_res_timer_enabled = enable;
UpdateTimerIntervalLocked();
}
// static
// Request that the system-global Windows timer interrupt frequency be raised.
// How high the frequency is raised depends on the system's power state and
// possibly other options.
// TL;DR - call this at the beginning and end of a time period where you want
// higher frequency timer interrupts. Each call with activating=true must be
// paired with a subsequent activating=false call.
bool Time::ActivateHighResolutionTimer(bool activating) {
// We only do work on the transition from zero to one or one to zero so we
// can easily undo the effect (if necessary) when EnableHighResolutionTimer is
// called.
const uint32_t max = std::numeric_limits<uint32_t>::max();
AutoLock lock(*GetHighResLock());
if (activating) {
DCHECK_NE(g_high_res_timer_count, max);
++g_high_res_timer_count;
} else {
DCHECK_NE(g_high_res_timer_count, 0u);
--g_high_res_timer_count;
}
UpdateTimerIntervalLocked();
return true;
}
// static
// See if the timer interrupt interval has been set to the lowest value.
bool Time::IsHighResolutionTimerInUse() {
AutoLock lock(*GetHighResLock());
return g_last_interval_requested_ms == MinTimerIntervalHighResMs();
}
// static
void Time::ResetHighResolutionTimerUsage() {
AutoLock lock(*GetHighResLock());
g_high_res_timer_usage = TimeDelta();
g_high_res_timer_usage_start = subtle::TimeTicksNowIgnoringOverride();
if (g_high_res_timer_count > 0)
g_high_res_timer_last_activation = g_high_res_timer_usage_start;
}
// static
double Time::GetHighResolutionTimerUsage() {
AutoLock lock(*GetHighResLock());
TimeTicks now = subtle::TimeTicksNowIgnoringOverride();
TimeDelta elapsed_time = now - g_high_res_timer_usage_start;
if (elapsed_time.is_zero()) {
// This is unexpected but possible if TimeTicks resolution is low and
// GetHighResolutionTimerUsage() is called promptly after
// ResetHighResolutionTimerUsage().
return 0.0;
}
TimeDelta used_time = g_high_res_timer_usage;
if (g_high_res_timer_count > 0) {
// If currently activated add the remainder of time since the last
// activation.
used_time += now - g_high_res_timer_last_activation;
}
return used_time.InMillisecondsF() / elapsed_time.InMillisecondsF() * 100;
}
// static
bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
// Create the system struct representing our exploded time. It will either be
// in local time or UTC.If casting from int to WORD results in overflow,
// fail and return Time(0).
SYSTEMTIME st;
if (!SafeConvertToWord(exploded.year, &st.wYear) ||
!SafeConvertToWord(exploded.month, &st.wMonth) ||
!SafeConvertToWord(exploded.day_of_week, &st.wDayOfWeek) ||
!SafeConvertToWord(exploded.day_of_month, &st.wDay) ||
!SafeConvertToWord(exploded.hour, &st.wHour) ||
!SafeConvertToWord(exploded.minute, &st.wMinute) ||
!SafeConvertToWord(exploded.second, &st.wSecond) ||
!SafeConvertToWord(exploded.millisecond, &st.wMilliseconds)) {
*time = Time(0);
return false;
}
FILETIME ft;
bool success = true;
// Ensure that it's in UTC.
if (is_local) {
SYSTEMTIME utc_st;
success = TzSpecificLocalTimeToSystemTime(nullptr, &st, &utc_st) &&
SystemTimeToFileTime(&utc_st, &ft);
} else {
success = !!SystemTimeToFileTime(&st, &ft);
}
if (!success) {
*time = Time(0);
return false;
}
*time = Time(FileTimeToMicroseconds(ft));
return true;
}
void Time::Explode(bool is_local, Exploded* exploded) const {
if (us_ < 0LL) {
// We are not able to convert it to FILETIME.
ZeroMemory(exploded, sizeof(*exploded));
return;
}
// FILETIME in UTC.
FILETIME utc_ft;
MicrosecondsToFileTime(us_, &utc_ft);
// FILETIME in local time if necessary.
bool success = true;
// FILETIME in SYSTEMTIME (exploded).
SYSTEMTIME st = {0};
if (is_local) {
SYSTEMTIME utc_st;
// We don't use FileTimeToLocalFileTime here, since it uses the current
// settings for the time zone and daylight saving time. Therefore, if it is
// daylight saving time, it will take daylight saving time into account,
// even if the time you are converting is in standard time.
success = FileTimeToSystemTime(&utc_ft, &utc_st) &&
SystemTimeToTzSpecificLocalTime(nullptr, &utc_st, &st);
} else {
success = !!FileTimeToSystemTime(&utc_ft, &st);
}
if (!success) {
NOTREACHED() << "Unable to convert time, don't know why";
ZeroMemory(exploded, sizeof(*exploded));
return;
}
exploded->year = st.wYear;
exploded->month = st.wMonth;
exploded->day_of_week = st.wDayOfWeek;
exploded->day_of_month = st.wDay;
exploded->hour = st.wHour;
exploded->minute = st.wMinute;
exploded->second = st.wSecond;
exploded->millisecond = st.wMilliseconds;
}
// TimeTicks ------------------------------------------------------------------
namespace {
// We define a wrapper to adapt between the __stdcall and __cdecl call of the
// mock function, and to avoid a static constructor. Assigning an import to a
// function pointer directly would require setup code to fetch from the IAT.
DWORD timeGetTimeWrapper() {
return timeGetTime();
}
DWORD (*g_tick_function)(void) = &timeGetTimeWrapper;
// A structure holding the most significant bits of "last seen" and a
// "rollover" counter.
union LastTimeAndRolloversState {
// The state as a single 32-bit opaque value.
subtle::Atomic32 as_opaque_32;
// The state as usable values.
struct {
// The top 8-bits of the "last" time. This is enough to check for rollovers
// and the small bit-size means fewer CompareAndSwap operations to store
// changes in state, which in turn makes for fewer retries.
uint8_t last_8;
// A count of the number of detected rollovers. Using this as bits 47-32
// of the upper half of a 64-bit value results in a 48-bit tick counter.
// This extends the total rollover period from about 49 days to about 8800
// years while still allowing it to be stored with last_8 in a single
// 32-bit value.
uint16_t rollovers;
} as_values;
};
subtle::Atomic32 g_last_time_and_rollovers = 0;
static_assert(
sizeof(LastTimeAndRolloversState) <= sizeof(g_last_time_and_rollovers),
"LastTimeAndRolloversState does not fit in a single atomic word");
// We use timeGetTime() to implement TimeTicks::Now(). This can be problematic
// because it returns the number of milliseconds since Windows has started,
// which will roll over the 32-bit value every ~49 days. We try to track
// rollover ourselves, which works if TimeTicks::Now() is called at least every
// 48.8 days (not 49 days because only changes in the top 8 bits get noticed).
TimeTicks RolloverProtectedNow() {
LastTimeAndRolloversState state;
DWORD now; // DWORD is always unsigned 32 bits.
while (true) {
// Fetch the "now" and "last" tick values, updating "last" with "now" and
// incrementing the "rollovers" counter if the tick-value has wrapped back
// around. Atomic operations ensure that both "last" and "rollovers" are
// always updated together.
int32_t original = subtle::Acquire_Load(&g_last_time_and_rollovers);
state.as_opaque_32 = original;
now = g_tick_function();
uint8_t now_8 = static_cast<uint8_t>(now >> 24);
if (now_8 < state.as_values.last_8)
++state.as_values.rollovers;
state.as_values.last_8 = now_8;
// If the state hasn't changed, exit the loop.
if (state.as_opaque_32 == original)
break;
// Save the changed state. If the existing value is unchanged from the
// original, exit the loop.
int32_t check = subtle::Release_CompareAndSwap(
&g_last_time_and_rollovers, original, state.as_opaque_32);
if (check == original)
break;
// Another thread has done something in between so retry from the top.
}
return TimeTicks() +
TimeDelta::FromMilliseconds(
now + (static_cast<uint64_t>(state.as_values.rollovers) << 32));
}
// Discussion of tick counter options on Windows:
//
// (1) CPU cycle counter. (Retrieved via RDTSC)
// The CPU counter provides the highest resolution time stamp and is the least
// expensive to retrieve. However, on older CPUs, two issues can affect its
// reliability: First it is maintained per processor and not synchronized
// between processors. Also, the counters will change frequency due to thermal
// and power changes, and stop in some states.
//
// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high-
// resolution (<1 microsecond) time stamp. On most hardware running today, it
// auto-detects and uses the constant-rate RDTSC counter to provide extremely
// efficient and reliable time stamps.
//
// On older CPUs where RDTSC is unreliable, it falls back to using more
// expensive (20X to 40X more costly) alternate clocks, such as HPET or the ACPI
// PM timer, and can involve system calls; and all this is up to the HAL (with
// some help from ACPI). According to
// http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx, in the
// worst case, it gets the counter from the rollover interrupt on the
// programmable interrupt timer. In best cases, the HAL may conclude that the
// RDTSC counter runs at a constant frequency, then it uses that instead. On
// multiprocessor machines, it will try to verify the values returned from
// RDTSC on each processor are consistent with each other, and apply a handful
// of workarounds for known buggy hardware. In other words, QPC is supposed to
// give consistent results on a multiprocessor computer, but for older CPUs it
// can be unreliable due bugs in BIOS or HAL.
//
// (3) System time. The system time provides a low-resolution (from ~1 to ~15.6
// milliseconds) time stamp but is comparatively less expensive to retrieve and
// more reliable. Time::EnableHighResolutionTimer() and
// Time::ActivateHighResolutionTimer() can be called to alter the resolution of
// this timer; and also other Windows applications can alter it, affecting this
// one.
TimeTicks InitialNowFunction();
// See "threading notes" in InitializeNowFunctionPointer() for details on how
// concurrent reads/writes to these globals has been made safe.
TimeTicksNowFunction g_time_ticks_now_ignoring_override_function =
&InitialNowFunction;
int64_t g_qpc_ticks_per_second = 0;
// As of January 2015, use of <atomic> is forbidden in Chromium code. This is
// what std::atomic_thread_fence does on Windows on all Intel architectures when
// the memory_order argument is anything but std::memory_order_seq_cst:
#define ATOMIC_THREAD_FENCE(memory_order) _ReadWriteBarrier();
TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) {
// Ensure that the assignment to |g_qpc_ticks_per_second|, made in
// InitializeNowFunctionPointer(), has happened by this point.
ATOMIC_THREAD_FENCE(memory_order_acquire);
DCHECK_GT(g_qpc_ticks_per_second, 0);
// If the QPC Value is below the overflow threshold, we proceed with
// simple multiply and divide.
if (qpc_value < Time::kQPCOverflowThreshold) {
return TimeDelta::FromMicroseconds(
qpc_value * Time::kMicrosecondsPerSecond / g_qpc_ticks_per_second);
}
// Otherwise, calculate microseconds in a round about manner to avoid
// overflow and precision issues.
int64_t whole_seconds = qpc_value / g_qpc_ticks_per_second;
int64_t leftover_ticks = qpc_value - (whole_seconds * g_qpc_ticks_per_second);
return TimeDelta::FromMicroseconds(
(whole_seconds * Time::kMicrosecondsPerSecond) +
((leftover_ticks * Time::kMicrosecondsPerSecond) /
g_qpc_ticks_per_second));
}
TimeTicks QPCNow() {
return TimeTicks() + QPCValueToTimeDelta(QPCNowRaw());
}
void InitializeNowFunctionPointer() {
LARGE_INTEGER ticks_per_sec = {};
if (!QueryPerformanceFrequency(&ticks_per_sec))
ticks_per_sec.QuadPart = 0;
// If Windows cannot provide a QPC implementation, TimeTicks::Now() must use
// the low-resolution clock.
//
// If the QPC implementation is expensive and/or unreliable, TimeTicks::Now()
// will still use the low-resolution clock. A CPU lacking a non-stop time
// counter will cause Windows to provide an alternate QPC implementation that
// works, but is expensive to use.
//
// Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015,
// ~72% of users fall within this category.
TimeTicksNowFunction now_function;
CPU cpu;
if (ticks_per_sec.QuadPart <= 0 || !cpu.has_non_stop_time_stamp_counter()) {
now_function = &RolloverProtectedNow;
} else {
now_function = &QPCNow;
}
// Threading note 1: In an unlikely race condition, it's possible for two or
// more threads to enter InitializeNowFunctionPointer() in parallel. This is
// not a problem since all threads should end up writing out the same values
// to the global variables.
//
// Threading note 2: A release fence is placed here to ensure, from the
// perspective of other threads using the function pointers, that the
// assignment to |g_qpc_ticks_per_second| happens before the function pointers
// are changed.
g_qpc_ticks_per_second = ticks_per_sec.QuadPart;
ATOMIC_THREAD_FENCE(memory_order_release);
// Also set g_time_ticks_now_function to avoid the additional indirection via
// TimeTicksNowIgnoringOverride() for future calls to TimeTicks::Now(). But
// g_time_ticks_now_function may have already be overridden.
if (internal::g_time_ticks_now_function ==
&subtle::TimeTicksNowIgnoringOverride) {
internal::g_time_ticks_now_function = now_function;
}
g_time_ticks_now_ignoring_override_function = now_function;
}
TimeTicks InitialNowFunction() {
InitializeNowFunctionPointer();
return g_time_ticks_now_ignoring_override_function();
}
} // namespace
// static
TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction(
TickFunctionType ticker) {
TickFunctionType old = g_tick_function;
g_tick_function = ticker;
subtle::NoBarrier_Store(&g_last_time_and_rollovers, 0);
return old;
}
namespace subtle {
TimeTicks TimeTicksNowIgnoringOverride() {
return g_time_ticks_now_ignoring_override_function();
}
} // namespace subtle
// static
bool TimeTicks::IsHighResolution() {
if (g_time_ticks_now_ignoring_override_function == &InitialNowFunction)
InitializeNowFunctionPointer();
return g_time_ticks_now_ignoring_override_function == &QPCNow;
}
// static
bool TimeTicks::IsConsistentAcrossProcesses() {
// According to Windows documentation [1] QPC is consistent post-Windows
// Vista. So if we are using QPC then we are consistent which is the same as
// being high resolution.
//
// [1] https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
//
// "In general, the performance counter results are consistent across all
// processors in multi-core and multi-processor systems, even when measured on
// different threads or processes. Here are some exceptions to this rule:
// - Pre-Windows Vista operating systems that run on certain processors might
// violate this consistency because of one of these reasons:
// 1. The hardware processors have a non-invariant TSC and the BIOS
// doesn't indicate this condition correctly.
// 2. The TSC synchronization algorithm that was used wasn't suitable for
// systems with large numbers of processors."
return IsHighResolution();
}
// static
TimeTicks::Clock TimeTicks::GetClock() {
return IsHighResolution() ?
Clock::WIN_QPC : Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME;
}
// ThreadTicks ----------------------------------------------------------------
namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
return ThreadTicks::GetForThread(PlatformThread::CurrentHandle());
}
} // namespace subtle
// static
ThreadTicks ThreadTicks::GetForThread(
const PlatformThreadHandle& thread_handle) {
DCHECK(IsSupported());
#if defined(ARCH_CPU_ARM64)
// QueryThreadCycleTime versus TSCTicksPerSecond doesn't have much relation to
// actual elapsed time on Windows on Arm, because QueryThreadCycleTime is
// backed by the actual number of CPU cycles executed, rather than a
// constant-rate timer like Intel. To work around this, use GetThreadTimes
// (which isn't as accurate but is meaningful as a measure of elapsed
// per-thread time).
FILETIME creation_time, exit_time, kernel_time, user_time;
::GetThreadTimes(thread_handle.platform_handle(), &creation_time, &exit_time,
&kernel_time, &user_time);
int64_t us = FileTimeToMicroseconds(user_time);
return ThreadTicks(us);
#else
// Get the number of TSC ticks used by the current thread.
ULONG64 thread_cycle_time = 0;
::QueryThreadCycleTime(thread_handle.platform_handle(), &thread_cycle_time);
// Get the frequency of the TSC.
double tsc_ticks_per_second = TSCTicksPerSecond();
if (tsc_ticks_per_second == 0)
return ThreadTicks();
// Return the CPU time of the current thread.
double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second;
return ThreadTicks(
static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond));
#endif
}
// static
bool ThreadTicks::IsSupportedWin() {
static bool is_supported = CPU().has_non_stop_time_stamp_counter();
return is_supported;
}
// static
void ThreadTicks::WaitUntilInitializedWin() {
#if !defined(ARCH_CPU_ARM64)
while (TSCTicksPerSecond() == 0)
::Sleep(10);
#endif
}
#if !defined(ARCH_CPU_ARM64)
double ThreadTicks::TSCTicksPerSecond() {
DCHECK(IsSupported());
// The value returned by QueryPerformanceFrequency() cannot be used as the TSC
// frequency, because there is no guarantee that the TSC frequency is equal to
// the performance counter frequency.
// The TSC frequency is cached in a static variable because it takes some time
// to compute it.
static double tsc_ticks_per_second = 0;
if (tsc_ticks_per_second != 0)
return tsc_ticks_per_second;
// Increase the thread priority to reduces the chances of having a context
// switch during a reading of the TSC and the performance counter.
int previous_priority = ::GetThreadPriority(::GetCurrentThread());
::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
// The first time that this function is called, make an initial reading of the
// TSC and the performance counter.
static const uint64_t tsc_initial = __rdtsc();
static const uint64_t perf_counter_initial = QPCNowRaw();
// Make a another reading of the TSC and the performance counter every time
// that this function is called.
uint64_t tsc_now = __rdtsc();
uint64_t perf_counter_now = QPCNowRaw();
// Reset the thread priority.
::SetThreadPriority(::GetCurrentThread(), previous_priority);
// Make sure that at least 50 ms elapsed between the 2 readings. The first
// time that this function is called, we don't expect this to be the case.
// Note: The longer the elapsed time between the 2 readings is, the more
// accurate the computed TSC frequency will be. The 50 ms value was
// chosen because local benchmarks show that it allows us to get a
// stddev of less than 1 tick/us between multiple runs.
// Note: According to the MSDN documentation for QueryPerformanceFrequency(),
// this will never fail on systems that run XP or later.
// https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx
LARGE_INTEGER perf_counter_frequency = {};
::QueryPerformanceFrequency(&perf_counter_frequency);
DCHECK_GE(perf_counter_now, perf_counter_initial);
uint64_t perf_counter_ticks = perf_counter_now - perf_counter_initial;
double elapsed_time_seconds =
perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart);
static constexpr double kMinimumEvaluationPeriodSeconds = 0.05;
if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds)
return 0;
// Compute the frequency of the TSC.
DCHECK_GE(tsc_now, tsc_initial);
uint64_t tsc_ticks = tsc_now - tsc_initial;
tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds;
return tsc_ticks_per_second;
}
#endif // defined(ARCH_CPU_ARM64)
// static
TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) {
return TimeTicks() + QPCValueToTimeDelta(qpc_value);
}
// TimeDelta ------------------------------------------------------------------
// static
TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) {
return QPCValueToTimeDelta(qpc_value);
}
// static
TimeDelta TimeDelta::FromFileTime(FILETIME ft) {
return TimeDelta::FromMicroseconds(FileTimeToMicroseconds(ft));
}
// static
TimeDelta TimeDelta::FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt) {
// UniversalTime is 100 ns intervals since January 1, 1601 (UTC)
return TimeDelta::FromMicroseconds(dt.UniversalTime / 10);
}
ABI::Windows::Foundation::DateTime TimeDelta::ToWinrtDateTime() const {
ABI::Windows::Foundation::DateTime date_time;
date_time.UniversalTime = InMicroseconds() * 10;
return date_time;
}
} // namespace base

View file

@ -0,0 +1,14 @@
// Copyright 2019 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_win_features.h"
#include "base/feature_list.h"
namespace base {
const Feature kSlowDCTimerInterruptsWin{"SlowDCTimerInterruptsWin",
FEATURE_DISABLED_BY_DEFAULT};
} // namespace base

View file

@ -0,0 +1,20 @@
// Copyright 2019 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.
#ifndef BASE_TIME_TIME_WIN_FEATURES_H_
#define BASE_TIME_TIME_WIN_FEATURES_H_
#include "base/base_export.h"
namespace base {
struct Feature;
// Slow the maximum interrupt timer on battery power to 8 ms, instead of the
// default 4 ms.
extern const BASE_EXPORT Feature kSlowDCTimerInterruptsWin;
} // namespace base
#endif // BASE_TIME_TIME_WIN_FEATURES_H_