diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /security/sandbox/chromium/base/time | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/sandbox/chromium/base/time')
-rw-r--r-- | security/sandbox/chromium/base/time/time.cc | 433 | ||||
-rw-r--r-- | security/sandbox/chromium/base/time/time.h | 1077 | ||||
-rw-r--r-- | security/sandbox/chromium/base/time/time_exploded_posix.cc | 287 | ||||
-rw-r--r-- | security/sandbox/chromium/base/time/time_now_posix.cc | 122 | ||||
-rw-r--r-- | security/sandbox/chromium/base/time/time_override.h | 74 | ||||
-rw-r--r-- | security/sandbox/chromium/base/time/time_win.cc | 810 | ||||
-rw-r--r-- | security/sandbox/chromium/base/time/time_win_features.cc | 14 | ||||
-rw-r--r-- | security/sandbox/chromium/base/time/time_win_features.h | 20 |
8 files changed, 2837 insertions, 0 deletions
diff --git a/security/sandbox/chromium/base/time/time.cc b/security/sandbox/chromium/base/time/time.cc new file mode 100644 index 0000000000..1293cdcaad --- /dev/null +++ b/security/sandbox/chromium/base/time/time.cc @@ -0,0 +1,433 @@ +// 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(); + } + 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(); + } + 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(); + } + 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(); + } + 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(); + } + 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(); + } + return delta_ / Time::kMicrosecondsPerSecond; +} + +double TimeDelta::InMillisecondsF() const { + if (is_max()) { + // Preserve max to prevent overflow. + 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(); + } + return delta_ / Time::kMicrosecondsPerMillisecond; +} + +int64_t TimeDelta::InMillisecondsRoundedUp() const { + if (is_max()) { + // Preserve max to prevent overflow. + return std::numeric_limits<int64_t>::max(); + } + 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(); + } + 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(); + } + 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 (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(); + } + 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(); + } + 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(); + } + 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(); +} + +#if !defined(MOZ_SANDBOX) +// 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; +} +#endif + +// 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 - kMicrosecondsPerMillisecond + 1) / + kMicrosecondsPerMillisecond; + } +} + +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 diff --git a/security/sandbox/chromium/base/time/time.h b/security/sandbox/chromium/base/time/time.h new file mode 100644 index 0000000000..7214e000f0 --- /dev/null +++ b/security/sandbox/chromium/base/time/time.h @@ -0,0 +1,1077 @@ +// 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. + +// Time represents an absolute point in coordinated universal time (UTC), +// internally represented as microseconds (s/1,000,000) since the Windows epoch +// (1601-01-01 00:00:00 UTC). System-dependent clock interface routines are +// defined in time_PLATFORM.cc. Note that values for Time may skew and jump +// around as the operating system makes adjustments to synchronize (e.g., with +// NTP servers). Thus, client code that uses the Time class must account for +// this. +// +// TimeDelta represents a duration of time, internally represented in +// microseconds. +// +// TimeTicks and ThreadTicks represent an abstract time that is most of the time +// incrementing, for use in measuring time durations. Internally, they are +// represented in microseconds. They cannot be converted to a human-readable +// time, but are guaranteed not to decrease (unlike the Time class). Note that +// TimeTicks may "stand still" (e.g., if the computer is suspended), and +// ThreadTicks will "stand still" whenever the thread has been de-scheduled by +// the operating system. +// +// All time classes are copyable, assignable, and occupy 64-bits per instance. +// As a result, prefer passing them by value: +// void MyFunction(TimeDelta arg); +// If circumstances require, you may also pass by const reference: +// void MyFunction(const TimeDelta& arg); // Not preferred. +// +// Definitions of operator<< are provided to make these types work with +// DCHECK_EQ() and other log macros. For human-readable formatting, see +// "base/i18n/time_formatting.h". +// +// So many choices! Which time class should you use? Examples: +// +// Time: Interpreting the wall-clock time provided by a remote system. +// Detecting whether cached resources have expired. Providing the +// user with a display of the current date and time. Determining +// the amount of time between events across re-boots of the +// machine. +// +// TimeTicks: Tracking the amount of time a task runs. Executing delayed +// tasks at the right time. Computing presentation timestamps. +// Synchronizing audio and video using TimeTicks as a common +// reference clock (lip-sync). Measuring network round-trip +// latency. +// +// ThreadTicks: Benchmarking how long the current thread has been doing actual +// work. + +#ifndef BASE_TIME_TIME_H_ +#define BASE_TIME_TIME_H_ + +#include <stdint.h> +#include <time.h> + +#include <iosfwd> +#include <limits> + +#include "base/base_export.h" +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "base/numerics/safe_math.h" +#include "build/build_config.h" + +#if defined(OS_FUCHSIA) +#include <zircon/types.h> +#endif + +#if defined(OS_MACOSX) +#include <CoreFoundation/CoreFoundation.h> +// Avoid Mac system header macro leak. +#undef TYPE_BOOL +#endif + +#if defined(OS_ANDROID) +#include <jni.h> +#endif + +#if defined(OS_POSIX) || defined(OS_FUCHSIA) +#include <unistd.h> +#include <sys/time.h> +#endif + +#if defined(OS_WIN) +#include "base/gtest_prod_util.h" +#include "base/win/windows_types.h" +#endif + +namespace ABI { +namespace Windows { +namespace Foundation { +struct DateTime; +} // namespace Foundation +} // namespace Windows +} // namespace ABI + +namespace base { + +class PlatformThreadHandle; +class TimeDelta; + +// The functions in the time_internal namespace are meant to be used only by the +// time classes and functions. Please use the math operators defined in the +// time classes instead. +namespace time_internal { + +// Add or subtract a TimeDelta from |value|. TimeDelta::Min()/Max() are treated +// as infinity and will always saturate the return value (infinity math applies +// if |value| also is at either limit of its spectrum). The int64_t argument and +// return value are in terms of a microsecond timebase. +BASE_EXPORT constexpr int64_t SaturatedAdd(int64_t value, TimeDelta delta); +BASE_EXPORT constexpr int64_t SaturatedSub(int64_t value, TimeDelta delta); + +} // namespace time_internal + +// TimeDelta ------------------------------------------------------------------ + +class BASE_EXPORT TimeDelta { + public: + constexpr TimeDelta() : delta_(0) {} + + // Converts units of time to TimeDeltas. + // WARNING: Floating point arithmetic is such that FromXXXD(t.InXXXF()) may + // not precisely equal |t|. Hence, floating point values should not be used + // for storage. + static constexpr TimeDelta FromDays(int days); + static constexpr TimeDelta FromHours(int hours); + static constexpr TimeDelta FromMinutes(int minutes); + static constexpr TimeDelta FromSeconds(int64_t secs); + static constexpr TimeDelta FromMilliseconds(int64_t ms); + static constexpr TimeDelta FromMicroseconds(int64_t us); + static constexpr TimeDelta FromNanoseconds(int64_t ns); + static constexpr TimeDelta FromSecondsD(double secs); + static constexpr TimeDelta FromMillisecondsD(double ms); + static constexpr TimeDelta FromMicrosecondsD(double us); + static constexpr TimeDelta FromNanosecondsD(double ns); +#if defined(OS_WIN) + static TimeDelta FromQPCValue(LONGLONG qpc_value); + // TODO(crbug.com/989694): Avoid base::TimeDelta factory functions + // based on absolute time + static TimeDelta FromFileTime(FILETIME ft); + static TimeDelta FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt); +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + static TimeDelta FromTimeSpec(const timespec& ts); +#endif +#if defined(OS_FUCHSIA) + static TimeDelta FromZxDuration(zx_duration_t nanos); +#endif + + // Converts an integer value representing TimeDelta to a class. This is used + // when deserializing a |TimeDelta| structure, using a value known to be + // compatible. It is not provided as a constructor because the integer type + // may be unclear from the perspective of a caller. + // + // DEPRECATED - Do not use in new code. http://crbug.com/634507 + static constexpr TimeDelta FromInternalValue(int64_t delta) { + return TimeDelta(delta); + } + + // Returns the maximum time delta, which should be greater than any reasonable + // time delta we might compare it to. Adding or subtracting the maximum time + // delta to a time or another time delta has an undefined result. + static constexpr TimeDelta Max(); + + // Returns the minimum time delta, which should be less than than any + // reasonable time delta we might compare it to. Adding or subtracting the + // minimum time delta to a time or another time delta has an undefined result. + static constexpr TimeDelta Min(); + + // Returns the internal numeric value of the TimeDelta object. Please don't + // use this and do arithmetic on it, as it is more error prone than using the + // provided operators. + // For serializing, use FromInternalValue to reconstitute. + // + // DEPRECATED - Do not use in new code. http://crbug.com/634507 + constexpr int64_t ToInternalValue() const { return delta_; } + + // Returns the magnitude (absolute value) of this TimeDelta. + constexpr TimeDelta magnitude() const { + // Some toolchains provide an incomplete C++11 implementation and lack an + // int64_t overload for std::abs(). The following is a simple branchless + // implementation: + const int64_t mask = delta_ >> (sizeof(delta_) * 8 - 1); + return TimeDelta((delta_ + mask) ^ mask); + } + + // Returns true if the time delta is zero. + constexpr bool is_zero() const { return delta_ == 0; } + + // Returns true if the time delta is the maximum/minimum time delta. + constexpr bool is_max() const { + return delta_ == std::numeric_limits<int64_t>::max(); + } + constexpr bool is_min() const { + return delta_ == std::numeric_limits<int64_t>::min(); + } + +#if defined(OS_POSIX) || defined(OS_FUCHSIA) + struct timespec ToTimeSpec() const; +#endif +#if defined(OS_FUCHSIA) + zx_duration_t ToZxDuration() const; +#endif +#if defined(OS_WIN) + ABI::Windows::Foundation::DateTime ToWinrtDateTime() const; +#endif + + // Returns the time delta in some unit. The InXYZF versions return a floating + // point value. The InXYZ versions return a truncated value (aka rounded + // towards zero, std::trunc() behavior). The InXYZFloored() versions round to + // lesser integers (std::floor() behavior). The XYZRoundedUp() versions round + // up to greater integers (std::ceil() behavior). + // WARNING: Floating point arithmetic is such that FromXXXD(t.InXXXF()) may + // not precisely equal |t|. Hence, floating point values should not be used + // for storage. + int InDays() const; + int InDaysFloored() const; + int InHours() const; + int InMinutes() const; + double InSecondsF() const; + int64_t InSeconds() const; + double InMillisecondsF() const; + int64_t InMilliseconds() const; + int64_t InMillisecondsRoundedUp() const; + constexpr int64_t InMicroseconds() const { return delta_; } + double InMicrosecondsF() const; + int64_t InNanoseconds() const; + + // Computations with other deltas. + constexpr TimeDelta operator+(TimeDelta other) const { + return TimeDelta(time_internal::SaturatedAdd(delta_, other)); + } + constexpr TimeDelta operator-(TimeDelta other) const { + return TimeDelta(time_internal::SaturatedSub(delta_, other)); + } + + constexpr TimeDelta& operator+=(TimeDelta other) { + return *this = (*this + other); + } + constexpr TimeDelta& operator-=(TimeDelta other) { + return *this = (*this - other); + } + constexpr TimeDelta operator-() const { return TimeDelta(-delta_); } + + // Computations with numeric types. + template <typename T> + constexpr TimeDelta operator*(T a) const { + CheckedNumeric<int64_t> rv(delta_); + rv *= a; + if (rv.IsValid()) + return TimeDelta(rv.ValueOrDie()); + // Matched sign overflows. Mismatched sign underflows. + if ((delta_ < 0) ^ (a < 0)) + return TimeDelta(std::numeric_limits<int64_t>::min()); + return TimeDelta(std::numeric_limits<int64_t>::max()); + } + template <typename T> + constexpr TimeDelta operator/(T a) const { + CheckedNumeric<int64_t> rv(delta_); + rv /= a; + if (rv.IsValid()) + return TimeDelta(rv.ValueOrDie()); + // Matched sign overflows. Mismatched sign underflows. + // Special case to catch divide by zero. + if ((delta_ < 0) ^ (a <= 0)) + return TimeDelta(std::numeric_limits<int64_t>::min()); + return TimeDelta(std::numeric_limits<int64_t>::max()); + } + template <typename T> + constexpr TimeDelta& operator*=(T a) { + return *this = (*this * a); + } + template <typename T> + constexpr TimeDelta& operator/=(T a) { + return *this = (*this / a); + } + + constexpr int64_t operator/(TimeDelta a) const { return delta_ / a.delta_; } + + constexpr TimeDelta operator%(TimeDelta a) const { + return TimeDelta(delta_ % a.delta_); + } + TimeDelta& operator%=(TimeDelta other) { return *this = (*this % other); } + + // Comparison operators. + constexpr bool operator==(TimeDelta other) const { + return delta_ == other.delta_; + } + constexpr bool operator!=(TimeDelta other) const { + return delta_ != other.delta_; + } + constexpr bool operator<(TimeDelta other) const { + return delta_ < other.delta_; + } + constexpr bool operator<=(TimeDelta other) const { + return delta_ <= other.delta_; + } + constexpr bool operator>(TimeDelta other) const { + return delta_ > other.delta_; + } + constexpr bool operator>=(TimeDelta other) const { + return delta_ >= other.delta_; + } + + private: + friend constexpr int64_t time_internal::SaturatedAdd(int64_t value, + TimeDelta delta); + friend constexpr int64_t time_internal::SaturatedSub(int64_t value, + TimeDelta delta); + + // Constructs a delta given the duration in microseconds. This is private + // to avoid confusion by callers with an integer constructor. Use + // FromSeconds, FromMilliseconds, etc. instead. + constexpr explicit TimeDelta(int64_t delta_us) : delta_(delta_us) {} + + // Private method to build a delta from a double. + static constexpr TimeDelta FromDouble(double value); + + // Private method to build a delta from the product of a user-provided value + // and a known-positive value. + static constexpr TimeDelta FromProduct(int64_t value, int64_t positive_value); + + // Delta in microseconds. + int64_t delta_; +}; + +template <typename T> +constexpr TimeDelta operator*(T a, TimeDelta td) { + return td * a; +} + +// For logging use only. +BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeDelta time_delta); + +// Do not reference the time_internal::TimeBase template class directly. Please +// use one of the time subclasses instead, and only reference the public +// TimeBase members via those classes. +namespace time_internal { + +constexpr int64_t SaturatedAdd(int64_t value, TimeDelta delta) { + // Treat Min/Max() as +/- infinity (additions involving two infinities are + // only valid if signs match). + if (delta.is_max()) { + CHECK_GT(value, std::numeric_limits<int64_t>::min()); + return std::numeric_limits<int64_t>::max(); + } else if (delta.is_min()) { + CHECK_LT(value, std::numeric_limits<int64_t>::max()); + return std::numeric_limits<int64_t>::min(); + } + + return base::ClampAdd(value, delta.delta_); +} + +constexpr int64_t SaturatedSub(int64_t value, TimeDelta delta) { + // Treat Min/Max() as +/- infinity (subtractions involving two infinities are + // only valid if signs are opposite). + if (delta.is_max()) { + CHECK_LT(value, std::numeric_limits<int64_t>::max()); + return std::numeric_limits<int64_t>::min(); + } else if (delta.is_min()) { + CHECK_GT(value, std::numeric_limits<int64_t>::min()); + return std::numeric_limits<int64_t>::max(); + } + + return base::ClampSub(value, delta.delta_); +} + +// TimeBase-------------------------------------------------------------------- + +// Provides value storage and comparison/math operations common to all time +// classes. Each subclass provides for strong type-checking to ensure +// semantically meaningful comparison/math of time values from the same clock +// source or timeline. +template<class TimeClass> +class TimeBase { + public: + static constexpr int64_t kHoursPerDay = 24; + static constexpr int64_t kSecondsPerMinute = 60; + static constexpr int64_t kSecondsPerHour = 60 * kSecondsPerMinute; + static constexpr int64_t kMillisecondsPerSecond = 1000; + static constexpr int64_t kMillisecondsPerDay = + kMillisecondsPerSecond * 60 * 60 * kHoursPerDay; + static constexpr int64_t kMicrosecondsPerMillisecond = 1000; + static constexpr int64_t kMicrosecondsPerSecond = + kMicrosecondsPerMillisecond * kMillisecondsPerSecond; + static constexpr int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; + static constexpr int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; + static constexpr int64_t kMicrosecondsPerDay = + kMicrosecondsPerHour * kHoursPerDay; + static constexpr int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; + static constexpr int64_t kNanosecondsPerMicrosecond = 1000; + static constexpr int64_t kNanosecondsPerSecond = + kNanosecondsPerMicrosecond * kMicrosecondsPerSecond; + + // Returns true if this object has not been initialized. + // + // Warning: Be careful when writing code that performs math on time values, + // since it's possible to produce a valid "zero" result that should not be + // interpreted as a "null" value. + constexpr bool is_null() const { return us_ == 0; } + + // Returns true if this object represents the maximum/minimum time. + constexpr bool is_max() const { + return us_ == std::numeric_limits<int64_t>::max(); + } + constexpr bool is_min() const { + return us_ == std::numeric_limits<int64_t>::min(); + } + + // Returns the maximum/minimum times, which should be greater/less than than + // any reasonable time with which we might compare it. + static constexpr TimeClass Max() { + return TimeClass(std::numeric_limits<int64_t>::max()); + } + + static constexpr TimeClass Min() { + return TimeClass(std::numeric_limits<int64_t>::min()); + } + + // For serializing only. Use FromInternalValue() to reconstitute. Please don't + // use this and do arithmetic on it, as it is more error prone than using the + // provided operators. + // + // DEPRECATED - Do not use in new code. For serializing Time values, prefer + // Time::ToDeltaSinceWindowsEpoch().InMicroseconds(). http://crbug.com/634507 + constexpr int64_t ToInternalValue() const { return us_; } + + // The amount of time since the origin (or "zero") point. This is a syntactic + // convenience to aid in code readability, mainly for debugging/testing use + // cases. + // + // Warning: While the Time subclass has a fixed origin point, the origin for + // the other subclasses can vary each time the application is restarted. + constexpr TimeDelta since_origin() const { + return TimeDelta::FromMicroseconds(us_); + } + + constexpr TimeClass& operator=(TimeClass other) { + us_ = other.us_; + return *(static_cast<TimeClass*>(this)); + } + + // Compute the difference between two times. + constexpr TimeDelta operator-(TimeClass other) const { + return TimeDelta::FromMicroseconds(us_ - other.us_); + } + + // Return a new time modified by some delta. + constexpr TimeClass operator+(TimeDelta delta) const { + return TimeClass(time_internal::SaturatedAdd(us_, delta)); + } + constexpr TimeClass operator-(TimeDelta delta) const { + return TimeClass(time_internal::SaturatedSub(us_, delta)); + } + + // Modify by some time delta. + constexpr TimeClass& operator+=(TimeDelta delta) { + return static_cast<TimeClass&>(*this = (*this + delta)); + } + constexpr TimeClass& operator-=(TimeDelta delta) { + return static_cast<TimeClass&>(*this = (*this - delta)); + } + + // Comparison operators + constexpr bool operator==(TimeClass other) const { return us_ == other.us_; } + constexpr bool operator!=(TimeClass other) const { return us_ != other.us_; } + constexpr bool operator<(TimeClass other) const { return us_ < other.us_; } + constexpr bool operator<=(TimeClass other) const { return us_ <= other.us_; } + constexpr bool operator>(TimeClass other) const { return us_ > other.us_; } + constexpr bool operator>=(TimeClass other) const { return us_ >= other.us_; } + + protected: + constexpr explicit TimeBase(int64_t us) : us_(us) {} + + // Time value in a microsecond timebase. + int64_t us_; +}; + +} // namespace time_internal + +template <class TimeClass> +inline constexpr TimeClass operator+(TimeDelta delta, TimeClass t) { + return t + delta; +} + +// Time ----------------------------------------------------------------------- + +// Represents a wall clock time in UTC. Values are not guaranteed to be +// monotonically non-decreasing and are subject to large amounts of skew. +// Time is stored internally as microseconds since the Windows epoch (1601). +class BASE_EXPORT Time : public time_internal::TimeBase<Time> { + public: + // Offset of UNIX epoch (1970-01-01 00:00:00 UTC) from Windows FILETIME epoch + // (1601-01-01 00:00:00 UTC), in microseconds. This value is derived from the + // following: ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the number + // of leap year days between 1601 and 1970: (1970-1601)/4 excluding 1700, + // 1800, and 1900. + static constexpr int64_t kTimeTToMicrosecondsOffset = + INT64_C(11644473600000000); + +#if defined(OS_WIN) + // To avoid overflow in QPC to Microseconds calculations, since we multiply + // by kMicrosecondsPerSecond, then the QPC value should not exceed + // (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply. + static constexpr int64_t kQPCOverflowThreshold = INT64_C(0x8637BD05AF7); +#endif + +// kExplodedMinYear and kExplodedMaxYear define the platform-specific limits +// for values passed to FromUTCExploded() and FromLocalExploded(). Those +// functions will return false if passed values outside these limits. The limits +// are inclusive, meaning that the API should support all dates within a given +// limit year. +#if defined(OS_WIN) + static constexpr int kExplodedMinYear = 1601; + static constexpr int kExplodedMaxYear = 30827; +#elif defined(OS_IOS) && !__LP64__ + static constexpr int kExplodedMinYear = std::numeric_limits<int>::min(); + static constexpr int kExplodedMaxYear = std::numeric_limits<int>::max(); +#elif defined(OS_MACOSX) + static constexpr int kExplodedMinYear = 1902; + static constexpr int kExplodedMaxYear = std::numeric_limits<int>::max(); +#elif defined(OS_ANDROID) + // Though we use 64-bit time APIs on both 32 and 64 bit Android, some OS + // versions like KitKat (ARM but not x86 emulator) can't handle some early + // dates (e.g. before 1170). So we set min conservatively here. + static constexpr int kExplodedMinYear = 1902; + static constexpr int kExplodedMaxYear = std::numeric_limits<int>::max(); +#else + static constexpr int kExplodedMinYear = + (sizeof(time_t) == 4 ? 1902 : std::numeric_limits<int>::min()); + static constexpr int kExplodedMaxYear = + (sizeof(time_t) == 4 ? 2037 : std::numeric_limits<int>::max()); +#endif + + // Represents an exploded time that can be formatted nicely. This is kind of + // like the Win32 SYSTEMTIME structure or the Unix "struct tm" with a few + // additions and changes to prevent errors. + struct BASE_EXPORT Exploded { + int year; // Four digit year "2007" + int month; // 1-based month (values 1 = January, etc.) + int day_of_week; // 0-based day of week (0 = Sunday, etc.) + int day_of_month; // 1-based day of month (1-31) + int hour; // Hour within the current day (0-23) + int minute; // Minute within the current hour (0-59) + int second; // Second within the current minute (0-59 plus leap + // seconds which may take it up to 60). + int millisecond; // Milliseconds within the current second (0-999) + + // A cursory test for whether the data members are within their + // respective ranges. A 'true' return value does not guarantee the + // Exploded value can be successfully converted to a Time value. + bool HasValidValues() const; + }; + + // Contains the NULL time. Use Time::Now() to get the current time. + constexpr Time() : TimeBase(0) {} + + // Returns the time for epoch in Unix-like system (Jan 1, 1970). + static Time UnixEpoch(); + + // Returns the current time. Watch out, the system might adjust its clock + // in which case time will actually go backwards. We don't guarantee that + // times are increasing, or that two calls to Now() won't be the same. + static Time Now(); + + // Returns the current time. Same as Now() except that this function always + // uses system time so that there are no discrepancies between the returned + // time and system time even on virtual environments including our test bot. + // For timing sensitive unittests, this function should be used. + static Time NowFromSystemTime(); + + // Converts to/from TimeDeltas relative to the Windows epoch (1601-01-01 + // 00:00:00 UTC). Prefer these methods for opaque serialization and + // deserialization of time values, e.g. + // + // // Serialization: + // base::Time last_updated = ...; + // SaveToDatabase(last_updated.ToDeltaSinceWindowsEpoch().InMicroseconds()); + // + // // Deserialization: + // base::Time last_updated = base::Time::FromDeltaSinceWindowsEpoch( + // base::TimeDelta::FromMicroseconds(LoadFromDatabase())); + static Time FromDeltaSinceWindowsEpoch(TimeDelta delta); + TimeDelta ToDeltaSinceWindowsEpoch() const; + + // Converts to/from time_t in UTC and a Time class. + static Time FromTimeT(time_t tt); + time_t ToTimeT() const; + + // Converts time to/from a double which is the number of seconds since epoch + // (Jan 1, 1970). Webkit uses this format to represent time. + // Because WebKit initializes double time value to 0 to indicate "not + // initialized", we map it to empty Time object that also means "not + // initialized". + static Time FromDoubleT(double dt); + double ToDoubleT() const; + +#if defined(OS_POSIX) || defined(OS_FUCHSIA) + // Converts the timespec structure to time. MacOS X 10.8.3 (and tentatively, + // earlier versions) will have the |ts|'s tv_nsec component zeroed out, + // having a 1 second resolution, which agrees with + // https://developer.apple.com/legacy/library/#technotes/tn/tn1150.html#HFSPlusDates. + static Time FromTimeSpec(const timespec& ts); +#endif + + // Converts to/from the Javascript convention for times, a number of + // milliseconds since the epoch: + // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/getTime. + // + // Don't use ToJsTime() in new code, since it contains a subtle hack (only + // exactly 1601-01-01 00:00 UTC is represented as 1970-01-01 00:00 UTC), and + // that is not appropriate for general use. Try to use ToJsTimeIgnoringNull() + // unless you have a very good reason to use ToJsTime(). + static Time FromJsTime(double ms_since_epoch); + double ToJsTime() const; + double ToJsTimeIgnoringNull() const; + + // Converts to/from Java convention for times, a number of milliseconds since + // the epoch. Because the Java format has less resolution, converting to Java + // time is a lossy operation. + static Time FromJavaTime(int64_t ms_since_epoch); + int64_t ToJavaTime() const; + +#if defined(OS_POSIX) || defined(OS_FUCHSIA) + static Time FromTimeVal(struct timeval t); + struct timeval ToTimeVal() const; +#endif + +#if defined(OS_FUCHSIA) + static Time FromZxTime(zx_time_t time); + zx_time_t ToZxTime() const; +#endif + +#if defined(OS_MACOSX) + static Time FromCFAbsoluteTime(CFAbsoluteTime t); + CFAbsoluteTime ToCFAbsoluteTime() const; +#endif + +#if defined(OS_WIN) + static Time FromFileTime(FILETIME ft); + FILETIME ToFileTime() const; + + // The minimum time of a low resolution timer. This is basically a windows + // constant of ~15.6ms. While it does vary on some older OS versions, we'll + // treat it as static across all windows versions. + static const int kMinLowResolutionThresholdMs = 16; + + // Enable or disable Windows high resolution timer. + static void EnableHighResolutionTimer(bool enable); + + // Read the minimum timer interval from the feature list. This should be + // called once after the feature list is initialized. This is needed for + // an experiment - see https://crbug.com/927165 + static void ReadMinTimerIntervalLowResMs(); + + // Activates or deactivates the high resolution timer based on the |activate| + // flag. If the HighResolutionTimer is not Enabled (see + // EnableHighResolutionTimer), this function will return false. Otherwise + // returns true. Each successful activate call must be paired with a + // subsequent deactivate call. + // All callers to activate the high resolution timer must eventually call + // this function to deactivate the high resolution timer. + static bool ActivateHighResolutionTimer(bool activate); + + // Returns true if the high resolution timer is both enabled and activated. + // This is provided for testing only, and is not tracked in a thread-safe + // way. + static bool IsHighResolutionTimerInUse(); + + // The following two functions are used to report the fraction of elapsed time + // that the high resolution timer is activated. + // ResetHighResolutionTimerUsage() resets the cumulative usage and starts the + // measurement interval and GetHighResolutionTimerUsage() returns the + // percentage of time since the reset that the high resolution timer was + // activated. + // ResetHighResolutionTimerUsage() must be called at least once before calling + // GetHighResolutionTimerUsage(); otherwise the usage result would be + // undefined. + static void ResetHighResolutionTimerUsage(); + static double GetHighResolutionTimerUsage(); +#endif // defined(OS_WIN) + + // Converts an exploded structure representing either the local time or UTC + // into a Time class. Returns false on a failure when, for example, a day of + // month is set to 31 on a 28-30 day month. Returns Time(0) on overflow. + static bool FromUTCExploded(const Exploded& exploded, + Time* time) WARN_UNUSED_RESULT { + return FromExploded(false, exploded, time); + } + static bool FromLocalExploded(const Exploded& exploded, + Time* time) WARN_UNUSED_RESULT { + return FromExploded(true, exploded, time); + } + + // Converts a string representation of time to a Time object. + // An example of a time string which is converted is as below:- + // "Tue, 15 Nov 1994 12:45:26 GMT". If the timezone is not specified + // in the input string, FromString assumes local time and FromUTCString + // assumes UTC. A timezone that cannot be parsed (e.g. "UTC" which is not + // specified in RFC822) is treated as if the timezone is not specified. + // + // WARNING: the underlying converter is very permissive. For example: it is + // not checked whether a given day of the week matches the date; Feb 29 + // silently becomes Mar 1 in non-leap years; under certain conditions, whole + // English sentences may be parsed successfully and yield unexpected results. + // + // TODO(iyengar) Move the FromString/FromTimeT/ToTimeT/FromFileTime to + // a new time converter class. + static bool FromString(const char* time_string, + Time* parsed_time) WARN_UNUSED_RESULT { + return FromStringInternal(time_string, true, parsed_time); + } + static bool FromUTCString(const char* time_string, + Time* parsed_time) WARN_UNUSED_RESULT { + return FromStringInternal(time_string, false, parsed_time); + } + + // Fills the given exploded structure with either the local time or UTC from + // this time structure (containing UTC). + void UTCExplode(Exploded* exploded) const { + return Explode(false, exploded); + } + void LocalExplode(Exploded* exploded) const { + return Explode(true, exploded); + } + + // The following two functions round down the time to the nearest day in + // either UTC or local time. It will represent midnight on that day. + Time UTCMidnight() const { return Midnight(false); } + Time LocalMidnight() const { return Midnight(true); } + + // Converts an integer value representing Time to a class. This may be used + // when deserializing a |Time| structure, using a value known to be + // compatible. It is not provided as a constructor because the integer type + // may be unclear from the perspective of a caller. + // + // DEPRECATED - Do not use in new code. For deserializing Time values, prefer + // Time::FromDeltaSinceWindowsEpoch(). http://crbug.com/634507 + static constexpr Time FromInternalValue(int64_t us) { return Time(us); } + + private: + friend class time_internal::TimeBase<Time>; + + constexpr explicit Time(int64_t microseconds_since_win_epoch) + : TimeBase(microseconds_since_win_epoch) {} + + // Explodes the given time to either local time |is_local = true| or UTC + // |is_local = false|. + void Explode(bool is_local, Exploded* exploded) const; + + // Unexplodes a given time assuming the source is either local time + // |is_local = true| or UTC |is_local = false|. Function returns false on + // failure and sets |time| to Time(0). Otherwise returns true and sets |time| + // to non-exploded time. + static bool FromExploded(bool is_local, + const Exploded& exploded, + Time* time) WARN_UNUSED_RESULT; + + // Rounds down the time to the nearest day in either local time + // |is_local = true| or UTC |is_local = false|. + Time Midnight(bool is_local) const; + + // Converts a string representation of time to a Time object. + // An example of a time string which is converted is as below:- + // "Tue, 15 Nov 1994 12:45:26 GMT". If the timezone is not specified + // in the input string, local time |is_local = true| or + // UTC |is_local = false| is assumed. A timezone that cannot be parsed + // (e.g. "UTC" which is not specified in RFC822) is treated as if the + // timezone is not specified. + static bool FromStringInternal(const char* time_string, + bool is_local, + Time* parsed_time) WARN_UNUSED_RESULT; + + // Comparison does not consider |day_of_week| when doing the operation. + static bool ExplodedMostlyEquals(const Exploded& lhs, + const Exploded& rhs) WARN_UNUSED_RESULT; + + // Converts the provided time in milliseconds since the Unix epoch (1970) to a + // Time object, avoiding overflows. + static bool FromMillisecondsSinceUnixEpoch(int64_t unix_milliseconds, + Time* time) WARN_UNUSED_RESULT; + + // Returns the milliseconds since the Unix epoch (1970), rounding the + // microseconds towards -infinity. + int64_t ToRoundedDownMillisecondsSinceUnixEpoch() const; +}; + +// static +constexpr TimeDelta TimeDelta::FromDays(int days) { + return days == std::numeric_limits<int>::max() + ? Max() + : TimeDelta(days * Time::kMicrosecondsPerDay); +} + +// static +constexpr TimeDelta TimeDelta::FromHours(int hours) { + return hours == std::numeric_limits<int>::max() + ? Max() + : TimeDelta(hours * Time::kMicrosecondsPerHour); +} + +// static +constexpr TimeDelta TimeDelta::FromMinutes(int minutes) { + return minutes == std::numeric_limits<int>::max() + ? Max() + : TimeDelta(minutes * Time::kMicrosecondsPerMinute); +} + +// static +constexpr TimeDelta TimeDelta::FromSeconds(int64_t secs) { + return FromProduct(secs, Time::kMicrosecondsPerSecond); +} + +// static +constexpr TimeDelta TimeDelta::FromMilliseconds(int64_t ms) { + return FromProduct(ms, Time::kMicrosecondsPerMillisecond); +} + +// static +constexpr TimeDelta TimeDelta::FromMicroseconds(int64_t us) { + return TimeDelta(us); +} + +// static +constexpr TimeDelta TimeDelta::FromNanoseconds(int64_t ns) { + return TimeDelta(ns / Time::kNanosecondsPerMicrosecond); +} + +// static +constexpr TimeDelta TimeDelta::FromSecondsD(double secs) { + return FromDouble(secs * Time::kMicrosecondsPerSecond); +} + +// static +constexpr TimeDelta TimeDelta::FromMillisecondsD(double ms) { + return FromDouble(ms * Time::kMicrosecondsPerMillisecond); +} + +// static +constexpr TimeDelta TimeDelta::FromMicrosecondsD(double us) { + return FromDouble(us); +} + +// static +constexpr TimeDelta TimeDelta::FromNanosecondsD(double ns) { + return FromDouble(ns / Time::kNanosecondsPerMicrosecond); +} + +// static +constexpr TimeDelta TimeDelta::Max() { + return TimeDelta(std::numeric_limits<int64_t>::max()); +} + +// static +constexpr TimeDelta TimeDelta::Min() { + return TimeDelta(std::numeric_limits<int64_t>::min()); +} + +// static +constexpr TimeDelta TimeDelta::FromDouble(double value) { + return TimeDelta(saturated_cast<int64_t>(value)); +} + +// static +constexpr TimeDelta TimeDelta::FromProduct(int64_t value, + int64_t positive_value) { + DCHECK(positive_value > 0); // NOLINT, DCHECK_GT isn't constexpr. + return value > std::numeric_limits<int64_t>::max() / positive_value + ? Max() + : value < std::numeric_limits<int64_t>::min() / positive_value + ? Min() + : TimeDelta(value * positive_value); +} + +// For logging use only. +BASE_EXPORT std::ostream& operator<<(std::ostream& os, Time time); + +// TimeTicks ------------------------------------------------------------------ + +// Represents monotonically non-decreasing clock time. +class BASE_EXPORT TimeTicks : public time_internal::TimeBase<TimeTicks> { + public: + // The underlying clock used to generate new TimeTicks. + enum class Clock { + FUCHSIA_ZX_CLOCK_MONOTONIC, + LINUX_CLOCK_MONOTONIC, + IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME, + MAC_MACH_ABSOLUTE_TIME, + WIN_QPC, + WIN_ROLLOVER_PROTECTED_TIME_GET_TIME + }; + + constexpr TimeTicks() : TimeBase(0) {} + + // Platform-dependent tick count representing "right now." When + // IsHighResolution() returns false, the resolution of the clock could be + // as coarse as ~15.6ms. Otherwise, the resolution should be no worse than one + // microsecond. + static TimeTicks Now(); + + // Returns true if the high resolution clock is working on this system and + // Now() will return high resolution values. Note that, on systems where the + // high resolution clock works but is deemed inefficient, the low resolution + // clock will be used instead. + static bool IsHighResolution() WARN_UNUSED_RESULT; + + // Returns true if TimeTicks is consistent across processes, meaning that + // timestamps taken on different processes can be safely compared with one + // another. (Note that, even on platforms where this returns true, time values + // from different threads that are within one tick of each other must be + // considered to have an ambiguous ordering.) + static bool IsConsistentAcrossProcesses() WARN_UNUSED_RESULT; + +#if defined(OS_FUCHSIA) + // Converts between TimeTicks and an ZX_CLOCK_MONOTONIC zx_time_t value. + static TimeTicks FromZxTime(zx_time_t nanos_since_boot); + zx_time_t ToZxTime() const; +#endif + +#if defined(OS_WIN) + // Translates an absolute QPC timestamp into a TimeTicks value. The returned + // value has the same origin as Now(). Do NOT attempt to use this if + // IsHighResolution() returns false. + static TimeTicks FromQPCValue(LONGLONG qpc_value); +#endif + +#if defined(OS_MACOSX) && !defined(OS_IOS) + static TimeTicks FromMachAbsoluteTime(uint64_t mach_absolute_time); +#endif // defined(OS_MACOSX) && !defined(OS_IOS) + +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) + // Converts to TimeTicks the value obtained from SystemClock.uptimeMillis(). + // Note: this convertion may be non-monotonic in relation to previously + // obtained TimeTicks::Now() values because of the truncation (to + // milliseconds) performed by uptimeMillis(). + static TimeTicks FromUptimeMillis(int64_t uptime_millis_value); +#endif + + // Get an estimate of the TimeTick value at the time of the UnixEpoch. Because + // Time and TimeTicks respond differently to user-set time and NTP + // adjustments, this number is only an estimate. Nevertheless, this can be + // useful when you need to relate the value of TimeTicks to a real time and + // date. Note: Upon first invocation, this function takes a snapshot of the + // realtime clock to establish a reference point. This function will return + // the same value for the duration of the application, but will be different + // in future application runs. + static TimeTicks UnixEpoch(); + + // Returns |this| snapped to the next tick, given a |tick_phase| and + // repeating |tick_interval| in both directions. |this| may be before, + // after, or equal to the |tick_phase|. + TimeTicks SnappedToNextTick(TimeTicks tick_phase, + TimeDelta tick_interval) const; + + // Returns an enum indicating the underlying clock being used to generate + // TimeTicks timestamps. This function should only be used for debugging and + // logging purposes. + static Clock GetClock(); + + // Converts an integer value representing TimeTicks to a class. This may be + // used when deserializing a |TimeTicks| structure, using a value known to be + // compatible. It is not provided as a constructor because the integer type + // may be unclear from the perspective of a caller. + // + // DEPRECATED - Do not use in new code. For deserializing TimeTicks values, + // prefer TimeTicks + TimeDelta(). http://crbug.com/634507 + static constexpr TimeTicks FromInternalValue(int64_t us) { + return TimeTicks(us); + } + + protected: +#if defined(OS_WIN) + typedef DWORD (*TickFunctionType)(void); + static TickFunctionType SetMockTickFunction(TickFunctionType ticker); +#endif + + private: + friend class time_internal::TimeBase<TimeTicks>; + + // Please use Now() to create a new object. This is for internal use + // and testing. + constexpr explicit TimeTicks(int64_t us) : TimeBase(us) {} +}; + +// For logging use only. +BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks); + +// ThreadTicks ---------------------------------------------------------------- + +// Represents a clock, specific to a particular thread, than runs only while the +// thread is running. +class BASE_EXPORT ThreadTicks : public time_internal::TimeBase<ThreadTicks> { + public: + constexpr ThreadTicks() : TimeBase(0) {} + + // Returns true if ThreadTicks::Now() is supported on this system. + static bool IsSupported() WARN_UNUSED_RESULT { +#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ + (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_ANDROID) || \ + defined(OS_FUCHSIA) + return true; +#elif defined(OS_WIN) + return IsSupportedWin(); +#else + return false; +#endif + } + + // Waits until the initialization is completed. Needs to be guarded with a + // call to IsSupported(). + static void WaitUntilInitialized() { +#if defined(OS_WIN) + WaitUntilInitializedWin(); +#endif + } + + // Returns thread-specific CPU-time on systems that support this feature. + // Needs to be guarded with a call to IsSupported(). Use this timer + // to (approximately) measure how much time the calling thread spent doing + // actual work vs. being de-scheduled. May return bogus results if the thread + // migrates to another CPU between two calls. Returns an empty ThreadTicks + // object until the initialization is completed. If a clock reading is + // absolutely needed, call WaitUntilInitialized() before this method. + static ThreadTicks Now(); + +#if defined(OS_WIN) + // Similar to Now() above except this returns thread-specific CPU time for an + // arbitrary thread. All comments for Now() method above apply apply to this + // method as well. + static ThreadTicks GetForThread(const PlatformThreadHandle& thread_handle); +#endif + + // Converts an integer value representing ThreadTicks to a class. This may be + // used when deserializing a |ThreadTicks| structure, using a value known to + // be compatible. It is not provided as a constructor because the integer type + // may be unclear from the perspective of a caller. + // + // DEPRECATED - Do not use in new code. For deserializing ThreadTicks values, + // prefer ThreadTicks + TimeDelta(). http://crbug.com/634507 + static constexpr ThreadTicks FromInternalValue(int64_t us) { + return ThreadTicks(us); + } + + private: + friend class time_internal::TimeBase<ThreadTicks>; + + // Please use Now() or GetForThread() to create a new object. This is for + // internal use and testing. + constexpr explicit ThreadTicks(int64_t us) : TimeBase(us) {} + +#if defined(OS_WIN) + FRIEND_TEST_ALL_PREFIXES(TimeTicks, TSCTicksPerSecond); + +#if defined(ARCH_CPU_ARM64) + // TSCTicksPerSecond is not supported on Windows on Arm systems because the + // cycle-counting methods use the actual CPU cycle count, and not a consistent + // incrementing counter. +#else + // Returns the frequency of the TSC in ticks per second, or 0 if it hasn't + // been measured yet. Needs to be guarded with a call to IsSupported(). + // This method is declared here rather than in the anonymous namespace to + // allow testing. + static double TSCTicksPerSecond(); +#endif + + static bool IsSupportedWin() WARN_UNUSED_RESULT; + static void WaitUntilInitializedWin(); +#endif +}; + +// For logging use only. +BASE_EXPORT std::ostream& operator<<(std::ostream& os, ThreadTicks time_ticks); + +} // namespace base + +#endif // BASE_TIME_TIME_H_ diff --git a/security/sandbox/chromium/base/time/time_exploded_posix.cc b/security/sandbox/chromium/base/time/time_exploded_posix.cc new file mode 100644 index 0000000000..ca8a7880bf --- /dev/null +++ b/security/sandbox/chromium/base/time/time_exploded_posix.cc @@ -0,0 +1,287 @@ +// 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 - kMillisecondsPerSecond + 1) / kMillisecondsPerSecond; + // Make this nonnegative (and between 0 and 999 inclusive). + millisecond = milliseconds % kMillisecondsPerSecond; + if (millisecond < 0) + millisecond += kMillisecondsPerSecond; + } + + struct tm timestruct; + SysTimeToTimeStruct(seconds, ×truct, 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(×truct, 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(×truct, is_local); + + timestruct = timestruct0; + timestruct.tm_isdst = 1; + int64_t seconds_isdst1 = SysTimeFromTimeStruct(×truct, 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 diff --git a/security/sandbox/chromium/base/time/time_now_posix.cc b/security/sandbox/chromium/base/time/time_now_posix.cc new file mode 100644 index 0000000000..4ce93c0811 --- /dev/null +++ b/security/sandbox/chromium/base/time/time_now_posix.cc @@ -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 diff --git a/security/sandbox/chromium/base/time/time_override.h b/security/sandbox/chromium/base/time/time_override.h new file mode 100644 index 0000000000..ad3180c62a --- /dev/null +++ b/security/sandbox/chromium/base/time/time_override.h @@ -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_ diff --git a/security/sandbox/chromium/base/time/time_win.cc b/security/sandbox/chromium/base/time/time_win.cc new file mode 100644 index 0000000000..c1976e64a6 --- /dev/null +++ b/security/sandbox/chromium/base/time/time_win.cc @@ -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 diff --git a/security/sandbox/chromium/base/time/time_win_features.cc b/security/sandbox/chromium/base/time/time_win_features.cc new file mode 100644 index 0000000000..edf3024e70 --- /dev/null +++ b/security/sandbox/chromium/base/time/time_win_features.cc @@ -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 diff --git a/security/sandbox/chromium/base/time/time_win_features.h b/security/sandbox/chromium/base/time/time_win_features.h new file mode 100644 index 0000000000..b586ec2419 --- /dev/null +++ b/security/sandbox/chromium/base/time/time_win_features.h @@ -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_ |