| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/base/platform/time.h" | 5 #include "src/base/platform/time.h" |
| 6 | 6 |
| 7 #if V8_OS_POSIX | 7 #if V8_OS_POSIX |
| 8 #include <fcntl.h> // for O_RDONLY | 8 #include <fcntl.h> // for O_RDONLY |
| 9 #include <sys/time.h> | 9 #include <sys/time.h> |
| 10 #include <unistd.h> | 10 #include <unistd.h> |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 } | 140 } |
| 141 | 141 |
| 142 #endif // V8_OS_POSIX | 142 #endif // V8_OS_POSIX |
| 143 | 143 |
| 144 | 144 |
| 145 #if V8_OS_WIN | 145 #if V8_OS_WIN |
| 146 | 146 |
| 147 // We implement time using the high-resolution timers so that we can get | 147 // We implement time using the high-resolution timers so that we can get |
| 148 // timeouts which are smaller than 10-15ms. To avoid any drift, we | 148 // timeouts which are smaller than 10-15ms. To avoid any drift, we |
| 149 // periodically resync the internal clock to the system clock. | 149 // periodically resync the internal clock to the system clock. |
| 150 class Clock FINAL { | 150 class Clock final { |
| 151 public: | 151 public: |
| 152 Clock() : initial_ticks_(GetSystemTicks()), initial_time_(GetSystemTime()) {} | 152 Clock() : initial_ticks_(GetSystemTicks()), initial_time_(GetSystemTime()) {} |
| 153 | 153 |
| 154 Time Now() { | 154 Time Now() { |
| 155 // Time between resampling the un-granular clock for this API (1 minute). | 155 // Time between resampling the un-granular clock for this API (1 minute). |
| 156 const TimeDelta kMaxElapsedTime = TimeDelta::FromMinutes(1); | 156 const TimeDelta kMaxElapsedTime = TimeDelta::FromMinutes(1); |
| 157 | 157 |
| 158 LockGuard<Mutex> lock_guard(&mutex_); | 158 LockGuard<Mutex> lock_guard(&mutex_); |
| 159 | 159 |
| 160 // Determine current time and ticks. | 160 // Determine current time and ticks. |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 // RDTSC on each processor are consistent with each other, and apply a handful | 392 // RDTSC on each processor are consistent with each other, and apply a handful |
| 393 // of workarounds for known buggy hardware. In other words, QPC is supposed to | 393 // of workarounds for known buggy hardware. In other words, QPC is supposed to |
| 394 // give consistent result on a multiprocessor computer, but it is unreliable in | 394 // give consistent result on a multiprocessor computer, but it is unreliable in |
| 395 // reality due to bugs in BIOS or HAL on some, especially old computers. | 395 // reality due to bugs in BIOS or HAL on some, especially old computers. |
| 396 // With recent updates on HAL and newer BIOS, QPC is getting more reliable but | 396 // With recent updates on HAL and newer BIOS, QPC is getting more reliable but |
| 397 // it should be used with caution. | 397 // it should be used with caution. |
| 398 // | 398 // |
| 399 // (3) System time. The system time provides a low-resolution (typically 10ms | 399 // (3) System time. The system time provides a low-resolution (typically 10ms |
| 400 // to 55 milliseconds) time stamp but is comparatively less expensive to | 400 // to 55 milliseconds) time stamp but is comparatively less expensive to |
| 401 // retrieve and more reliable. | 401 // retrieve and more reliable. |
| 402 class HighResolutionTickClock FINAL : public TickClock { | 402 class HighResolutionTickClock final : public TickClock { |
| 403 public: | 403 public: |
| 404 explicit HighResolutionTickClock(int64_t ticks_per_second) | 404 explicit HighResolutionTickClock(int64_t ticks_per_second) |
| 405 : ticks_per_second_(ticks_per_second) { | 405 : ticks_per_second_(ticks_per_second) { |
| 406 DCHECK_LT(0, ticks_per_second); | 406 DCHECK_LT(0, ticks_per_second); |
| 407 } | 407 } |
| 408 virtual ~HighResolutionTickClock() {} | 408 virtual ~HighResolutionTickClock() {} |
| 409 | 409 |
| 410 int64_t Now() OVERRIDE { | 410 int64_t Now() override { |
| 411 LARGE_INTEGER now; | 411 LARGE_INTEGER now; |
| 412 BOOL result = QueryPerformanceCounter(&now); | 412 BOOL result = QueryPerformanceCounter(&now); |
| 413 DCHECK(result); | 413 DCHECK(result); |
| 414 USE(result); | 414 USE(result); |
| 415 | 415 |
| 416 // Intentionally calculate microseconds in a round about manner to avoid | 416 // Intentionally calculate microseconds in a round about manner to avoid |
| 417 // overflow and precision issues. Think twice before simplifying! | 417 // overflow and precision issues. Think twice before simplifying! |
| 418 int64_t whole_seconds = now.QuadPart / ticks_per_second_; | 418 int64_t whole_seconds = now.QuadPart / ticks_per_second_; |
| 419 int64_t leftover_ticks = now.QuadPart % ticks_per_second_; | 419 int64_t leftover_ticks = now.QuadPart % ticks_per_second_; |
| 420 int64_t ticks = (whole_seconds * Time::kMicrosecondsPerSecond) + | 420 int64_t ticks = (whole_seconds * Time::kMicrosecondsPerSecond) + |
| 421 ((leftover_ticks * Time::kMicrosecondsPerSecond) / ticks_per_second_); | 421 ((leftover_ticks * Time::kMicrosecondsPerSecond) / ticks_per_second_); |
| 422 | 422 |
| 423 // Make sure we never return 0 here, so that TimeTicks::HighResolutionNow() | 423 // Make sure we never return 0 here, so that TimeTicks::HighResolutionNow() |
| 424 // will never return 0. | 424 // will never return 0. |
| 425 return ticks + 1; | 425 return ticks + 1; |
| 426 } | 426 } |
| 427 | 427 |
| 428 bool IsHighResolution() OVERRIDE { return true; } | 428 bool IsHighResolution() override { return true; } |
| 429 | 429 |
| 430 private: | 430 private: |
| 431 int64_t ticks_per_second_; | 431 int64_t ticks_per_second_; |
| 432 }; | 432 }; |
| 433 | 433 |
| 434 | 434 |
| 435 class RolloverProtectedTickClock FINAL : public TickClock { | 435 class RolloverProtectedTickClock final : public TickClock { |
| 436 public: | 436 public: |
| 437 // We initialize rollover_ms_ to 1 to ensure that we will never | 437 // We initialize rollover_ms_ to 1 to ensure that we will never |
| 438 // return 0 from TimeTicks::HighResolutionNow() and TimeTicks::Now() below. | 438 // return 0 from TimeTicks::HighResolutionNow() and TimeTicks::Now() below. |
| 439 RolloverProtectedTickClock() : last_seen_now_(0), rollover_ms_(1) {} | 439 RolloverProtectedTickClock() : last_seen_now_(0), rollover_ms_(1) {} |
| 440 virtual ~RolloverProtectedTickClock() {} | 440 virtual ~RolloverProtectedTickClock() {} |
| 441 | 441 |
| 442 int64_t Now() OVERRIDE { | 442 int64_t Now() override { |
| 443 LockGuard<Mutex> lock_guard(&mutex_); | 443 LockGuard<Mutex> lock_guard(&mutex_); |
| 444 // We use timeGetTime() to implement TimeTicks::Now(), which rolls over | 444 // We use timeGetTime() to implement TimeTicks::Now(), which rolls over |
| 445 // every ~49.7 days. We try to track rollover ourselves, which works if | 445 // every ~49.7 days. We try to track rollover ourselves, which works if |
| 446 // TimeTicks::Now() is called at least every 49 days. | 446 // TimeTicks::Now() is called at least every 49 days. |
| 447 // Note that we do not use GetTickCount() here, since timeGetTime() gives | 447 // Note that we do not use GetTickCount() here, since timeGetTime() gives |
| 448 // more predictable delta values, as described here: | 448 // more predictable delta values, as described here: |
| 449 // http://blogs.msdn.com/b/larryosterman/archive/2009/09/02/what-s-the-diffe
rence-between-gettickcount-and-timegettime.aspx | 449 // http://blogs.msdn.com/b/larryosterman/archive/2009/09/02/what-s-the-diffe
rence-between-gettickcount-and-timegettime.aspx |
| 450 // timeGetTime() provides 1ms granularity when combined with | 450 // timeGetTime() provides 1ms granularity when combined with |
| 451 // timeBeginPeriod(). If the host application for V8 wants fast timers, it | 451 // timeBeginPeriod(). If the host application for V8 wants fast timers, it |
| 452 // can use timeBeginPeriod() to increase the resolution. | 452 // can use timeBeginPeriod() to increase the resolution. |
| 453 DWORD now = timeGetTime(); | 453 DWORD now = timeGetTime(); |
| 454 if (now < last_seen_now_) { | 454 if (now < last_seen_now_) { |
| 455 rollover_ms_ += V8_INT64_C(0x100000000); // ~49.7 days. | 455 rollover_ms_ += V8_INT64_C(0x100000000); // ~49.7 days. |
| 456 } | 456 } |
| 457 last_seen_now_ = now; | 457 last_seen_now_ = now; |
| 458 return (now + rollover_ms_) * Time::kMicrosecondsPerMillisecond; | 458 return (now + rollover_ms_) * Time::kMicrosecondsPerMillisecond; |
| 459 } | 459 } |
| 460 | 460 |
| 461 bool IsHighResolution() OVERRIDE { return false; } | 461 bool IsHighResolution() override { return false; } |
| 462 | 462 |
| 463 private: | 463 private: |
| 464 Mutex mutex_; | 464 Mutex mutex_; |
| 465 DWORD last_seen_now_; | 465 DWORD last_seen_now_; |
| 466 int64_t rollover_ms_; | 466 int64_t rollover_ms_; |
| 467 }; | 467 }; |
| 468 | 468 |
| 469 | 469 |
| 470 static LazyStaticInstance<RolloverProtectedTickClock, | 470 static LazyStaticInstance<RolloverProtectedTickClock, |
| 471 DefaultConstructTrait<RolloverProtectedTickClock>, | 471 DefaultConstructTrait<RolloverProtectedTickClock>, |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 | 638 |
| 639 | 639 |
| 640 // static | 640 // static |
| 641 bool TimeTicks::KernelTimestampAvailable() { | 641 bool TimeTicks::KernelTimestampAvailable() { |
| 642 return kernel_tick_clock.Pointer()->Available(); | 642 return kernel_tick_clock.Pointer()->Available(); |
| 643 } | 643 } |
| 644 | 644 |
| 645 #endif // V8_OS_WIN | 645 #endif // V8_OS_WIN |
| 646 | 646 |
| 647 } } // namespace v8::base | 647 } } // namespace v8::base |
| OLD | NEW |