From 9808d4e70b8fe62b22202c4773e5da7f1f83c465 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer <eike@sf-mail.de> Date: Wed, 2 Jan 2013 17:42:35 +0100 Subject: [PATCH] SystemInformation: get CPU speed on Windows when RDTSC fails The CPU may have a TSC but reading it may fail, in which case we now always fall back to reading the value from the registry. This is especially true on Windows64 where we do not have the assembler instructions at all. Change-Id: I5b1aafac6cd8df57ed8c1ac3bafcc8e092e3d4fb --- SystemInformation.cxx | 68 ++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/SystemInformation.cxx b/SystemInformation.cxx index 0ee02bd..b8872f1 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -417,7 +417,7 @@ protected: unsigned char LogicalCPUPerPhysicalCPU(); unsigned char GetAPICId(); unsigned int IsHyperThreadingSupported(); - LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); + static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For Linux and Cygwin, /proc/cpuinfo formats are slightly different int RetreiveInformationFromCpuInfoFile(); @@ -2071,11 +2071,40 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed() bool retrieved = false; #if defined(_WIN32) - // First of all we check to see if the RDTSC (0x0F, 0x31) instruction is - // supported. If not, we fallback to trying to read this value from the - // registry: - // - if (!this->Features.HasTSC) + unsigned int uiRepetitions = 1; + unsigned int uiMSecPerRepetition = 50; + __int64 i64Total = 0; + __int64 i64Overhead = 0; + + // Check if the TSC implementation works at all + if (this->Features.HasTSC && + GetCyclesDifference(SystemInformationImplementation::Delay, + uiMSecPerRepetition) > 0) + { + for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++) + { + i64Total += GetCyclesDifference (SystemInformationImplementation::Delay, + uiMSecPerRepetition); + i64Overhead += + GetCyclesDifference (SystemInformationImplementation::DelayOverhead, + uiMSecPerRepetition); + } + + // Calculate the MHz speed. + i64Total -= i64Overhead; + i64Total /= uiRepetitions; + i64Total /= uiMSecPerRepetition; + i64Total /= 1000; + + // Save the CPU speed. + this->CPUSpeedInMHz = (float) i64Total; + + retrieved = true; + } + + // If RDTSC is not supported, we fallback to trying to read this value + // from the registry: + if (!retrieved) { HKEY hKey = NULL; LONG err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, @@ -2100,34 +2129,7 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed() RegCloseKey(hKey); hKey = NULL; } - - return retrieved; } - - unsigned int uiRepetitions = 1; - unsigned int uiMSecPerRepetition = 50; - __int64 i64Total = 0; - __int64 i64Overhead = 0; - - for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++) - { - i64Total += GetCyclesDifference (SystemInformationImplementation::Delay, - uiMSecPerRepetition); - i64Overhead += - GetCyclesDifference (SystemInformationImplementation::DelayOverhead, - uiMSecPerRepetition); - } - - // Calculate the MHz speed. - i64Total -= i64Overhead; - i64Total /= uiRepetitions; - i64Total /= uiMSecPerRepetition; - i64Total /= 1000; - - // Save the CPU speed. - this->CPUSpeedInMHz = (float) i64Total; - - retrieved = true; #endif return retrieved; -- GitLab