Commit 190f13f7 authored by sleffler@chromium.org's avatar sleffler@chromium.org

Add interface to system trace clock.

Add TimeTicks::NowFromSystemTraceTime to return the current system trace
event clock (falling back to TimeTicks::HighResNow when not supported).
On systems where the system trace clock is available this allows
system and chrome events to be stamped with a common clock (eliminating
post-processing time shift adjustment that can be hard).

BUG=chromium-os:27809
TEST=unit tests + collect trace data on chrome os w/ kernel that supports clock_gettime(CLOCK_SYSTEM_TRACE)

Change-Id: Ia6a500bd13a6f09c49052a1dd1421027960d8dea


Review URL: http://codereview.chromium.org/10257020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134772 0039d316-1c4b-4281-b951-d872f2087c98
parent 28832873
...@@ -585,7 +585,7 @@ int TraceLog::AddTraceEvent(char phase, ...@@ -585,7 +585,7 @@ int TraceLog::AddTraceEvent(char phase,
long long threshold, long long threshold,
unsigned char flags) { unsigned char flags) {
DCHECK(name); DCHECK(name);
TimeTicks now = TimeTicks::HighResNow(); TimeTicks now = TimeTicks::NowFromSystemTraceTime();
BufferFullCallback buffer_full_callback_copy; BufferFullCallback buffer_full_callback_copy;
int ret_begin_id = -1; int ret_begin_id = -1;
{ {
...@@ -710,7 +710,7 @@ void TraceLog::AddClockSyncMetadataEvents() { ...@@ -710,7 +710,7 @@ void TraceLog::AddClockSyncMetadataEvents() {
// debugfs that takes the written data and pushes it onto the trace // debugfs that takes the written data and pushes it onto the trace
// buffer. So, to establish clock sync, we write our monotonic clock into that // buffer. So, to establish clock sync, we write our monotonic clock into that
// trace buffer. // trace buffer.
TimeTicks now = TimeTicks::HighResNow(); TimeTicks now = TimeTicks::NowFromSystemTraceTime();
double now_in_seconds = now.ToInternalValue() / 1000000.0; double now_in_seconds = now.ToInternalValue() / 1000000.0;
std::string marker = std::string marker =
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -482,6 +482,13 @@ class BASE_EXPORT TimeTicks { ...@@ -482,6 +482,13 @@ class BASE_EXPORT TimeTicks {
// SHOULD ONLY BE USED WHEN IT IS REALLY NEEDED. // SHOULD ONLY BE USED WHEN IT IS REALLY NEEDED.
static TimeTicks HighResNow(); static TimeTicks HighResNow();
// Returns the current system trace time or, if none is defined, the current
// high-res time (i.e. HighResNow()). On systems where a global trace clock
// is defined, timestamping TraceEvents's with this value guarantees
// synchronization between events collected inside chrome and events
// collected outside (e.g. kernel, X server).
static TimeTicks NowFromSystemTraceTime();
#if defined(OS_WIN) #if defined(OS_WIN)
// Get the absolute value of QPC time drift. For testing. // Get the absolute value of QPC time drift. For testing.
static int64 GetQPCDriftMicroseconds(); static int64 GetQPCDriftMicroseconds();
......
...@@ -148,4 +148,9 @@ TimeTicks TimeTicks::HighResNow() { ...@@ -148,4 +148,9 @@ TimeTicks TimeTicks::HighResNow() {
return Now(); return Now();
} }
// static
TimeTicks TimeTicks::NowFromSystemTraceTime() {
return HighResNow();
}
} // namespace base } // namespace base
...@@ -228,6 +228,34 @@ TimeTicks TimeTicks::HighResNow() { ...@@ -228,6 +228,34 @@ TimeTicks TimeTicks::HighResNow() {
return Now(); return Now();
} }
#if defined(OS_POSIX) && defined(CLOCK_SYSTEM_TRACE)
// static
TimeTicks TimeTicks::NowFromSystemTraceTime() {
uint64_t absolute_micro;
struct timespec ts;
if (clock_gettime(CLOCK_SYSTEM_TRACE, &ts) != 0) {
NOTREACHED() << "clock_gettime(CLOCK_SYSTEM_TRACE) failed.";
return HighResNow();
}
absolute_micro =
(static_cast<int64>(ts.tv_sec) * Time::kMicrosecondsPerSecond) +
(static_cast<int64>(ts.tv_nsec) / Time::kNanosecondsPerMicrosecond);
return TimeTicks(absolute_micro);
}
#else // !(defined(OS_POSIX) && defined(CLOCK_SYSTEM_TRACE))
// static
TimeTicks TimeTicks::NowFromSystemTraceTime() {
return HighResNow();
}
#endif // defined(OS_POSIX) && defined(CLOCK_SYSTEM_TRACE)
#endif // !OS_MACOSX #endif // !OS_MACOSX
struct timeval Time::ToTimeVal() const { struct timeval Time::ToTimeVal() const {
......
...@@ -464,7 +464,7 @@ TEST(TimeTicks, Deltas) { ...@@ -464,7 +464,7 @@ TEST(TimeTicks, Deltas) {
} }
} }
TEST(TimeTicks, HighResNow) { static void HighResClockTest(TimeTicks (*GetTicks)()) {
#if defined(OS_WIN) #if defined(OS_WIN)
// HighResNow doesn't work on some systems. Since the product still works // HighResNow doesn't work on some systems. Since the product still works
// even if it doesn't work, it makes this entire test questionable. // even if it doesn't work, it makes this entire test questionable.
...@@ -486,12 +486,12 @@ TEST(TimeTicks, HighResNow) { ...@@ -486,12 +486,12 @@ TEST(TimeTicks, HighResNow) {
int retries = 100; // Arbitrary. int retries = 100; // Arbitrary.
TimeDelta delta; TimeDelta delta;
while (!success && retries--) { while (!success && retries--) {
TimeTicks ticks_start = TimeTicks::HighResNow(); TimeTicks ticks_start = GetTicks();
// Loop until we can detect that the clock has changed. Non-HighRes timers // Loop until we can detect that the clock has changed. Non-HighRes timers
// will increment in chunks, e.g. 15ms. By spinning until we see a clock // will increment in chunks, e.g. 15ms. By spinning until we see a clock
// change, we detect the minimum time between measurements. // change, we detect the minimum time between measurements.
do { do {
delta = TimeTicks::HighResNow() - ticks_start; delta = GetTicks() - ticks_start;
} while (delta.InMilliseconds() == 0); } while (delta.InMilliseconds() == 0);
if (delta.InMicroseconds() <= kTargetGranularityUs) if (delta.InMicroseconds() <= kTargetGranularityUs)
...@@ -503,6 +503,15 @@ TEST(TimeTicks, HighResNow) { ...@@ -503,6 +503,15 @@ TEST(TimeTicks, HighResNow) {
EXPECT_TRUE(success); EXPECT_TRUE(success);
} }
TEST(TimeTicks, HighResNow) {
HighResClockTest(&TimeTicks::HighResNow);
}
TEST(TimeTicks, NowFromSystemTraceTime) {
// Re-use HighResNow test for now since clock properties are identical.
HighResClockTest(&TimeTicks::NowFromSystemTraceTime);
}
TEST(TimeDelta, FromAndIn) { TEST(TimeDelta, FromAndIn) {
EXPECT_TRUE(TimeDelta::FromDays(2) == TimeDelta::FromHours(48)); EXPECT_TRUE(TimeDelta::FromDays(2) == TimeDelta::FromHours(48));
EXPECT_TRUE(TimeDelta::FromHours(3) == TimeDelta::FromMinutes(180)); EXPECT_TRUE(TimeDelta::FromHours(3) == TimeDelta::FromMinutes(180));
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -435,6 +435,11 @@ TimeTicks TimeTicks::HighResNow() { ...@@ -435,6 +435,11 @@ TimeTicks TimeTicks::HighResNow() {
return TimeTicks() + HighResNowSingleton::GetInstance()->Now(); return TimeTicks() + HighResNowSingleton::GetInstance()->Now();
} }
// static
TimeTicks TimeTicks::NowFromSystemTraceTime() {
return HighResNow();
}
// static // static
int64 TimeTicks::GetQPCDriftMicroseconds() { int64 TimeTicks::GetQPCDriftMicroseconds() {
return HighResNowSingleton::GetInstance()->GetQPCDriftMicroseconds(); return HighResNowSingleton::GetInstance()->GetQPCDriftMicroseconds();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment