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