Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Unified Diff: src/base/platform/time.cc

Issue 1977983003: [base] Implement CPU time on Windows. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/base/platform/time.h ('k') | src/base/win32-headers.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/base/platform/time.cc
diff --git a/src/base/platform/time.cc b/src/base/platform/time.cc
index b2355a33bde275695d13fe49ceb619ddf12911d5..4c8870d1ee28dfe643f4670e222c315dcf6fad92 100644
--- a/src/base/platform/time.cc
+++ b/src/base/platform/time.cc
@@ -67,6 +67,21 @@ inline int64_t ClockNow(clockid_t clk_id) {
return 0;
#endif
}
+#elif V8_OS_WIN
+bool IsBuggyAthlon(const v8::base::CPU& cpu) {
+ // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is unreliable.
+ return strcmp(cpu.vendor(), "AuthenticAMD") == 0 && cpu.family() == 15;
noordhuis 2016/05/15 09:06:46 I commented on this in the other CL but I think it
lpy 2016/05/24 22:21:46 I will leave this as it is for now, since we are u
+}
+
+// Returns the current value of the performance counter.
+uint64_t QPCNowRaw() {
fmeawad 2016/05/14 01:04:07 If I am reading the correctly, we do not use QPC f
lpy 2016/05/24 22:21:46 It depends. V8 may fall back to low resolution tim
+ 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;
+}
#endif // V8_OS_MACOSX
@@ -621,11 +636,106 @@ ThreadTicks ThreadTicks::Now() {
#elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
defined(V8_OS_ANDROID)
return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID));
+#elif V8_OS_WIN
+ return ThreadTicks::GetForThread(::GetCurrentThread());
#else
UNREACHABLE();
return ThreadTicks();
#endif
}
+
+#if V8_OS_WIN
+ThreadTicks ThreadTicks::GetForThread(const HANDLE& thread_handle) {
+ DCHECK(IsSupported());
+
+ // Get the number of TSC ticks used by the current thread.
+ ULONG64 thread_cycle_time = 0;
+ ::QueryThreadCycleTime(thread_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));
+}
+
+// static
+bool ThreadTicks::IsSupportedWin() {
+ static bool is_supported = base::CPU().has_non_stop_time_stamp_counter() &&
+ !IsBuggyAthlon(base::CPU());
+ return is_supported;
+}
+
+// static
+void ThreadTicks::WaitUntilInitializedWin() {
+ while (TSCTicksPerSecond() == 0)
+ ::Sleep(10);
+}
+
+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);
+
+ const 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 // V8_OS_WIN
+
} // namespace base
} // namespace v8
« no previous file with comments | « src/base/platform/time.h ('k') | src/base/win32-headers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698