Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
4
TMessagesProj/jni/voip/webrtc/base/time/OWNERS
Normal file
4
TMessagesProj/jni/voip/webrtc/base/time/OWNERS
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
gab@chromium.org
|
||||
miu@chromium.org
|
||||
|
||||
# COMPONENT: Internals>Core
|
||||
11
TMessagesProj/jni/voip/webrtc/base/time/clock.cc
Normal file
11
TMessagesProj/jni/voip/webrtc/base/time/clock.cc
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/clock.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
Clock::~Clock() = default;
|
||||
|
||||
} // namespace base
|
||||
40
TMessagesProj/jni/voip/webrtc/base/time/clock.h
Normal file
40
TMessagesProj/jni/voip/webrtc/base/time/clock.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_TIME_CLOCK_H_
|
||||
#define BASE_TIME_CLOCK_H_
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/time/time.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// A Clock is an interface for objects that vend Times. It is
|
||||
// intended to be able to test the behavior of classes with respect to
|
||||
// time.
|
||||
//
|
||||
// See DefaultClock (base/time/default_clock.h) for the default
|
||||
// implementation that simply uses Time::Now().
|
||||
//
|
||||
// (An implementation that uses Time::SystemTime() should be added as
|
||||
// needed.)
|
||||
//
|
||||
// See SimpleTestClock (base/test/simple_test_clock.h) for a simple
|
||||
// test implementation.
|
||||
//
|
||||
// See TickClock (base/time/tick_clock.h) for the equivalent interface for
|
||||
// TimeTicks.
|
||||
class BASE_EXPORT Clock {
|
||||
public:
|
||||
virtual ~Clock();
|
||||
|
||||
// Now() must be safe to call from any thread. The caller cannot
|
||||
// make any ordering assumptions about the returned Time. For
|
||||
// example, the system clock may change to an earlier time.
|
||||
virtual Time Now() const = 0;
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_TIME_CLOCK_H_
|
||||
23
TMessagesProj/jni/voip/webrtc/base/time/default_clock.cc
Normal file
23
TMessagesProj/jni/voip/webrtc/base/time/default_clock.cc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/default_clock.h"
|
||||
|
||||
#include "base/no_destructor.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
DefaultClock::~DefaultClock() = default;
|
||||
|
||||
Time DefaultClock::Now() const {
|
||||
return Time::Now();
|
||||
}
|
||||
|
||||
// static
|
||||
DefaultClock* DefaultClock::GetInstance() {
|
||||
static base::NoDestructor<DefaultClock> instance;
|
||||
return instance.get();
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
28
TMessagesProj/jni/voip/webrtc/base/time/default_clock.h
Normal file
28
TMessagesProj/jni/voip/webrtc/base/time/default_clock.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_TIME_DEFAULT_CLOCK_H_
|
||||
#define BASE_TIME_DEFAULT_CLOCK_H_
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/time/clock.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// DefaultClock is a Clock implementation that uses Time::Now().
|
||||
class BASE_EXPORT DefaultClock : public Clock {
|
||||
public:
|
||||
~DefaultClock() override;
|
||||
|
||||
// Simply returns Time::Now().
|
||||
Time Now() const override;
|
||||
|
||||
// Returns a shared instance of DefaultClock. This is thread-safe.
|
||||
static DefaultClock* GetInstance();
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_TIME_DEFAULT_CLOCK_H_
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/default_tick_clock.h"
|
||||
|
||||
#include "base/no_destructor.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
DefaultTickClock::~DefaultTickClock() = default;
|
||||
|
||||
TimeTicks DefaultTickClock::NowTicks() const {
|
||||
return TimeTicks::Now();
|
||||
}
|
||||
|
||||
// static
|
||||
const DefaultTickClock* DefaultTickClock::GetInstance() {
|
||||
static const base::NoDestructor<DefaultTickClock> default_tick_clock;
|
||||
return default_tick_clock.get();
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
32
TMessagesProj/jni/voip/webrtc/base/time/default_tick_clock.h
Normal file
32
TMessagesProj/jni/voip/webrtc/base/time/default_tick_clock.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_TIME_DEFAULT_TICK_CLOCK_H_
|
||||
#define BASE_TIME_DEFAULT_TICK_CLOCK_H_
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/time/tick_clock.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// DefaultTickClock is a TickClock implementation that uses TimeTicks::Now().
|
||||
// This is typically used by components that expose a SetTickClockForTesting().
|
||||
// Note: Overriding Time/TimeTicks altogether via
|
||||
// TaskEnvironment::TimeSource::MOCK_TIME is now the preferred of
|
||||
// overriding time in unit tests. As such, there shouldn't be many new use cases
|
||||
// for TickClock/DefaultTickClock anymore.
|
||||
class BASE_EXPORT DefaultTickClock : public TickClock {
|
||||
public:
|
||||
~DefaultTickClock() override;
|
||||
|
||||
// Simply returns TimeTicks::Now().
|
||||
TimeTicks NowTicks() const override;
|
||||
|
||||
// Returns a shared instance of DefaultTickClock. This is thread-safe.
|
||||
static const DefaultTickClock* GetInstance();
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_TIME_DEFAULT_TICK_CLOCK_H_
|
||||
11
TMessagesProj/jni/voip/webrtc/base/time/tick_clock.cc
Normal file
11
TMessagesProj/jni/voip/webrtc/base/time/tick_clock.cc
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/tick_clock.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
TickClock::~TickClock() = default;
|
||||
|
||||
} // namespace base
|
||||
40
TMessagesProj/jni/voip/webrtc/base/time/tick_clock.h
Normal file
40
TMessagesProj/jni/voip/webrtc/base/time/tick_clock.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_TIME_TICK_CLOCK_H_
|
||||
#define BASE_TIME_TICK_CLOCK_H_
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/time/time.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// A TickClock is an interface for objects that vend TimeTicks. It is
|
||||
// intended to be able to test the behavior of classes with respect to
|
||||
// non-decreasing time.
|
||||
//
|
||||
// See DefaultTickClock (base/time/default_tick_clock.h) for the default
|
||||
// implementation that simply uses TimeTicks::Now().
|
||||
//
|
||||
// (Other implementations that use TimeTicks::NowFromSystemTime() should
|
||||
// be added as needed.)
|
||||
//
|
||||
// See SimpleTestTickClock (base/test/simple_test_tick_clock.h) for a
|
||||
// simple test implementation.
|
||||
//
|
||||
// See Clock (base/time/clock.h) for the equivalent interface for Times.
|
||||
class BASE_EXPORT TickClock {
|
||||
public:
|
||||
virtual ~TickClock();
|
||||
|
||||
// NowTicks() must be safe to call from any thread. The caller may
|
||||
// assume that NowTicks() is monotonic (but not strictly monotonic).
|
||||
// In other words, the returned TimeTicks will never decrease with
|
||||
// time, although they might "stand still".
|
||||
virtual TimeTicks NowTicks() const = 0;
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_TIME_TICK_CLOCK_H_
|
||||
490
TMessagesProj/jni/voip/webrtc/base/time/time.cc
Normal file
490
TMessagesProj/jni/voip/webrtc/base/time/time.cc
Normal file
|
|
@ -0,0 +1,490 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <ios>
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/third_party/nspr/prtime.h"
|
||||
#include "base/time/time_override.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace internal {
|
||||
|
||||
TimeNowFunction g_time_now_function = &subtle::TimeNowIgnoringOverride;
|
||||
|
||||
TimeNowFunction g_time_now_from_system_time_function =
|
||||
&subtle::TimeNowFromSystemTimeIgnoringOverride;
|
||||
|
||||
TimeTicksNowFunction g_time_ticks_now_function =
|
||||
&subtle::TimeTicksNowIgnoringOverride;
|
||||
|
||||
ThreadTicksNowFunction g_thread_ticks_now_function =
|
||||
&subtle::ThreadTicksNowIgnoringOverride;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// TimeDelta ------------------------------------------------------------------
|
||||
|
||||
int TimeDelta::InDays() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<int>::max();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return std::numeric_limits<int>::min();
|
||||
}
|
||||
return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
|
||||
}
|
||||
|
||||
int TimeDelta::InDaysFloored() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<int>::max();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return std::numeric_limits<int>::min();
|
||||
}
|
||||
int result = delta_ / Time::kMicrosecondsPerDay;
|
||||
int64_t remainder = delta_ - (result * Time::kMicrosecondsPerDay);
|
||||
if (remainder < 0) {
|
||||
--result; // Use floor(), not trunc() rounding behavior.
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int TimeDelta::InHours() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<int>::max();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return std::numeric_limits<int>::min();
|
||||
}
|
||||
return static_cast<int>(delta_ / Time::kMicrosecondsPerHour);
|
||||
}
|
||||
|
||||
int TimeDelta::InMinutes() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<int>::max();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return std::numeric_limits<int>::min();
|
||||
}
|
||||
return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute);
|
||||
}
|
||||
|
||||
double TimeDelta::InSecondsF() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
|
||||
}
|
||||
|
||||
int64_t TimeDelta::InSeconds() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<int64_t>::max();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return std::numeric_limits<int64_t>::min();
|
||||
}
|
||||
return delta_ / Time::kMicrosecondsPerSecond;
|
||||
}
|
||||
|
||||
double TimeDelta::InMillisecondsF() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
|
||||
}
|
||||
|
||||
int64_t TimeDelta::InMilliseconds() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<int64_t>::max();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return std::numeric_limits<int64_t>::min();
|
||||
}
|
||||
return delta_ / Time::kMicrosecondsPerMillisecond;
|
||||
}
|
||||
|
||||
int64_t TimeDelta::InMillisecondsRoundedUp() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<int64_t>::max();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return std::numeric_limits<int64_t>::min();
|
||||
}
|
||||
int64_t result = delta_ / Time::kMicrosecondsPerMillisecond;
|
||||
int64_t remainder = delta_ - (result * Time::kMicrosecondsPerMillisecond);
|
||||
if (remainder > 0) {
|
||||
++result; // Use ceil(), not trunc() rounding behavior.
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
double TimeDelta::InMicrosecondsF() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
return static_cast<double>(delta_);
|
||||
}
|
||||
|
||||
int64_t TimeDelta::InNanoseconds() const {
|
||||
if (is_max()) {
|
||||
// Preserve max to prevent overflow.
|
||||
return std::numeric_limits<int64_t>::max();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min to prevent underflow.
|
||||
return std::numeric_limits<int64_t>::min();
|
||||
}
|
||||
return delta_ * Time::kNanosecondsPerMicrosecond;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) {
|
||||
return os << time_delta.InSecondsF() << " s";
|
||||
}
|
||||
|
||||
// Time -----------------------------------------------------------------------
|
||||
|
||||
// static
|
||||
Time Time::Now() {
|
||||
return internal::g_time_now_function();
|
||||
}
|
||||
|
||||
// static
|
||||
Time Time::NowFromSystemTime() {
|
||||
// Just use g_time_now_function because it returns the system time.
|
||||
return internal::g_time_now_from_system_time_function();
|
||||
}
|
||||
|
||||
// static
|
||||
Time Time::FromDeltaSinceWindowsEpoch(TimeDelta delta) {
|
||||
return Time(delta.InMicroseconds());
|
||||
}
|
||||
|
||||
TimeDelta Time::ToDeltaSinceWindowsEpoch() const {
|
||||
return TimeDelta::FromMicroseconds(us_);
|
||||
}
|
||||
|
||||
// static
|
||||
Time Time::FromTimeT(time_t tt) {
|
||||
if (tt == 0)
|
||||
return Time(); // Preserve 0 so we can tell it doesn't exist.
|
||||
if (tt == std::numeric_limits<time_t>::max())
|
||||
return Max();
|
||||
return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSeconds(tt);
|
||||
}
|
||||
|
||||
time_t Time::ToTimeT() const {
|
||||
if (is_null())
|
||||
return 0; // Preserve 0 so we can tell it doesn't exist.
|
||||
if (is_max()) {
|
||||
// Preserve max without offset to prevent overflow.
|
||||
return std::numeric_limits<time_t>::max();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min without offset to prevent underflow.
|
||||
return std::numeric_limits<time_t>::min();
|
||||
}
|
||||
if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) {
|
||||
DLOG(WARNING) << "Overflow when converting base::Time with internal " <<
|
||||
"value " << us_ << " to time_t.";
|
||||
return std::numeric_limits<time_t>::max();
|
||||
}
|
||||
return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond;
|
||||
}
|
||||
|
||||
// static
|
||||
Time Time::FromDoubleT(double dt) {
|
||||
if (dt == 0 || std::isnan(dt))
|
||||
return Time(); // Preserve 0 so we can tell it doesn't exist.
|
||||
return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSecondsD(dt);
|
||||
}
|
||||
|
||||
double Time::ToDoubleT() const {
|
||||
if (is_null())
|
||||
return 0; // Preserve 0 so we can tell it doesn't exist.
|
||||
if (is_max()) {
|
||||
// Preserve max without offset to prevent overflow.
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min without offset to prevent underflow.
|
||||
return -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
|
||||
static_cast<double>(kMicrosecondsPerSecond));
|
||||
}
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
// static
|
||||
Time Time::FromTimeSpec(const timespec& ts) {
|
||||
return FromDoubleT(ts.tv_sec +
|
||||
static_cast<double>(ts.tv_nsec) /
|
||||
base::Time::kNanosecondsPerSecond);
|
||||
}
|
||||
#endif
|
||||
|
||||
// static
|
||||
Time Time::FromJsTime(double ms_since_epoch) {
|
||||
// The epoch is a valid time, so this constructor doesn't interpret
|
||||
// 0 as the null time.
|
||||
return Time(kTimeTToMicrosecondsOffset) +
|
||||
TimeDelta::FromMillisecondsD(ms_since_epoch);
|
||||
}
|
||||
|
||||
double Time::ToJsTime() const {
|
||||
if (is_null()) {
|
||||
// Preserve 0 so the invalid result doesn't depend on the platform.
|
||||
return 0;
|
||||
}
|
||||
return ToJsTimeIgnoringNull();
|
||||
}
|
||||
|
||||
double Time::ToJsTimeIgnoringNull() const {
|
||||
if (is_max()) {
|
||||
// Preserve max without offset to prevent overflow.
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min without offset to prevent underflow.
|
||||
return -std::numeric_limits<double>::infinity();
|
||||
}
|
||||
return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
|
||||
kMicrosecondsPerMillisecond);
|
||||
}
|
||||
|
||||
Time Time::FromJavaTime(int64_t ms_since_epoch) {
|
||||
return base::Time::UnixEpoch() +
|
||||
base::TimeDelta::FromMilliseconds(ms_since_epoch);
|
||||
}
|
||||
|
||||
int64_t Time::ToJavaTime() const {
|
||||
if (is_null()) {
|
||||
// Preserve 0 so the invalid result doesn't depend on the platform.
|
||||
return 0;
|
||||
}
|
||||
if (is_max()) {
|
||||
// Preserve max without offset to prevent overflow.
|
||||
return std::numeric_limits<int64_t>::max();
|
||||
}
|
||||
if (is_min()) {
|
||||
// Preserve min without offset to prevent underflow.
|
||||
return std::numeric_limits<int64_t>::min();
|
||||
}
|
||||
return ((us_ - kTimeTToMicrosecondsOffset) /
|
||||
kMicrosecondsPerMillisecond);
|
||||
}
|
||||
|
||||
// static
|
||||
Time Time::UnixEpoch() {
|
||||
Time time;
|
||||
time.us_ = kTimeTToMicrosecondsOffset;
|
||||
return time;
|
||||
}
|
||||
|
||||
Time Time::Midnight(bool is_local) const {
|
||||
Exploded exploded;
|
||||
Explode(is_local, &exploded);
|
||||
exploded.hour = 0;
|
||||
exploded.minute = 0;
|
||||
exploded.second = 0;
|
||||
exploded.millisecond = 0;
|
||||
Time out_time;
|
||||
if (FromExploded(is_local, exploded, &out_time)) {
|
||||
return out_time;
|
||||
} else if (is_local) {
|
||||
// Hitting this branch means 00:00:00am of the current day
|
||||
// does not exist (due to Daylight Saving Time in some countries
|
||||
// where clocks are shifted at midnight). In this case, midnight
|
||||
// should be defined as 01:00:00am.
|
||||
exploded.hour = 1;
|
||||
if (FromExploded(is_local, exploded, &out_time))
|
||||
return out_time;
|
||||
}
|
||||
// This function must not fail.
|
||||
NOTREACHED();
|
||||
return Time();
|
||||
}
|
||||
|
||||
// static
|
||||
bool Time::FromStringInternal(const char* time_string,
|
||||
bool is_local,
|
||||
Time* parsed_time) {
|
||||
DCHECK((time_string != nullptr) && (parsed_time != nullptr));
|
||||
|
||||
if (time_string[0] == '\0')
|
||||
return false;
|
||||
|
||||
PRTime result_time = 0;
|
||||
PRStatus result = PR_ParseTimeString(time_string,
|
||||
is_local ? PR_FALSE : PR_TRUE,
|
||||
&result_time);
|
||||
if (PR_SUCCESS != result)
|
||||
return false;
|
||||
|
||||
result_time += kTimeTToMicrosecondsOffset;
|
||||
*parsed_time = Time(result_time);
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool Time::ExplodedMostlyEquals(const Exploded& lhs, const Exploded& rhs) {
|
||||
return lhs.year == rhs.year && lhs.month == rhs.month &&
|
||||
lhs.day_of_month == rhs.day_of_month && lhs.hour == rhs.hour &&
|
||||
lhs.minute == rhs.minute && lhs.second == rhs.second &&
|
||||
lhs.millisecond == rhs.millisecond;
|
||||
}
|
||||
|
||||
// static
|
||||
bool Time::FromMillisecondsSinceUnixEpoch(int64_t unix_milliseconds,
|
||||
Time* time) {
|
||||
// Adjust the provided time from milliseconds since the Unix epoch (1970) to
|
||||
// microseconds since the Windows epoch (1601), avoiding overflows.
|
||||
base::CheckedNumeric<int64_t> checked_microseconds_win_epoch =
|
||||
unix_milliseconds;
|
||||
checked_microseconds_win_epoch *= kMicrosecondsPerMillisecond;
|
||||
checked_microseconds_win_epoch += kTimeTToMicrosecondsOffset;
|
||||
if (!checked_microseconds_win_epoch.IsValid()) {
|
||||
*time = base::Time(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
*time = Time(checked_microseconds_win_epoch.ValueOrDie());
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t Time::ToRoundedDownMillisecondsSinceUnixEpoch() const {
|
||||
// Adjust from Windows epoch (1601) to Unix epoch (1970).
|
||||
int64_t microseconds = us_ - kTimeTToMicrosecondsOffset;
|
||||
|
||||
// Round the microseconds towards -infinity.
|
||||
if (microseconds >= 0) {
|
||||
// In this case, rounding towards -infinity means rounding towards 0.
|
||||
return microseconds / kMicrosecondsPerMillisecond;
|
||||
} else {
|
||||
return (microseconds + 1) / kMicrosecondsPerMillisecond - 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, Time time) {
|
||||
Time::Exploded exploded;
|
||||
time.UTCExplode(&exploded);
|
||||
// Use StringPrintf because iostreams formatting is painful.
|
||||
return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC",
|
||||
exploded.year,
|
||||
exploded.month,
|
||||
exploded.day_of_month,
|
||||
exploded.hour,
|
||||
exploded.minute,
|
||||
exploded.second,
|
||||
exploded.millisecond);
|
||||
}
|
||||
|
||||
// TimeTicks ------------------------------------------------------------------
|
||||
|
||||
// static
|
||||
TimeTicks TimeTicks::Now() {
|
||||
return internal::g_time_ticks_now_function();
|
||||
}
|
||||
|
||||
// static
|
||||
TimeTicks TimeTicks::UnixEpoch() {
|
||||
static const base::NoDestructor<base::TimeTicks> epoch([]() {
|
||||
return subtle::TimeTicksNowIgnoringOverride() -
|
||||
(subtle::TimeNowIgnoringOverride() - Time::UnixEpoch());
|
||||
}());
|
||||
return *epoch;
|
||||
}
|
||||
|
||||
TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
|
||||
TimeDelta tick_interval) const {
|
||||
// |interval_offset| is the offset from |this| to the next multiple of
|
||||
// |tick_interval| after |tick_phase|, possibly negative if in the past.
|
||||
TimeDelta interval_offset = (tick_phase - *this) % tick_interval;
|
||||
// If |this| is exactly on the interval (i.e. offset==0), don't adjust.
|
||||
// Otherwise, if |tick_phase| was in the past, adjust forward to the next
|
||||
// tick after |this|.
|
||||
if (!interval_offset.is_zero() && tick_phase < *this)
|
||||
interval_offset += tick_interval;
|
||||
return *this + interval_offset;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
|
||||
// This function formats a TimeTicks object as "bogo-microseconds".
|
||||
// The origin and granularity of the count are platform-specific, and may very
|
||||
// from run to run. Although bogo-microseconds usually roughly correspond to
|
||||
// real microseconds, the only real guarantee is that the number never goes
|
||||
// down during a single run.
|
||||
const TimeDelta as_time_delta = time_ticks - TimeTicks();
|
||||
return os << as_time_delta.InMicroseconds() << " bogo-microseconds";
|
||||
}
|
||||
|
||||
// ThreadTicks ----------------------------------------------------------------
|
||||
|
||||
// static
|
||||
ThreadTicks ThreadTicks::Now() {
|
||||
return internal::g_thread_ticks_now_function();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) {
|
||||
const TimeDelta as_time_delta = thread_ticks - ThreadTicks();
|
||||
return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds";
|
||||
}
|
||||
|
||||
// Time::Exploded -------------------------------------------------------------
|
||||
|
||||
inline bool is_in_range(int value, int lo, int hi) {
|
||||
return lo <= value && value <= hi;
|
||||
}
|
||||
|
||||
bool Time::Exploded::HasValidValues() const {
|
||||
return is_in_range(month, 1, 12) &&
|
||||
is_in_range(day_of_week, 0, 6) &&
|
||||
is_in_range(day_of_month, 1, 31) &&
|
||||
is_in_range(hour, 0, 23) &&
|
||||
is_in_range(minute, 0, 59) &&
|
||||
is_in_range(second, 0, 60) &&
|
||||
is_in_range(millisecond, 0, 999);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
1113
TMessagesProj/jni/voip/webrtc/base/time/time.h
Normal file
1113
TMessagesProj/jni/voip/webrtc/base/time/time.h
Normal file
File diff suppressed because it is too large
Load diff
26
TMessagesProj/jni/voip/webrtc/base/time/time_android.cc
Normal file
26
TMessagesProj/jni/voip/webrtc/base/time/time_android.cc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// static
|
||||
TimeTicks TimeTicks::FromUptimeMillis(int64_t uptime_millis_value) {
|
||||
// The implementation of the SystemClock.uptimeMillis() in AOSP uses the same
|
||||
// clock as base::TimeTicks::Now(): clock_gettime(CLOCK_MONOTONIC), see in
|
||||
// platform/system/code:
|
||||
// 1. libutils/SystemClock.cpp
|
||||
// 2. libutils/Timers.cpp
|
||||
//
|
||||
// We are not aware of any motivations for Android OEMs to modify the AOSP
|
||||
// implementation of either uptimeMillis() or clock_gettime(CLOCK_MONOTONIC),
|
||||
// so we assume that there are no such customizations.
|
||||
//
|
||||
// Under these assumptions the conversion is as safe as copying the value of
|
||||
// base::TimeTicks::Now() with a loss of sub-millisecond precision.
|
||||
return TimeTicks(uptime_millis_value * Time::kMicrosecondsPerMillisecond);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// static
|
||||
TimeDelta TimeDelta::FromTimeSpec(const timespec& ts) {
|
||||
return TimeDelta(ts.tv_sec * Time::kMicrosecondsPerSecond +
|
||||
ts.tv_nsec / Time::kNanosecondsPerMicrosecond);
|
||||
}
|
||||
|
||||
struct timespec TimeDelta::ToTimeSpec() const {
|
||||
int64_t microseconds = InMicroseconds();
|
||||
time_t seconds = 0;
|
||||
if (microseconds >= Time::kMicrosecondsPerSecond) {
|
||||
seconds = InSeconds();
|
||||
microseconds -= seconds * Time::kMicrosecondsPerSecond;
|
||||
}
|
||||
struct timespec result = {
|
||||
seconds,
|
||||
static_cast<long>(microseconds * Time::kNanosecondsPerMicrosecond)};
|
||||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
Time Time::FromTimeVal(struct timeval t) {
|
||||
DCHECK_LT(t.tv_usec, static_cast<int>(Time::kMicrosecondsPerSecond));
|
||||
DCHECK_GE(t.tv_usec, 0);
|
||||
if (t.tv_usec == 0 && t.tv_sec == 0)
|
||||
return Time();
|
||||
if (t.tv_usec == static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1 &&
|
||||
t.tv_sec == std::numeric_limits<time_t>::max())
|
||||
return Max();
|
||||
return Time((static_cast<int64_t>(t.tv_sec) * Time::kMicrosecondsPerSecond) +
|
||||
t.tv_usec + kTimeTToMicrosecondsOffset);
|
||||
}
|
||||
|
||||
struct timeval Time::ToTimeVal() const {
|
||||
struct timeval result;
|
||||
if (is_null()) {
|
||||
result.tv_sec = 0;
|
||||
result.tv_usec = 0;
|
||||
return result;
|
||||
}
|
||||
if (is_max()) {
|
||||
result.tv_sec = std::numeric_limits<time_t>::max();
|
||||
result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1;
|
||||
return result;
|
||||
}
|
||||
int64_t us = us_ - kTimeTToMicrosecondsOffset;
|
||||
result.tv_sec = us / Time::kMicrosecondsPerSecond;
|
||||
result.tv_usec = us % Time::kMicrosecondsPerSecond;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
96
TMessagesProj/jni/voip/webrtc/base/time/time_exploded_icu.cc
Normal file
96
TMessagesProj/jni/voip/webrtc/base/time/time_exploded_icu.cc
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "third_party/icu/source/i18n/unicode/calendar.h"
|
||||
#include "third_party/icu/source/i18n/unicode/timezone.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
static_assert(
|
||||
sizeof(Time::Exploded::year) == sizeof(int32_t),
|
||||
"The sizes of Time::Exploded members and ICU date fields do not match.");
|
||||
|
||||
namespace {
|
||||
|
||||
// Returns a new icu::Calendar instance for the local time zone if |is_local|
|
||||
// and for GMT otherwise. Returns null on error.
|
||||
std::unique_ptr<icu::Calendar> CreateCalendar(bool is_local) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
std::unique_ptr<icu::Calendar> calendar =
|
||||
base::WrapUnique(is_local ? icu::Calendar::createInstance(status)
|
||||
: icu::Calendar::createInstance(
|
||||
*icu::TimeZone::getGMT(), status));
|
||||
CHECK(U_SUCCESS(status));
|
||||
|
||||
return calendar;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Time::Explode(bool is_local, Exploded* exploded) const {
|
||||
std::unique_ptr<icu::Calendar> calendar = CreateCalendar(is_local);
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
calendar->setTime(ToRoundedDownMillisecondsSinceUnixEpoch(), status);
|
||||
DCHECK(U_SUCCESS(status));
|
||||
|
||||
exploded->year = calendar->get(UCAL_YEAR, status);
|
||||
DCHECK(U_SUCCESS(status));
|
||||
|
||||
// ICU's UCalendarMonths is 0-based. E.g., 0 for January.
|
||||
exploded->month = calendar->get(UCAL_MONTH, status) + 1;
|
||||
DCHECK(U_SUCCESS(status));
|
||||
// ICU's UCalendarDaysOfWeek is 1-based. E.g., 1 for Sunday.
|
||||
exploded->day_of_week = calendar->get(UCAL_DAY_OF_WEEK, status) - 1;
|
||||
DCHECK(U_SUCCESS(status));
|
||||
exploded->day_of_month = calendar->get(UCAL_DAY_OF_MONTH, status);
|
||||
DCHECK(U_SUCCESS(status));
|
||||
exploded->hour = calendar->get(UCAL_HOUR_OF_DAY, status);
|
||||
DCHECK(U_SUCCESS(status));
|
||||
exploded->minute = calendar->get(UCAL_MINUTE, status);
|
||||
DCHECK(U_SUCCESS(status));
|
||||
exploded->second = calendar->get(UCAL_SECOND, status);
|
||||
DCHECK(U_SUCCESS(status));
|
||||
exploded->millisecond = calendar->get(UCAL_MILLISECOND, status);
|
||||
DCHECK(U_SUCCESS(status));
|
||||
}
|
||||
|
||||
// static
|
||||
bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
|
||||
// ICU's UCalendarMonths is 0-based. E.g., 0 for January.
|
||||
CheckedNumeric<int> month = exploded.month;
|
||||
month--;
|
||||
if (!month.IsValid()) {
|
||||
*time = Time(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<icu::Calendar> calendar = CreateCalendar(is_local);
|
||||
|
||||
// Cause getTime() to report an error if invalid dates, such as the 31st day
|
||||
// of February, are specified.
|
||||
calendar->setLenient(false);
|
||||
|
||||
calendar->set(exploded.year, month.ValueOrDie(), exploded.day_of_month,
|
||||
exploded.hour, exploded.minute, exploded.second);
|
||||
calendar->set(UCAL_MILLISECOND, exploded.millisecond);
|
||||
// Ignore exploded.day_of_week
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UDate date = calendar->getTime(status);
|
||||
if (U_FAILURE(status)) {
|
||||
*time = Time(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return FromMillisecondsSinceUnixEpoch(date, time);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
113
TMessagesProj/jni/voip/webrtc/base/time/time_exploded_ios.cc
Normal file
113
TMessagesProj/jni/voip/webrtc/base/time/time_exploded_ios.cc
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time.h"
|
||||
|
||||
#include <CoreFoundation/CFDate.h>
|
||||
#include <CoreFoundation/CFCalendar.h>
|
||||
#include <CoreFoundation/CFTimeZone.h>
|
||||
|
||||
#include "base/mac/scoped_cftyperef.h"
|
||||
|
||||
#if __LP64__
|
||||
#error Use posix implementation on 64-bit platforms.
|
||||
#endif // __LP64__
|
||||
|
||||
namespace base {
|
||||
|
||||
// Note: These implementations of Time::FromExploded() and Time::Explode() are
|
||||
// only used on iOS now. Since Mac is now always 64-bit, we can use the POSIX
|
||||
// versions of these functions as time_t is not capped at year 2038 on 64-bit
|
||||
// builds. The POSIX functions are preferred since they don't suffer from some
|
||||
// performance problems that are present in these implementations.
|
||||
// See crbug.com/781601, crbug.com/985061 for more details.
|
||||
|
||||
// static
|
||||
bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
|
||||
base::ScopedCFTypeRef<CFTimeZoneRef> time_zone(
|
||||
is_local
|
||||
? CFTimeZoneCopySystem()
|
||||
: CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0));
|
||||
base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier(
|
||||
kCFAllocatorDefault, kCFGregorianCalendar));
|
||||
CFCalendarSetTimeZone(gregorian, time_zone);
|
||||
CFAbsoluteTime absolute_time;
|
||||
// 'S' is not defined in componentDesc in Apple documentation, but can be
|
||||
// found at http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c
|
||||
CFCalendarComposeAbsoluteTime(
|
||||
gregorian, &absolute_time, "yMdHmsS", exploded.year, exploded.month,
|
||||
exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
|
||||
exploded.millisecond);
|
||||
CFAbsoluteTime seconds = absolute_time + kCFAbsoluteTimeIntervalSince1970;
|
||||
|
||||
// CFAbsolutTime is typedef of double. Convert seconds to
|
||||
// microseconds and then cast to int64. If
|
||||
// it cannot be suited to int64, then fail to avoid overflows.
|
||||
double microseconds =
|
||||
(seconds * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset;
|
||||
if (microseconds > std::numeric_limits<int64_t>::max() ||
|
||||
microseconds < std::numeric_limits<int64_t>::min()) {
|
||||
*time = Time(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
base::Time converted_time = Time(static_cast<int64_t>(microseconds));
|
||||
|
||||
// If |exploded.day_of_month| is set to 31
|
||||
// on a 28-30 day month, it will return the first day of the next month.
|
||||
// Thus round-trip the time and compare the initial |exploded| with
|
||||
// |utc_to_exploded| time.
|
||||
base::Time::Exploded to_exploded;
|
||||
if (!is_local)
|
||||
converted_time.UTCExplode(&to_exploded);
|
||||
else
|
||||
converted_time.LocalExplode(&to_exploded);
|
||||
|
||||
if (ExplodedMostlyEquals(to_exploded, exploded)) {
|
||||
*time = converted_time;
|
||||
return true;
|
||||
}
|
||||
|
||||
*time = Time(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
void Time::Explode(bool is_local, Exploded* exploded) const {
|
||||
// Avoid rounding issues, by only putting the integral number of seconds
|
||||
// (rounded towards -infinity) into a |CFAbsoluteTime| (which is a |double|).
|
||||
int64_t microsecond = us_ % kMicrosecondsPerSecond;
|
||||
if (microsecond < 0)
|
||||
microsecond += kMicrosecondsPerSecond;
|
||||
CFAbsoluteTime seconds = ((us_ - microsecond - kTimeTToMicrosecondsOffset) /
|
||||
kMicrosecondsPerSecond) -
|
||||
kCFAbsoluteTimeIntervalSince1970;
|
||||
|
||||
base::ScopedCFTypeRef<CFTimeZoneRef> time_zone(
|
||||
is_local
|
||||
? CFTimeZoneCopySystem()
|
||||
: CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0));
|
||||
base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier(
|
||||
kCFAllocatorDefault, kCFGregorianCalendar));
|
||||
CFCalendarSetTimeZone(gregorian, time_zone);
|
||||
int second, day_of_week;
|
||||
// 'E' sets the day of week, but is not defined in componentDesc in Apple
|
||||
// documentation. It can be found in open source code here:
|
||||
// http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c
|
||||
CFCalendarDecomposeAbsoluteTime(gregorian, seconds, "yMdHmsE",
|
||||
&exploded->year, &exploded->month,
|
||||
&exploded->day_of_month, &exploded->hour,
|
||||
&exploded->minute, &second, &day_of_week);
|
||||
// Make sure seconds are rounded down towards -infinity.
|
||||
exploded->second = floor(second);
|
||||
// |Exploded|'s convention for day of week is 0 = Sunday, i.e. different
|
||||
// from CF's 1 = Sunday.
|
||||
exploded->day_of_week = (day_of_week - 1) % 7;
|
||||
// Calculate milliseconds ourselves, since we rounded the |seconds|, making
|
||||
// sure to round towards -infinity.
|
||||
exploded->millisecond =
|
||||
(microsecond >= 0) ? microsecond / kMicrosecondsPerMillisecond
|
||||
: ((microsecond + 1) / kMicrosecondsPerMillisecond - 1);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
286
TMessagesProj/jni/voip/webrtc/base/time/time_exploded_posix.cc
Normal file
286
TMessagesProj/jni/voip/webrtc/base/time/time_exploded_posix.cc
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#if defined(OS_ANDROID) && !defined(__LP64__)
|
||||
#include <time64.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "base/numerics/safe_math.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if defined(OS_ANDROID)
|
||||
#include "base/os_compat_android.h"
|
||||
#elif defined(OS_NACL)
|
||||
#include "base/os_compat_nacl.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX) || defined(OS_IOS)
|
||||
static_assert(sizeof(time_t) >= 8, "Y2038 problem!");
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
// This prevents a crash on traversing the environment global and looking up
|
||||
// the 'TZ' variable in libc. See: crbug.com/390567.
|
||||
base::Lock* GetSysTimeToTimeStructLock() {
|
||||
static auto* lock = new base::Lock();
|
||||
return lock;
|
||||
}
|
||||
|
||||
// Define a system-specific SysTime that wraps either to a time_t or
|
||||
// a time64_t depending on the host system, and associated convertion.
|
||||
// See crbug.com/162007
|
||||
#if defined(OS_ANDROID) && !defined(__LP64__)
|
||||
typedef time64_t SysTime;
|
||||
|
||||
SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
|
||||
base::AutoLock locked(*GetSysTimeToTimeStructLock());
|
||||
if (is_local)
|
||||
return mktime64(timestruct);
|
||||
else
|
||||
return timegm64(timestruct);
|
||||
}
|
||||
|
||||
void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
|
||||
base::AutoLock locked(*GetSysTimeToTimeStructLock());
|
||||
if (is_local)
|
||||
localtime64_r(&t, timestruct);
|
||||
else
|
||||
gmtime64_r(&t, timestruct);
|
||||
}
|
||||
#elif defined(OS_AIX)
|
||||
// The function timegm is not available on AIX.
|
||||
time_t aix_timegm(struct tm* tm) {
|
||||
time_t ret;
|
||||
char* tz;
|
||||
|
||||
tz = getenv("TZ");
|
||||
if (tz) {
|
||||
tz = strdup(tz);
|
||||
}
|
||||
setenv("TZ", "GMT0", 1);
|
||||
tzset();
|
||||
ret = mktime(tm);
|
||||
if (tz) {
|
||||
setenv("TZ", tz, 1);
|
||||
free(tz);
|
||||
} else {
|
||||
unsetenv("TZ");
|
||||
}
|
||||
tzset();
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef time_t SysTime;
|
||||
|
||||
SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
|
||||
base::AutoLock locked(*GetSysTimeToTimeStructLock());
|
||||
if (is_local)
|
||||
return mktime(timestruct);
|
||||
else
|
||||
return aix_timegm(timestruct);
|
||||
}
|
||||
|
||||
void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
|
||||
base::AutoLock locked(*GetSysTimeToTimeStructLock());
|
||||
if (is_local)
|
||||
localtime_r(&t, timestruct);
|
||||
else
|
||||
gmtime_r(&t, timestruct);
|
||||
}
|
||||
|
||||
#else
|
||||
typedef time_t SysTime;
|
||||
|
||||
SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
|
||||
base::AutoLock locked(*GetSysTimeToTimeStructLock());
|
||||
return is_local ? mktime(timestruct) : timegm(timestruct);
|
||||
}
|
||||
|
||||
void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
|
||||
base::AutoLock locked(*GetSysTimeToTimeStructLock());
|
||||
if (is_local)
|
||||
localtime_r(&t, timestruct);
|
||||
else
|
||||
gmtime_r(&t, timestruct);
|
||||
}
|
||||
#endif // defined(OS_ANDROID) && !defined(__LP64__)
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace base {
|
||||
|
||||
void Time::Explode(bool is_local, Exploded* exploded) const {
|
||||
// The following values are all rounded towards -infinity.
|
||||
int64_t milliseconds = ToRoundedDownMillisecondsSinceUnixEpoch();
|
||||
SysTime seconds; // Seconds since epoch.
|
||||
int millisecond; // Exploded millisecond value (0-999).
|
||||
|
||||
// If the microseconds were negative, the rounded down milliseconds will also
|
||||
// be negative. For example, -1 us becomes -1 ms.
|
||||
if (milliseconds >= 0) {
|
||||
// Rounding towards -infinity <=> rounding towards 0, in this case.
|
||||
seconds = milliseconds / kMillisecondsPerSecond;
|
||||
millisecond = milliseconds % kMillisecondsPerSecond;
|
||||
} else {
|
||||
// Round these *down* (towards -infinity).
|
||||
seconds = (milliseconds + 1) / kMillisecondsPerSecond - 1;
|
||||
// Make this nonnegative (and between 0 and 999 inclusive).
|
||||
millisecond = milliseconds % kMillisecondsPerSecond;
|
||||
if (millisecond < 0)
|
||||
millisecond += kMillisecondsPerSecond;
|
||||
}
|
||||
|
||||
struct tm timestruct;
|
||||
SysTimeToTimeStruct(seconds, ×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
|
||||
96
TMessagesProj/jni/voip/webrtc/base/time/time_fuchsia.cc
Normal file
96
TMessagesProj/jni/voip/webrtc/base/time/time_fuchsia.cc
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time.h"
|
||||
|
||||
#include <zircon/syscalls.h>
|
||||
|
||||
#include "base/fuchsia/fuchsia_logging.h"
|
||||
#include "base/time/time_override.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// Time -----------------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
Time TimeNowIgnoringOverride() {
|
||||
zx_time_t nanos_since_unix_epoch;
|
||||
zx_status_t status = zx_clock_get(ZX_CLOCK_UTC, &nanos_since_unix_epoch);
|
||||
ZX_CHECK(status == ZX_OK, status);
|
||||
// The following expression will overflow in the year 289938 A.D.:
|
||||
return Time::FromZxTime(nanos_since_unix_epoch);
|
||||
}
|
||||
|
||||
Time TimeNowFromSystemTimeIgnoringOverride() {
|
||||
// Just use TimeNowIgnoringOverride() because it returns the system time.
|
||||
return TimeNowIgnoringOverride();
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
// TimeTicks ------------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
TimeTicks TimeTicksNowIgnoringOverride() {
|
||||
const zx_time_t nanos_since_boot = zx_clock_get_monotonic();
|
||||
CHECK(nanos_since_boot != 0);
|
||||
return TimeTicks::FromZxTime(nanos_since_boot);
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
// static
|
||||
TimeDelta TimeDelta::FromZxDuration(zx_duration_t nanos) {
|
||||
return TimeDelta::FromNanoseconds(nanos);
|
||||
}
|
||||
|
||||
zx_duration_t TimeDelta::ToZxDuration() const {
|
||||
return InNanoseconds();
|
||||
}
|
||||
|
||||
// static
|
||||
Time Time::FromZxTime(zx_time_t nanos_since_unix_epoch) {
|
||||
return Time::UnixEpoch() + TimeDelta::FromNanoseconds(nanos_since_unix_epoch);
|
||||
}
|
||||
|
||||
zx_time_t Time::ToZxTime() const {
|
||||
return (*this - Time::UnixEpoch()).InNanoseconds();
|
||||
}
|
||||
|
||||
// static
|
||||
TimeTicks::Clock TimeTicks::GetClock() {
|
||||
return Clock::FUCHSIA_ZX_CLOCK_MONOTONIC;
|
||||
}
|
||||
|
||||
// static
|
||||
bool TimeTicks::IsHighResolution() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool TimeTicks::IsConsistentAcrossProcesses() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
TimeTicks TimeTicks::FromZxTime(zx_time_t nanos_since_boot) {
|
||||
return TimeTicks() + TimeDelta::FromNanoseconds(nanos_since_boot);
|
||||
}
|
||||
|
||||
zx_time_t TimeTicks::ToZxTime() const {
|
||||
return (*this - TimeTicks()).InNanoseconds();
|
||||
}
|
||||
|
||||
// ThreadTicks ----------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
ThreadTicks ThreadTicksNowIgnoringOverride() {
|
||||
zx_time_t nanos_since_thread_started;
|
||||
zx_status_t status =
|
||||
zx_clock_get(ZX_CLOCK_THREAD, &nanos_since_thread_started);
|
||||
ZX_CHECK(status == ZX_OK, status);
|
||||
DCHECK(nanos_since_thread_started != 0);
|
||||
return ThreadTicks() + TimeDelta::FromNanoseconds(nanos_since_thread_started);
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
} // namespace base
|
||||
219
TMessagesProj/jni/voip/webrtc/base/time/time_mac.cc
Normal file
219
TMessagesProj/jni/voip/webrtc/base/time/time_mac.cc
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time.h"
|
||||
|
||||
#include <CoreFoundation/CFDate.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/mac/mach_logging.h"
|
||||
#include "base/mac/scoped_cftyperef.h"
|
||||
#include "base/mac/scoped_mach_port.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "base/time/time_override.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if defined(OS_IOS)
|
||||
#include <time.h>
|
||||
#include "base/ios/ios_util.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
||||
int64_t MachAbsoluteTimeToTicks(uint64_t mach_absolute_time) {
|
||||
static mach_timebase_info_data_t timebase_info;
|
||||
if (timebase_info.denom == 0) {
|
||||
// Zero-initialization of statics guarantees that denom will be 0 before
|
||||
// calling mach_timebase_info. mach_timebase_info will never set denom to
|
||||
// 0 as that would be invalid, so the zero-check can be used to determine
|
||||
// whether mach_timebase_info has already been called. This is
|
||||
// recommended by Apple's QA1398.
|
||||
kern_return_t kr = mach_timebase_info(&timebase_info);
|
||||
MACH_DCHECK(kr == KERN_SUCCESS, kr) << "mach_timebase_info";
|
||||
}
|
||||
|
||||
// timebase_info converts absolute time tick units into nanoseconds. Convert
|
||||
// to microseconds up front to stave off overflows.
|
||||
base::CheckedNumeric<uint64_t> result(mach_absolute_time /
|
||||
base::Time::kNanosecondsPerMicrosecond);
|
||||
result *= timebase_info.numer;
|
||||
result /= timebase_info.denom;
|
||||
|
||||
// Don't bother with the rollover handling that the Windows version does.
|
||||
// With numer and denom = 1 (the expected case), the 64-bit absolute time
|
||||
// reported in nanoseconds is enough to last nearly 585 years.
|
||||
return base::checked_cast<int64_t>(result.ValueOrDie());
|
||||
}
|
||||
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
|
||||
|
||||
// Returns monotonically growing number of ticks in microseconds since some
|
||||
// unspecified starting point.
|
||||
int64_t ComputeCurrentTicks() {
|
||||
#if defined(OS_IOS)
|
||||
// iOS 10 supports clock_gettime(CLOCK_MONOTONIC, ...), which is
|
||||
// around 15 times faster than sysctl() call. Use it if possible;
|
||||
// otherwise, fall back to sysctl().
|
||||
if (__builtin_available(iOS 10, *)) {
|
||||
struct timespec tp;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
|
||||
return (int64_t)tp.tv_sec * 1000000 + tp.tv_nsec / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
// On iOS mach_absolute_time stops while the device is sleeping. Instead use
|
||||
// now - KERN_BOOTTIME to get a time difference that is not impacted by clock
|
||||
// changes. KERN_BOOTTIME will be updated by the system whenever the system
|
||||
// clock change.
|
||||
struct timeval boottime;
|
||||
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
|
||||
size_t size = sizeof(boottime);
|
||||
int kr = sysctl(mib, base::size(mib), &boottime, &size, nullptr, 0);
|
||||
DCHECK_EQ(KERN_SUCCESS, kr);
|
||||
base::TimeDelta time_difference =
|
||||
base::subtle::TimeNowIgnoringOverride() -
|
||||
(base::Time::FromTimeT(boottime.tv_sec) +
|
||||
base::TimeDelta::FromMicroseconds(boottime.tv_usec));
|
||||
return time_difference.InMicroseconds();
|
||||
#else
|
||||
// mach_absolute_time is it when it comes to ticks on the Mac. Other calls
|
||||
// with less precision (such as TickCount) just call through to
|
||||
// mach_absolute_time.
|
||||
return MachAbsoluteTimeToTicks(mach_absolute_time());
|
||||
#endif // defined(OS_IOS)
|
||||
}
|
||||
|
||||
int64_t ComputeThreadTicks() {
|
||||
#if defined(OS_IOS)
|
||||
NOTREACHED();
|
||||
return 0;
|
||||
#else
|
||||
// The pthreads library keeps a cached reference to the thread port, which
|
||||
// does not have to be released like mach_thread_self() does.
|
||||
mach_port_t thread_port = pthread_mach_thread_np(pthread_self());
|
||||
if (thread_port == MACH_PORT_NULL) {
|
||||
DLOG(ERROR) << "Failed to get pthread_mach_thread_np()";
|
||||
return 0;
|
||||
}
|
||||
|
||||
mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT;
|
||||
thread_basic_info_data_t thread_info_data;
|
||||
|
||||
kern_return_t kr = thread_info(
|
||||
thread_port,
|
||||
THREAD_BASIC_INFO,
|
||||
reinterpret_cast<thread_info_t>(&thread_info_data),
|
||||
&thread_info_count);
|
||||
MACH_DCHECK(kr == KERN_SUCCESS, kr) << "thread_info";
|
||||
|
||||
base::CheckedNumeric<int64_t> absolute_micros(
|
||||
thread_info_data.user_time.seconds +
|
||||
thread_info_data.system_time.seconds);
|
||||
absolute_micros *= base::Time::kMicrosecondsPerSecond;
|
||||
absolute_micros += (thread_info_data.user_time.microseconds +
|
||||
thread_info_data.system_time.microseconds);
|
||||
return absolute_micros.ValueOrDie();
|
||||
#endif // defined(OS_IOS)
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace base {
|
||||
|
||||
// The Time routines in this file use Mach and CoreFoundation APIs, since the
|
||||
// POSIX definition of time_t in Mac OS X wraps around after 2038--and
|
||||
// there are already cookie expiration dates, etc., past that time out in
|
||||
// the field. Using CFDate prevents that problem, and using mach_absolute_time
|
||||
// for TimeTicks gives us nice high-resolution interval timing.
|
||||
|
||||
// Time -----------------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
Time TimeNowIgnoringOverride() {
|
||||
return Time::FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent());
|
||||
}
|
||||
|
||||
Time TimeNowFromSystemTimeIgnoringOverride() {
|
||||
// Just use TimeNowIgnoringOverride() because it returns the system time.
|
||||
return TimeNowIgnoringOverride();
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
// static
|
||||
Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) {
|
||||
static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity,
|
||||
"CFAbsoluteTime must have an infinity value");
|
||||
if (t == 0)
|
||||
return Time(); // Consider 0 as a null Time.
|
||||
if (t == std::numeric_limits<CFAbsoluteTime>::infinity())
|
||||
return Max();
|
||||
return Time(static_cast<int64_t>((t + kCFAbsoluteTimeIntervalSince1970) *
|
||||
kMicrosecondsPerSecond) +
|
||||
kTimeTToMicrosecondsOffset);
|
||||
}
|
||||
|
||||
CFAbsoluteTime Time::ToCFAbsoluteTime() const {
|
||||
static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity,
|
||||
"CFAbsoluteTime must have an infinity value");
|
||||
if (is_null())
|
||||
return 0; // Consider 0 as a null Time.
|
||||
if (is_max())
|
||||
return std::numeric_limits<CFAbsoluteTime>::infinity();
|
||||
return (static_cast<CFAbsoluteTime>(us_ - kTimeTToMicrosecondsOffset) /
|
||||
kMicrosecondsPerSecond) -
|
||||
kCFAbsoluteTimeIntervalSince1970;
|
||||
}
|
||||
|
||||
// TimeTicks ------------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
TimeTicks TimeTicksNowIgnoringOverride() {
|
||||
return TimeTicks() + TimeDelta::FromMicroseconds(ComputeCurrentTicks());
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
// static
|
||||
bool TimeTicks::IsHighResolution() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool TimeTicks::IsConsistentAcrossProcesses() {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX) && !defined(OS_IOS)
|
||||
// static
|
||||
TimeTicks TimeTicks::FromMachAbsoluteTime(uint64_t mach_absolute_time) {
|
||||
return TimeTicks(MachAbsoluteTimeToTicks(mach_absolute_time));
|
||||
}
|
||||
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
|
||||
|
||||
// static
|
||||
TimeTicks::Clock TimeTicks::GetClock() {
|
||||
#if defined(OS_IOS)
|
||||
return Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME;
|
||||
#else
|
||||
return Clock::MAC_MACH_ABSOLUTE_TIME;
|
||||
#endif // defined(OS_IOS)
|
||||
}
|
||||
|
||||
// ThreadTicks ----------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
ThreadTicks ThreadTicksNowIgnoringOverride() {
|
||||
return ThreadTicks() + TimeDelta::FromMicroseconds(ComputeThreadTicks());
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
} // namespace base
|
||||
122
TMessagesProj/jni/voip/webrtc/base/time/time_now_posix.cc
Normal file
122
TMessagesProj/jni/voip/webrtc/base/time/time_now_posix.cc
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#if defined(OS_ANDROID) && !defined(__LP64__)
|
||||
#include <time64.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/numerics/safe_math.h"
|
||||
#include "base/time/time_override.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
// Ensure the Fuchsia and Mac builds do not include this module. Instead,
|
||||
// non-POSIX implementation is used for sampling the system clocks.
|
||||
#if defined(OS_FUCHSIA) || defined(OS_MACOSX)
|
||||
#error "This implementation is for POSIX platforms other than Fuchsia or Mac."
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
int64_t ConvertTimespecToMicros(const struct timespec& ts) {
|
||||
// On 32-bit systems, the calculation cannot overflow int64_t.
|
||||
// 2**32 * 1000000 + 2**64 / 1000 < 2**63
|
||||
if (sizeof(ts.tv_sec) <= 4 && sizeof(ts.tv_nsec) <= 8) {
|
||||
int64_t result = ts.tv_sec;
|
||||
result *= base::Time::kMicrosecondsPerSecond;
|
||||
result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
|
||||
return result;
|
||||
}
|
||||
base::CheckedNumeric<int64_t> result(ts.tv_sec);
|
||||
result *= base::Time::kMicrosecondsPerSecond;
|
||||
result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
|
||||
return result.ValueOrDie();
|
||||
}
|
||||
|
||||
// Helper function to get results from clock_gettime() and convert to a
|
||||
// microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported
|
||||
// on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines
|
||||
// _POSIX_MONOTONIC_CLOCK to -1.
|
||||
#if (defined(OS_POSIX) && defined(_POSIX_MONOTONIC_CLOCK) && \
|
||||
_POSIX_MONOTONIC_CLOCK >= 0) || \
|
||||
defined(OS_BSD) || defined(OS_ANDROID)
|
||||
int64_t ClockNow(clockid_t clk_id) {
|
||||
struct timespec ts;
|
||||
CHECK(clock_gettime(clk_id, &ts) == 0);
|
||||
return ConvertTimespecToMicros(ts);
|
||||
}
|
||||
#else // _POSIX_MONOTONIC_CLOCK
|
||||
#error No usable tick clock function on this platform.
|
||||
#endif // _POSIX_MONOTONIC_CLOCK
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace base {
|
||||
|
||||
// Time -----------------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
Time TimeNowIgnoringOverride() {
|
||||
struct timeval tv;
|
||||
struct timezone tz = {0, 0}; // UTC
|
||||
CHECK(gettimeofday(&tv, &tz) == 0);
|
||||
// Combine seconds and microseconds in a 64-bit field containing microseconds
|
||||
// since the epoch. That's enough for nearly 600 centuries. Adjust from
|
||||
// Unix (1970) to Windows (1601) epoch.
|
||||
return Time() + TimeDelta::FromMicroseconds(
|
||||
(tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) +
|
||||
Time::kTimeTToMicrosecondsOffset);
|
||||
}
|
||||
|
||||
Time TimeNowFromSystemTimeIgnoringOverride() {
|
||||
// Just use TimeNowIgnoringOverride() because it returns the system time.
|
||||
return TimeNowIgnoringOverride();
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
// TimeTicks ------------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
TimeTicks TimeTicksNowIgnoringOverride() {
|
||||
return TimeTicks() + TimeDelta::FromMicroseconds(ClockNow(CLOCK_MONOTONIC));
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
// static
|
||||
TimeTicks::Clock TimeTicks::GetClock() {
|
||||
return Clock::LINUX_CLOCK_MONOTONIC;
|
||||
}
|
||||
|
||||
// static
|
||||
bool TimeTicks::IsHighResolution() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool TimeTicks::IsConsistentAcrossProcesses() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ThreadTicks ----------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
ThreadTicks ThreadTicksNowIgnoringOverride() {
|
||||
#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
|
||||
defined(OS_ANDROID)
|
||||
return ThreadTicks() +
|
||||
TimeDelta::FromMicroseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID));
|
||||
#else
|
||||
NOTREACHED();
|
||||
return ThreadTicks();
|
||||
#endif
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
} // namespace base
|
||||
39
TMessagesProj/jni/voip/webrtc/base/time/time_override.cc
Normal file
39
TMessagesProj/jni/voip/webrtc/base/time/time_override.cc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time_override.h"
|
||||
|
||||
namespace base {
|
||||
namespace subtle {
|
||||
|
||||
// static
|
||||
bool ScopedTimeClockOverrides::overrides_active_ = false;
|
||||
|
||||
ScopedTimeClockOverrides::ScopedTimeClockOverrides(
|
||||
TimeNowFunction time_override,
|
||||
TimeTicksNowFunction time_ticks_override,
|
||||
ThreadTicksNowFunction thread_ticks_override) {
|
||||
DCHECK(!overrides_active_);
|
||||
overrides_active_ = true;
|
||||
if (time_override) {
|
||||
internal::g_time_now_function = time_override;
|
||||
internal::g_time_now_from_system_time_function = time_override;
|
||||
}
|
||||
if (time_ticks_override)
|
||||
internal::g_time_ticks_now_function = time_ticks_override;
|
||||
if (thread_ticks_override)
|
||||
internal::g_thread_ticks_now_function = thread_ticks_override;
|
||||
}
|
||||
|
||||
ScopedTimeClockOverrides::~ScopedTimeClockOverrides() {
|
||||
internal::g_time_now_function = &TimeNowIgnoringOverride;
|
||||
internal::g_time_now_from_system_time_function =
|
||||
&TimeNowFromSystemTimeIgnoringOverride;
|
||||
internal::g_time_ticks_now_function = &TimeTicksNowIgnoringOverride;
|
||||
internal::g_thread_ticks_now_function = &ThreadTicksNowIgnoringOverride;
|
||||
overrides_active_ = false;
|
||||
}
|
||||
|
||||
} // namespace subtle
|
||||
} // namespace base
|
||||
74
TMessagesProj/jni/voip/webrtc/base/time/time_override.h
Normal file
74
TMessagesProj/jni/voip/webrtc/base/time/time_override.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_TIME_TIME_OVERRIDE_H_
|
||||
#define BASE_TIME_TIME_OVERRIDE_H_
|
||||
|
||||
#include "base/base_export.h"
|
||||
#include "base/time/time.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
using TimeNowFunction = decltype(&Time::Now);
|
||||
using TimeTicksNowFunction = decltype(&TimeTicks::Now);
|
||||
using ThreadTicksNowFunction = decltype(&ThreadTicks::Now);
|
||||
|
||||
// Time overrides should be used with extreme caution. Discuss with //base/time
|
||||
// OWNERS before adding a new one.
|
||||
namespace subtle {
|
||||
|
||||
// Override the return value of Time::Now and Time::NowFromSystemTime /
|
||||
// TimeTicks::Now / ThreadTicks::Now to emulate time, e.g. for tests or to
|
||||
// modify progression of time. Note that the override should be set while
|
||||
// single-threaded and before the first call to Now() to avoid threading issues
|
||||
// and inconsistencies in returned values. Nested overrides are not allowed.
|
||||
class BASE_EXPORT ScopedTimeClockOverrides {
|
||||
public:
|
||||
// Pass |nullptr| for any override if it shouldn't be overriden.
|
||||
ScopedTimeClockOverrides(TimeNowFunction time_override,
|
||||
TimeTicksNowFunction time_ticks_override,
|
||||
ThreadTicksNowFunction thread_ticks_override);
|
||||
|
||||
// Restores the platform default Now() functions.
|
||||
~ScopedTimeClockOverrides();
|
||||
|
||||
static bool overrides_active() { return overrides_active_; }
|
||||
|
||||
private:
|
||||
static bool overrides_active_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedTimeClockOverrides);
|
||||
};
|
||||
|
||||
// These methods return the platform default Time::Now / TimeTicks::Now /
|
||||
// ThreadTicks::Now values even while an override is in place. These methods
|
||||
// should only be used in places where emulated time should be disregarded. For
|
||||
// example, they can be used to implement test timeouts for tests that may
|
||||
// override time.
|
||||
BASE_EXPORT Time TimeNowIgnoringOverride();
|
||||
BASE_EXPORT Time TimeNowFromSystemTimeIgnoringOverride();
|
||||
BASE_EXPORT TimeTicks TimeTicksNowIgnoringOverride();
|
||||
BASE_EXPORT ThreadTicks ThreadTicksNowIgnoringOverride();
|
||||
|
||||
} // namespace subtle
|
||||
|
||||
namespace internal {
|
||||
|
||||
// These function pointers are used by platform-independent implementations of
|
||||
// the Now() methods and ScopedTimeClockOverrides. They are set to point to the
|
||||
// respective NowIgnoringOverride functions by default, but can also be set by
|
||||
// platform-specific code to select a default implementation at runtime, thereby
|
||||
// avoiding the indirection via the NowIgnoringOverride functions. Note that the
|
||||
// pointers can be overridden and later reset to the NowIgnoringOverride
|
||||
// functions by ScopedTimeClockOverrides.
|
||||
extern TimeNowFunction g_time_now_function;
|
||||
extern TimeNowFunction g_time_now_from_system_time_function;
|
||||
extern TimeTicksNowFunction g_time_ticks_now_function;
|
||||
extern ThreadTicksNowFunction g_thread_ticks_now_function;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_TIME_TIME_OVERRIDE_H_
|
||||
20
TMessagesProj/jni/voip/webrtc/base/time/time_to_iso8601.cc
Normal file
20
TMessagesProj/jni/voip/webrtc/base/time/time_to_iso8601.cc
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time_to_iso8601.h"
|
||||
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/time/time.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
std::string TimeToISO8601(const Time& t) {
|
||||
Time::Exploded exploded;
|
||||
t.UTCExplode(&exploded);
|
||||
return StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year,
|
||||
exploded.month, exploded.day_of_month, exploded.hour,
|
||||
exploded.minute, exploded.second, exploded.millisecond);
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
20
TMessagesProj/jni/voip/webrtc/base/time/time_to_iso8601.h
Normal file
20
TMessagesProj/jni/voip/webrtc/base/time/time_to_iso8601.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_TIME_TIME_TO_ISO8601_H_
|
||||
#define BASE_TIME_TIME_TO_ISO8601_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/base_export.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
class Time;
|
||||
|
||||
BASE_EXPORT std::string TimeToISO8601(const base::Time& t);
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_TIME_TIME_TO_ISO8601_H_
|
||||
810
TMessagesProj/jni/voip/webrtc/base/time/time_win.cc
Normal file
810
TMessagesProj/jni/voip/webrtc/base/time/time_win.cc
Normal file
|
|
@ -0,0 +1,810 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
|
||||
// Windows Timer Primer
|
||||
//
|
||||
// A good article: http://www.ddj.com/windows/184416651
|
||||
// A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258
|
||||
//
|
||||
// The default windows timer, GetSystemTimeAsFileTime is not very precise.
|
||||
// It is only good to ~15.5ms.
|
||||
//
|
||||
// QueryPerformanceCounter is the logical choice for a high-precision timer.
|
||||
// However, it is known to be buggy on some hardware. Specifically, it can
|
||||
// sometimes "jump". On laptops, QPC can also be very expensive to call.
|
||||
// It's 3-4x slower than timeGetTime() on desktops, but can be 10x slower
|
||||
// on laptops. A unittest exists which will show the relative cost of various
|
||||
// timers on any system.
|
||||
//
|
||||
// The next logical choice is timeGetTime(). timeGetTime has a precision of
|
||||
// 1ms, but only if you call APIs (timeBeginPeriod()) which affect all other
|
||||
// applications on the system. By default, precision is only 15.5ms.
|
||||
// Unfortunately, we don't want to call timeBeginPeriod because we don't
|
||||
// want to affect other applications. Further, on mobile platforms, use of
|
||||
// faster multimedia timers can hurt battery life. See the intel
|
||||
// article about this here:
|
||||
// http://softwarecommunity.intel.com/articles/eng/1086.htm
|
||||
//
|
||||
// To work around all this, we're going to generally use timeGetTime(). We
|
||||
// will only increase the system-wide timer if we're not running on battery
|
||||
// power.
|
||||
|
||||
#include "base/time/time.h"
|
||||
|
||||
#include <windows.foundation.h>
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "base/atomicops.h"
|
||||
#include "base/bit_cast.h"
|
||||
#include "base/cpu.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "base/threading/platform_thread.h"
|
||||
#include "base/time/time_override.h"
|
||||
#include "base/time/time_win_features.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
namespace {
|
||||
|
||||
// From MSDN, FILETIME "Contains a 64-bit value representing the number of
|
||||
// 100-nanosecond intervals since January 1, 1601 (UTC)."
|
||||
int64_t FileTimeToMicroseconds(const FILETIME& ft) {
|
||||
// Need to bit_cast to fix alignment, then divide by 10 to convert
|
||||
// 100-nanoseconds to microseconds. This only works on little-endian
|
||||
// machines.
|
||||
return bit_cast<int64_t, FILETIME>(ft) / 10;
|
||||
}
|
||||
|
||||
void MicrosecondsToFileTime(int64_t us, FILETIME* ft) {
|
||||
DCHECK_GE(us, 0LL) << "Time is less than 0, negative values are not "
|
||||
"representable in FILETIME";
|
||||
|
||||
// Multiply by 10 to convert microseconds to 100-nanoseconds. Bit_cast will
|
||||
// handle alignment problems. This only works on little-endian machines.
|
||||
*ft = bit_cast<FILETIME, int64_t>(us * 10);
|
||||
}
|
||||
|
||||
int64_t CurrentWallclockMicroseconds() {
|
||||
FILETIME ft;
|
||||
::GetSystemTimeAsFileTime(&ft);
|
||||
return FileTimeToMicroseconds(ft);
|
||||
}
|
||||
|
||||
// Time between resampling the un-granular clock for this API.
|
||||
constexpr TimeDelta kMaxTimeToAvoidDrift = TimeDelta::FromSeconds(60);
|
||||
|
||||
int64_t g_initial_time = 0;
|
||||
TimeTicks g_initial_ticks;
|
||||
|
||||
void InitializeClock() {
|
||||
g_initial_ticks = subtle::TimeTicksNowIgnoringOverride();
|
||||
g_initial_time = CurrentWallclockMicroseconds();
|
||||
}
|
||||
|
||||
// Interval to use when on DC power.
|
||||
UINT g_battery_power_interval_ms = 4;
|
||||
// Track the last value passed to timeBeginPeriod so that we can cancel that
|
||||
// call by calling timeEndPeriod with the same value. A value of zero means that
|
||||
// the timer frequency is not currently raised.
|
||||
UINT g_last_interval_requested_ms = 0;
|
||||
// Track if MinTimerIntervalHighResMs() or MinTimerIntervalLowResMs() is active.
|
||||
// For most purposes this could also be named g_is_on_ac_power.
|
||||
bool g_high_res_timer_enabled = false;
|
||||
// How many times the high resolution timer has been called.
|
||||
uint32_t g_high_res_timer_count = 0;
|
||||
// Start time of the high resolution timer usage monitoring. This is needed
|
||||
// to calculate the usage as percentage of the total elapsed time.
|
||||
TimeTicks g_high_res_timer_usage_start;
|
||||
// The cumulative time the high resolution timer has been in use since
|
||||
// |g_high_res_timer_usage_start| moment.
|
||||
TimeDelta g_high_res_timer_usage;
|
||||
// Timestamp of the last activation change of the high resolution timer. This
|
||||
// is used to calculate the cumulative usage.
|
||||
TimeTicks g_high_res_timer_last_activation;
|
||||
// The lock to control access to the above set of variables.
|
||||
Lock* GetHighResLock() {
|
||||
static auto* lock = new Lock();
|
||||
return lock;
|
||||
}
|
||||
|
||||
// The two values that ActivateHighResolutionTimer uses to set the systemwide
|
||||
// timer interrupt frequency on Windows. These control how precise timers are
|
||||
// but also have a big impact on battery life.
|
||||
|
||||
// Used when a faster timer has been requested (g_high_res_timer_count > 0) and
|
||||
// the computer is running on AC power (plugged in) so that it's okay to go to
|
||||
// the highest frequency.
|
||||
UINT MinTimerIntervalHighResMs() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Used when a faster timer has been requested (g_high_res_timer_count > 0) and
|
||||
// the computer is running on DC power (battery) so that we don't want to raise
|
||||
// the timer frequency as much.
|
||||
UINT MinTimerIntervalLowResMs() {
|
||||
return g_battery_power_interval_ms;
|
||||
}
|
||||
|
||||
// Calculate the desired timer interrupt interval. Note that zero means that the
|
||||
// system default should be used.
|
||||
UINT GetIntervalMs() {
|
||||
if (!g_high_res_timer_count)
|
||||
return 0; // Use the default, typically 15.625
|
||||
if (g_high_res_timer_enabled)
|
||||
return MinTimerIntervalHighResMs();
|
||||
return MinTimerIntervalLowResMs();
|
||||
}
|
||||
|
||||
// Compare the currently requested timer interrupt interval to the last interval
|
||||
// requested and update if necessary (by cancelling the old request and making a
|
||||
// new request). If there is no change then do nothing.
|
||||
void UpdateTimerIntervalLocked() {
|
||||
UINT new_interval = GetIntervalMs();
|
||||
if (new_interval == g_last_interval_requested_ms)
|
||||
return;
|
||||
if (g_last_interval_requested_ms) {
|
||||
// Record how long the timer interrupt frequency was raised.
|
||||
g_high_res_timer_usage += subtle::TimeTicksNowIgnoringOverride() -
|
||||
g_high_res_timer_last_activation;
|
||||
// Reset the timer interrupt back to the default.
|
||||
timeEndPeriod(g_last_interval_requested_ms);
|
||||
}
|
||||
g_last_interval_requested_ms = new_interval;
|
||||
if (g_last_interval_requested_ms) {
|
||||
// Record when the timer interrupt was raised.
|
||||
g_high_res_timer_last_activation = subtle::TimeTicksNowIgnoringOverride();
|
||||
timeBeginPeriod(g_last_interval_requested_ms);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the current value of the performance counter.
|
||||
uint64_t QPCNowRaw() {
|
||||
LARGE_INTEGER perf_counter_now = {};
|
||||
// According to the MSDN documentation for QueryPerformanceCounter(), this
|
||||
// will never fail on systems that run XP or later.
|
||||
// https://msdn.microsoft.com/library/windows/desktop/ms644904.aspx
|
||||
::QueryPerformanceCounter(&perf_counter_now);
|
||||
return perf_counter_now.QuadPart;
|
||||
}
|
||||
|
||||
bool SafeConvertToWord(int in, WORD* out) {
|
||||
CheckedNumeric<WORD> result = in;
|
||||
*out = result.ValueOrDefault(std::numeric_limits<WORD>::max());
|
||||
return result.IsValid();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Time -----------------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
Time TimeNowIgnoringOverride() {
|
||||
if (g_initial_time == 0)
|
||||
InitializeClock();
|
||||
|
||||
// We implement time using the high-resolution timers so that we can get
|
||||
// timeouts which are smaller than 10-15ms. If we just used
|
||||
// CurrentWallclockMicroseconds(), we'd have the less-granular timer.
|
||||
//
|
||||
// To make this work, we initialize the clock (g_initial_time) and the
|
||||
// counter (initial_ctr). To compute the initial time, we can check
|
||||
// the number of ticks that have elapsed, and compute the delta.
|
||||
//
|
||||
// To avoid any drift, we periodically resync the counters to the system
|
||||
// clock.
|
||||
while (true) {
|
||||
TimeTicks ticks = TimeTicksNowIgnoringOverride();
|
||||
|
||||
// Calculate the time elapsed since we started our timer
|
||||
TimeDelta elapsed = ticks - g_initial_ticks;
|
||||
|
||||
// Check if enough time has elapsed that we need to resync the clock.
|
||||
if (elapsed > kMaxTimeToAvoidDrift) {
|
||||
InitializeClock();
|
||||
continue;
|
||||
}
|
||||
|
||||
return Time() + elapsed + TimeDelta::FromMicroseconds(g_initial_time);
|
||||
}
|
||||
}
|
||||
|
||||
Time TimeNowFromSystemTimeIgnoringOverride() {
|
||||
// Force resync.
|
||||
InitializeClock();
|
||||
return Time() + TimeDelta::FromMicroseconds(g_initial_time);
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
// static
|
||||
Time Time::FromFileTime(FILETIME ft) {
|
||||
if (bit_cast<int64_t, FILETIME>(ft) == 0)
|
||||
return Time();
|
||||
if (ft.dwHighDateTime == std::numeric_limits<DWORD>::max() &&
|
||||
ft.dwLowDateTime == std::numeric_limits<DWORD>::max())
|
||||
return Max();
|
||||
return Time(FileTimeToMicroseconds(ft));
|
||||
}
|
||||
|
||||
FILETIME Time::ToFileTime() const {
|
||||
if (is_null())
|
||||
return bit_cast<FILETIME, int64_t>(0);
|
||||
if (is_max()) {
|
||||
FILETIME result;
|
||||
result.dwHighDateTime = std::numeric_limits<DWORD>::max();
|
||||
result.dwLowDateTime = std::numeric_limits<DWORD>::max();
|
||||
return result;
|
||||
}
|
||||
FILETIME utc_ft;
|
||||
MicrosecondsToFileTime(us_, &utc_ft);
|
||||
return utc_ft;
|
||||
}
|
||||
|
||||
void Time::ReadMinTimerIntervalLowResMs() {
|
||||
AutoLock lock(*GetHighResLock());
|
||||
// Read the setting for what interval to use on battery power.
|
||||
g_battery_power_interval_ms =
|
||||
base::FeatureList::IsEnabled(base::kSlowDCTimerInterruptsWin) ? 8 : 4;
|
||||
UpdateTimerIntervalLocked();
|
||||
}
|
||||
|
||||
// static
|
||||
// Enable raising of the system-global timer interrupt frequency to 1 kHz (when
|
||||
// enable is true, which happens when on AC power) or some lower frequency when
|
||||
// on battery power (when enable is false). If the g_high_res_timer_enabled
|
||||
// setting hasn't actually changed or if if there are no outstanding requests
|
||||
// (if g_high_res_timer_count is zero) then do nothing.
|
||||
// TL;DR - call this when going from AC to DC power or vice-versa.
|
||||
void Time::EnableHighResolutionTimer(bool enable) {
|
||||
AutoLock lock(*GetHighResLock());
|
||||
g_high_res_timer_enabled = enable;
|
||||
UpdateTimerIntervalLocked();
|
||||
}
|
||||
|
||||
// static
|
||||
// Request that the system-global Windows timer interrupt frequency be raised.
|
||||
// How high the frequency is raised depends on the system's power state and
|
||||
// possibly other options.
|
||||
// TL;DR - call this at the beginning and end of a time period where you want
|
||||
// higher frequency timer interrupts. Each call with activating=true must be
|
||||
// paired with a subsequent activating=false call.
|
||||
bool Time::ActivateHighResolutionTimer(bool activating) {
|
||||
// We only do work on the transition from zero to one or one to zero so we
|
||||
// can easily undo the effect (if necessary) when EnableHighResolutionTimer is
|
||||
// called.
|
||||
const uint32_t max = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
AutoLock lock(*GetHighResLock());
|
||||
if (activating) {
|
||||
DCHECK_NE(g_high_res_timer_count, max);
|
||||
++g_high_res_timer_count;
|
||||
} else {
|
||||
DCHECK_NE(g_high_res_timer_count, 0u);
|
||||
--g_high_res_timer_count;
|
||||
}
|
||||
UpdateTimerIntervalLocked();
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
// See if the timer interrupt interval has been set to the lowest value.
|
||||
bool Time::IsHighResolutionTimerInUse() {
|
||||
AutoLock lock(*GetHighResLock());
|
||||
return g_last_interval_requested_ms == MinTimerIntervalHighResMs();
|
||||
}
|
||||
|
||||
// static
|
||||
void Time::ResetHighResolutionTimerUsage() {
|
||||
AutoLock lock(*GetHighResLock());
|
||||
g_high_res_timer_usage = TimeDelta();
|
||||
g_high_res_timer_usage_start = subtle::TimeTicksNowIgnoringOverride();
|
||||
if (g_high_res_timer_count > 0)
|
||||
g_high_res_timer_last_activation = g_high_res_timer_usage_start;
|
||||
}
|
||||
|
||||
// static
|
||||
double Time::GetHighResolutionTimerUsage() {
|
||||
AutoLock lock(*GetHighResLock());
|
||||
TimeTicks now = subtle::TimeTicksNowIgnoringOverride();
|
||||
TimeDelta elapsed_time = now - g_high_res_timer_usage_start;
|
||||
if (elapsed_time.is_zero()) {
|
||||
// This is unexpected but possible if TimeTicks resolution is low and
|
||||
// GetHighResolutionTimerUsage() is called promptly after
|
||||
// ResetHighResolutionTimerUsage().
|
||||
return 0.0;
|
||||
}
|
||||
TimeDelta used_time = g_high_res_timer_usage;
|
||||
if (g_high_res_timer_count > 0) {
|
||||
// If currently activated add the remainder of time since the last
|
||||
// activation.
|
||||
used_time += now - g_high_res_timer_last_activation;
|
||||
}
|
||||
return used_time.InMillisecondsF() / elapsed_time.InMillisecondsF() * 100;
|
||||
}
|
||||
|
||||
// static
|
||||
bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) {
|
||||
// Create the system struct representing our exploded time. It will either be
|
||||
// in local time or UTC.If casting from int to WORD results in overflow,
|
||||
// fail and return Time(0).
|
||||
SYSTEMTIME st;
|
||||
if (!SafeConvertToWord(exploded.year, &st.wYear) ||
|
||||
!SafeConvertToWord(exploded.month, &st.wMonth) ||
|
||||
!SafeConvertToWord(exploded.day_of_week, &st.wDayOfWeek) ||
|
||||
!SafeConvertToWord(exploded.day_of_month, &st.wDay) ||
|
||||
!SafeConvertToWord(exploded.hour, &st.wHour) ||
|
||||
!SafeConvertToWord(exploded.minute, &st.wMinute) ||
|
||||
!SafeConvertToWord(exploded.second, &st.wSecond) ||
|
||||
!SafeConvertToWord(exploded.millisecond, &st.wMilliseconds)) {
|
||||
*time = Time(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
FILETIME ft;
|
||||
bool success = true;
|
||||
// Ensure that it's in UTC.
|
||||
if (is_local) {
|
||||
SYSTEMTIME utc_st;
|
||||
success = TzSpecificLocalTimeToSystemTime(nullptr, &st, &utc_st) &&
|
||||
SystemTimeToFileTime(&utc_st, &ft);
|
||||
} else {
|
||||
success = !!SystemTimeToFileTime(&st, &ft);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
*time = Time(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
*time = Time(FileTimeToMicroseconds(ft));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Time::Explode(bool is_local, Exploded* exploded) const {
|
||||
if (us_ < 0LL) {
|
||||
// We are not able to convert it to FILETIME.
|
||||
ZeroMemory(exploded, sizeof(*exploded));
|
||||
return;
|
||||
}
|
||||
|
||||
// FILETIME in UTC.
|
||||
FILETIME utc_ft;
|
||||
MicrosecondsToFileTime(us_, &utc_ft);
|
||||
|
||||
// FILETIME in local time if necessary.
|
||||
bool success = true;
|
||||
// FILETIME in SYSTEMTIME (exploded).
|
||||
SYSTEMTIME st = {0};
|
||||
if (is_local) {
|
||||
SYSTEMTIME utc_st;
|
||||
// We don't use FileTimeToLocalFileTime here, since it uses the current
|
||||
// settings for the time zone and daylight saving time. Therefore, if it is
|
||||
// daylight saving time, it will take daylight saving time into account,
|
||||
// even if the time you are converting is in standard time.
|
||||
success = FileTimeToSystemTime(&utc_ft, &utc_st) &&
|
||||
SystemTimeToTzSpecificLocalTime(nullptr, &utc_st, &st);
|
||||
} else {
|
||||
success = !!FileTimeToSystemTime(&utc_ft, &st);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
NOTREACHED() << "Unable to convert time, don't know why";
|
||||
ZeroMemory(exploded, sizeof(*exploded));
|
||||
return;
|
||||
}
|
||||
|
||||
exploded->year = st.wYear;
|
||||
exploded->month = st.wMonth;
|
||||
exploded->day_of_week = st.wDayOfWeek;
|
||||
exploded->day_of_month = st.wDay;
|
||||
exploded->hour = st.wHour;
|
||||
exploded->minute = st.wMinute;
|
||||
exploded->second = st.wSecond;
|
||||
exploded->millisecond = st.wMilliseconds;
|
||||
}
|
||||
|
||||
// TimeTicks ------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
||||
// We define a wrapper to adapt between the __stdcall and __cdecl call of the
|
||||
// mock function, and to avoid a static constructor. Assigning an import to a
|
||||
// function pointer directly would require setup code to fetch from the IAT.
|
||||
DWORD timeGetTimeWrapper() {
|
||||
return timeGetTime();
|
||||
}
|
||||
|
||||
DWORD (*g_tick_function)(void) = &timeGetTimeWrapper;
|
||||
|
||||
// A structure holding the most significant bits of "last seen" and a
|
||||
// "rollover" counter.
|
||||
union LastTimeAndRolloversState {
|
||||
// The state as a single 32-bit opaque value.
|
||||
subtle::Atomic32 as_opaque_32;
|
||||
|
||||
// The state as usable values.
|
||||
struct {
|
||||
// The top 8-bits of the "last" time. This is enough to check for rollovers
|
||||
// and the small bit-size means fewer CompareAndSwap operations to store
|
||||
// changes in state, which in turn makes for fewer retries.
|
||||
uint8_t last_8;
|
||||
// A count of the number of detected rollovers. Using this as bits 47-32
|
||||
// of the upper half of a 64-bit value results in a 48-bit tick counter.
|
||||
// This extends the total rollover period from about 49 days to about 8800
|
||||
// years while still allowing it to be stored with last_8 in a single
|
||||
// 32-bit value.
|
||||
uint16_t rollovers;
|
||||
} as_values;
|
||||
};
|
||||
subtle::Atomic32 g_last_time_and_rollovers = 0;
|
||||
static_assert(
|
||||
sizeof(LastTimeAndRolloversState) <= sizeof(g_last_time_and_rollovers),
|
||||
"LastTimeAndRolloversState does not fit in a single atomic word");
|
||||
|
||||
// We use timeGetTime() to implement TimeTicks::Now(). This can be problematic
|
||||
// because it returns the number of milliseconds since Windows has started,
|
||||
// which will roll over the 32-bit value every ~49 days. We try to track
|
||||
// rollover ourselves, which works if TimeTicks::Now() is called at least every
|
||||
// 48.8 days (not 49 days because only changes in the top 8 bits get noticed).
|
||||
TimeTicks RolloverProtectedNow() {
|
||||
LastTimeAndRolloversState state;
|
||||
DWORD now; // DWORD is always unsigned 32 bits.
|
||||
|
||||
while (true) {
|
||||
// Fetch the "now" and "last" tick values, updating "last" with "now" and
|
||||
// incrementing the "rollovers" counter if the tick-value has wrapped back
|
||||
// around. Atomic operations ensure that both "last" and "rollovers" are
|
||||
// always updated together.
|
||||
int32_t original = subtle::Acquire_Load(&g_last_time_and_rollovers);
|
||||
state.as_opaque_32 = original;
|
||||
now = g_tick_function();
|
||||
uint8_t now_8 = static_cast<uint8_t>(now >> 24);
|
||||
if (now_8 < state.as_values.last_8)
|
||||
++state.as_values.rollovers;
|
||||
state.as_values.last_8 = now_8;
|
||||
|
||||
// If the state hasn't changed, exit the loop.
|
||||
if (state.as_opaque_32 == original)
|
||||
break;
|
||||
|
||||
// Save the changed state. If the existing value is unchanged from the
|
||||
// original, exit the loop.
|
||||
int32_t check = subtle::Release_CompareAndSwap(
|
||||
&g_last_time_and_rollovers, original, state.as_opaque_32);
|
||||
if (check == original)
|
||||
break;
|
||||
|
||||
// Another thread has done something in between so retry from the top.
|
||||
}
|
||||
|
||||
return TimeTicks() +
|
||||
TimeDelta::FromMilliseconds(
|
||||
now + (static_cast<uint64_t>(state.as_values.rollovers) << 32));
|
||||
}
|
||||
|
||||
// Discussion of tick counter options on Windows:
|
||||
//
|
||||
// (1) CPU cycle counter. (Retrieved via RDTSC)
|
||||
// The CPU counter provides the highest resolution time stamp and is the least
|
||||
// expensive to retrieve. However, on older CPUs, two issues can affect its
|
||||
// reliability: First it is maintained per processor and not synchronized
|
||||
// between processors. Also, the counters will change frequency due to thermal
|
||||
// and power changes, and stop in some states.
|
||||
//
|
||||
// (2) QueryPerformanceCounter (QPC). The QPC counter provides a high-
|
||||
// resolution (<1 microsecond) time stamp. On most hardware running today, it
|
||||
// auto-detects and uses the constant-rate RDTSC counter to provide extremely
|
||||
// efficient and reliable time stamps.
|
||||
//
|
||||
// On older CPUs where RDTSC is unreliable, it falls back to using more
|
||||
// expensive (20X to 40X more costly) alternate clocks, such as HPET or the ACPI
|
||||
// PM timer, and can involve system calls; and all this is up to the HAL (with
|
||||
// some help from ACPI). According to
|
||||
// http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx, in the
|
||||
// worst case, it gets the counter from the rollover interrupt on the
|
||||
// programmable interrupt timer. In best cases, the HAL may conclude that the
|
||||
// RDTSC counter runs at a constant frequency, then it uses that instead. On
|
||||
// multiprocessor machines, it will try to verify the values returned from
|
||||
// RDTSC on each processor are consistent with each other, and apply a handful
|
||||
// of workarounds for known buggy hardware. In other words, QPC is supposed to
|
||||
// give consistent results on a multiprocessor computer, but for older CPUs it
|
||||
// can be unreliable due bugs in BIOS or HAL.
|
||||
//
|
||||
// (3) System time. The system time provides a low-resolution (from ~1 to ~15.6
|
||||
// milliseconds) time stamp but is comparatively less expensive to retrieve and
|
||||
// more reliable. Time::EnableHighResolutionTimer() and
|
||||
// Time::ActivateHighResolutionTimer() can be called to alter the resolution of
|
||||
// this timer; and also other Windows applications can alter it, affecting this
|
||||
// one.
|
||||
|
||||
TimeTicks InitialNowFunction();
|
||||
|
||||
// See "threading notes" in InitializeNowFunctionPointer() for details on how
|
||||
// concurrent reads/writes to these globals has been made safe.
|
||||
TimeTicksNowFunction g_time_ticks_now_ignoring_override_function =
|
||||
&InitialNowFunction;
|
||||
int64_t g_qpc_ticks_per_second = 0;
|
||||
|
||||
// As of January 2015, use of <atomic> is forbidden in Chromium code. This is
|
||||
// what std::atomic_thread_fence does on Windows on all Intel architectures when
|
||||
// the memory_order argument is anything but std::memory_order_seq_cst:
|
||||
#define ATOMIC_THREAD_FENCE(memory_order) _ReadWriteBarrier();
|
||||
|
||||
TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) {
|
||||
// Ensure that the assignment to |g_qpc_ticks_per_second|, made in
|
||||
// InitializeNowFunctionPointer(), has happened by this point.
|
||||
ATOMIC_THREAD_FENCE(memory_order_acquire);
|
||||
|
||||
DCHECK_GT(g_qpc_ticks_per_second, 0);
|
||||
|
||||
// If the QPC Value is below the overflow threshold, we proceed with
|
||||
// simple multiply and divide.
|
||||
if (qpc_value < Time::kQPCOverflowThreshold) {
|
||||
return TimeDelta::FromMicroseconds(
|
||||
qpc_value * Time::kMicrosecondsPerSecond / g_qpc_ticks_per_second);
|
||||
}
|
||||
// Otherwise, calculate microseconds in a round about manner to avoid
|
||||
// overflow and precision issues.
|
||||
int64_t whole_seconds = qpc_value / g_qpc_ticks_per_second;
|
||||
int64_t leftover_ticks = qpc_value - (whole_seconds * g_qpc_ticks_per_second);
|
||||
return TimeDelta::FromMicroseconds(
|
||||
(whole_seconds * Time::kMicrosecondsPerSecond) +
|
||||
((leftover_ticks * Time::kMicrosecondsPerSecond) /
|
||||
g_qpc_ticks_per_second));
|
||||
}
|
||||
|
||||
TimeTicks QPCNow() {
|
||||
return TimeTicks() + QPCValueToTimeDelta(QPCNowRaw());
|
||||
}
|
||||
|
||||
void InitializeNowFunctionPointer() {
|
||||
LARGE_INTEGER ticks_per_sec = {};
|
||||
if (!QueryPerformanceFrequency(&ticks_per_sec))
|
||||
ticks_per_sec.QuadPart = 0;
|
||||
|
||||
// If Windows cannot provide a QPC implementation, TimeTicks::Now() must use
|
||||
// the low-resolution clock.
|
||||
//
|
||||
// If the QPC implementation is expensive and/or unreliable, TimeTicks::Now()
|
||||
// will still use the low-resolution clock. A CPU lacking a non-stop time
|
||||
// counter will cause Windows to provide an alternate QPC implementation that
|
||||
// works, but is expensive to use.
|
||||
//
|
||||
// Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015,
|
||||
// ~72% of users fall within this category.
|
||||
TimeTicksNowFunction now_function;
|
||||
CPU cpu;
|
||||
if (ticks_per_sec.QuadPart <= 0 || !cpu.has_non_stop_time_stamp_counter()) {
|
||||
now_function = &RolloverProtectedNow;
|
||||
} else {
|
||||
now_function = &QPCNow;
|
||||
}
|
||||
|
||||
// Threading note 1: In an unlikely race condition, it's possible for two or
|
||||
// more threads to enter InitializeNowFunctionPointer() in parallel. This is
|
||||
// not a problem since all threads should end up writing out the same values
|
||||
// to the global variables.
|
||||
//
|
||||
// Threading note 2: A release fence is placed here to ensure, from the
|
||||
// perspective of other threads using the function pointers, that the
|
||||
// assignment to |g_qpc_ticks_per_second| happens before the function pointers
|
||||
// are changed.
|
||||
g_qpc_ticks_per_second = ticks_per_sec.QuadPart;
|
||||
ATOMIC_THREAD_FENCE(memory_order_release);
|
||||
// Also set g_time_ticks_now_function to avoid the additional indirection via
|
||||
// TimeTicksNowIgnoringOverride() for future calls to TimeTicks::Now(). But
|
||||
// g_time_ticks_now_function may have already be overridden.
|
||||
if (internal::g_time_ticks_now_function ==
|
||||
&subtle::TimeTicksNowIgnoringOverride) {
|
||||
internal::g_time_ticks_now_function = now_function;
|
||||
}
|
||||
g_time_ticks_now_ignoring_override_function = now_function;
|
||||
}
|
||||
|
||||
TimeTicks InitialNowFunction() {
|
||||
InitializeNowFunctionPointer();
|
||||
return g_time_ticks_now_ignoring_override_function();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
TimeTicks::TickFunctionType TimeTicks::SetMockTickFunction(
|
||||
TickFunctionType ticker) {
|
||||
TickFunctionType old = g_tick_function;
|
||||
g_tick_function = ticker;
|
||||
subtle::NoBarrier_Store(&g_last_time_and_rollovers, 0);
|
||||
return old;
|
||||
}
|
||||
|
||||
namespace subtle {
|
||||
TimeTicks TimeTicksNowIgnoringOverride() {
|
||||
return g_time_ticks_now_ignoring_override_function();
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
// static
|
||||
bool TimeTicks::IsHighResolution() {
|
||||
if (g_time_ticks_now_ignoring_override_function == &InitialNowFunction)
|
||||
InitializeNowFunctionPointer();
|
||||
return g_time_ticks_now_ignoring_override_function == &QPCNow;
|
||||
}
|
||||
|
||||
// static
|
||||
bool TimeTicks::IsConsistentAcrossProcesses() {
|
||||
// According to Windows documentation [1] QPC is consistent post-Windows
|
||||
// Vista. So if we are using QPC then we are consistent which is the same as
|
||||
// being high resolution.
|
||||
//
|
||||
// [1] https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
|
||||
//
|
||||
// "In general, the performance counter results are consistent across all
|
||||
// processors in multi-core and multi-processor systems, even when measured on
|
||||
// different threads or processes. Here are some exceptions to this rule:
|
||||
// - Pre-Windows Vista operating systems that run on certain processors might
|
||||
// violate this consistency because of one of these reasons:
|
||||
// 1. The hardware processors have a non-invariant TSC and the BIOS
|
||||
// doesn't indicate this condition correctly.
|
||||
// 2. The TSC synchronization algorithm that was used wasn't suitable for
|
||||
// systems with large numbers of processors."
|
||||
return IsHighResolution();
|
||||
}
|
||||
|
||||
// static
|
||||
TimeTicks::Clock TimeTicks::GetClock() {
|
||||
return IsHighResolution() ?
|
||||
Clock::WIN_QPC : Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME;
|
||||
}
|
||||
|
||||
// ThreadTicks ----------------------------------------------------------------
|
||||
|
||||
namespace subtle {
|
||||
ThreadTicks ThreadTicksNowIgnoringOverride() {
|
||||
return ThreadTicks::GetForThread(PlatformThread::CurrentHandle());
|
||||
}
|
||||
} // namespace subtle
|
||||
|
||||
// static
|
||||
ThreadTicks ThreadTicks::GetForThread(
|
||||
const PlatformThreadHandle& thread_handle) {
|
||||
DCHECK(IsSupported());
|
||||
|
||||
#if defined(ARCH_CPU_ARM64)
|
||||
// QueryThreadCycleTime versus TSCTicksPerSecond doesn't have much relation to
|
||||
// actual elapsed time on Windows on Arm, because QueryThreadCycleTime is
|
||||
// backed by the actual number of CPU cycles executed, rather than a
|
||||
// constant-rate timer like Intel. To work around this, use GetThreadTimes
|
||||
// (which isn't as accurate but is meaningful as a measure of elapsed
|
||||
// per-thread time).
|
||||
FILETIME creation_time, exit_time, kernel_time, user_time;
|
||||
::GetThreadTimes(thread_handle.platform_handle(), &creation_time, &exit_time,
|
||||
&kernel_time, &user_time);
|
||||
|
||||
int64_t us = FileTimeToMicroseconds(user_time);
|
||||
return ThreadTicks(us);
|
||||
#else
|
||||
// Get the number of TSC ticks used by the current thread.
|
||||
ULONG64 thread_cycle_time = 0;
|
||||
::QueryThreadCycleTime(thread_handle.platform_handle(), &thread_cycle_time);
|
||||
|
||||
// Get the frequency of the TSC.
|
||||
double tsc_ticks_per_second = TSCTicksPerSecond();
|
||||
if (tsc_ticks_per_second == 0)
|
||||
return ThreadTicks();
|
||||
|
||||
// Return the CPU time of the current thread.
|
||||
double thread_time_seconds = thread_cycle_time / tsc_ticks_per_second;
|
||||
return ThreadTicks(
|
||||
static_cast<int64_t>(thread_time_seconds * Time::kMicrosecondsPerSecond));
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
bool ThreadTicks::IsSupportedWin() {
|
||||
static bool is_supported = CPU().has_non_stop_time_stamp_counter();
|
||||
return is_supported;
|
||||
}
|
||||
|
||||
// static
|
||||
void ThreadTicks::WaitUntilInitializedWin() {
|
||||
#if !defined(ARCH_CPU_ARM64)
|
||||
while (TSCTicksPerSecond() == 0)
|
||||
::Sleep(10);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(ARCH_CPU_ARM64)
|
||||
double ThreadTicks::TSCTicksPerSecond() {
|
||||
DCHECK(IsSupported());
|
||||
// The value returned by QueryPerformanceFrequency() cannot be used as the TSC
|
||||
// frequency, because there is no guarantee that the TSC frequency is equal to
|
||||
// the performance counter frequency.
|
||||
// The TSC frequency is cached in a static variable because it takes some time
|
||||
// to compute it.
|
||||
static double tsc_ticks_per_second = 0;
|
||||
if (tsc_ticks_per_second != 0)
|
||||
return tsc_ticks_per_second;
|
||||
|
||||
// Increase the thread priority to reduces the chances of having a context
|
||||
// switch during a reading of the TSC and the performance counter.
|
||||
int previous_priority = ::GetThreadPriority(::GetCurrentThread());
|
||||
::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
|
||||
|
||||
// The first time that this function is called, make an initial reading of the
|
||||
// TSC and the performance counter.
|
||||
|
||||
static const uint64_t tsc_initial = __rdtsc();
|
||||
static const uint64_t perf_counter_initial = QPCNowRaw();
|
||||
|
||||
// Make a another reading of the TSC and the performance counter every time
|
||||
// that this function is called.
|
||||
uint64_t tsc_now = __rdtsc();
|
||||
uint64_t perf_counter_now = QPCNowRaw();
|
||||
|
||||
// Reset the thread priority.
|
||||
::SetThreadPriority(::GetCurrentThread(), previous_priority);
|
||||
|
||||
// Make sure that at least 50 ms elapsed between the 2 readings. The first
|
||||
// time that this function is called, we don't expect this to be the case.
|
||||
// Note: The longer the elapsed time between the 2 readings is, the more
|
||||
// accurate the computed TSC frequency will be. The 50 ms value was
|
||||
// chosen because local benchmarks show that it allows us to get a
|
||||
// stddev of less than 1 tick/us between multiple runs.
|
||||
// Note: According to the MSDN documentation for QueryPerformanceFrequency(),
|
||||
// this will never fail on systems that run XP or later.
|
||||
// https://msdn.microsoft.com/library/windows/desktop/ms644905.aspx
|
||||
LARGE_INTEGER perf_counter_frequency = {};
|
||||
::QueryPerformanceFrequency(&perf_counter_frequency);
|
||||
DCHECK_GE(perf_counter_now, perf_counter_initial);
|
||||
uint64_t perf_counter_ticks = perf_counter_now - perf_counter_initial;
|
||||
double elapsed_time_seconds =
|
||||
perf_counter_ticks / static_cast<double>(perf_counter_frequency.QuadPart);
|
||||
|
||||
static constexpr double kMinimumEvaluationPeriodSeconds = 0.05;
|
||||
if (elapsed_time_seconds < kMinimumEvaluationPeriodSeconds)
|
||||
return 0;
|
||||
|
||||
// Compute the frequency of the TSC.
|
||||
DCHECK_GE(tsc_now, tsc_initial);
|
||||
uint64_t tsc_ticks = tsc_now - tsc_initial;
|
||||
tsc_ticks_per_second = tsc_ticks / elapsed_time_seconds;
|
||||
|
||||
return tsc_ticks_per_second;
|
||||
}
|
||||
#endif // defined(ARCH_CPU_ARM64)
|
||||
|
||||
// static
|
||||
TimeTicks TimeTicks::FromQPCValue(LONGLONG qpc_value) {
|
||||
return TimeTicks() + QPCValueToTimeDelta(qpc_value);
|
||||
}
|
||||
|
||||
// TimeDelta ------------------------------------------------------------------
|
||||
|
||||
// static
|
||||
TimeDelta TimeDelta::FromQPCValue(LONGLONG qpc_value) {
|
||||
return QPCValueToTimeDelta(qpc_value);
|
||||
}
|
||||
|
||||
// static
|
||||
TimeDelta TimeDelta::FromFileTime(FILETIME ft) {
|
||||
return TimeDelta::FromMicroseconds(FileTimeToMicroseconds(ft));
|
||||
}
|
||||
|
||||
// static
|
||||
TimeDelta TimeDelta::FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt) {
|
||||
// UniversalTime is 100 ns intervals since January 1, 1601 (UTC)
|
||||
return TimeDelta::FromMicroseconds(dt.UniversalTime / 10);
|
||||
}
|
||||
|
||||
ABI::Windows::Foundation::DateTime TimeDelta::ToWinrtDateTime() const {
|
||||
ABI::Windows::Foundation::DateTime date_time;
|
||||
date_time.UniversalTime = InMicroseconds() * 10;
|
||||
return date_time;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
14
TMessagesProj/jni/voip/webrtc/base/time/time_win_features.cc
Normal file
14
TMessagesProj/jni/voip/webrtc/base/time/time_win_features.cc
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/time/time_win_features.h"
|
||||
|
||||
#include "base/feature_list.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
const Feature kSlowDCTimerInterruptsWin{"SlowDCTimerInterruptsWin",
|
||||
FEATURE_DISABLED_BY_DEFAULT};
|
||||
|
||||
} // namespace base
|
||||
20
TMessagesProj/jni/voip/webrtc/base/time/time_win_features.h
Normal file
20
TMessagesProj/jni/voip/webrtc/base/time/time_win_features.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_TIME_TIME_WIN_FEATURES_H_
|
||||
#define BASE_TIME_TIME_WIN_FEATURES_H_
|
||||
|
||||
#include "base/base_export.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
struct Feature;
|
||||
|
||||
// Slow the maximum interrupt timer on battery power to 8 ms, instead of the
|
||||
// default 4 ms.
|
||||
extern const BASE_EXPORT Feature kSlowDCTimerInterruptsWin;
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_TIME_TIME_WIN_FEATURES_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue