diff --git a/CMakeLists.txt b/CMakeLists.txt index dd8ef23e71..c329994b7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -774,7 +774,7 @@ if(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) if(KWSYS_USE_SystemInformation) if(WIN32) - target_link_libraries(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} ws2_32) + target_link_libraries(${KWSYS_TARGET_INTERFACE} ${KWSYS_LINK_DEPENDENCY} ws2_32 PowrProf) # link in dbghelp.dll for symbol lookup if MSVC 1800 or later # Note that the dbghelp runtime is part of MS Windows OS if(MSVC_VERSION AND NOT MSVC_VERSION VERSION_LESS 1800) diff --git a/SystemInformation.cxx b/SystemInformation.cxx index 7c7c4adc73..c65587edbe 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -61,6 +61,7 @@ # if !defined(siginfo_t) using siginfo_t = int; # endif +# include #else # include @@ -2489,40 +2490,63 @@ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails() #endif } +#if defined(_WIN32) +typedef struct _PROCESSOR_POWER_INFORMATION +{ + ULONG Number; + ULONG MaxMhz; + ULONG CurrentMhz; + ULONG MhzLimit; + ULONG MaxIdleState; + ULONG CurrentIdleState; +} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION; +#endif + /** */ bool SystemInformationImplementation::RetrieveCPUClockSpeed() { bool retrieved = false; #if defined(_WIN32) - 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; + PROCESSOR_POWER_INFORMATION powerInfo[64]; + NTSTATUS status = + CallNtPowerInformation(ProcessorInformation, nullptr, 0, powerInfo, + sizeof(PROCESSOR_POWER_INFORMATION) * 64); + if (status == 0) { + this->CPUSpeedInMHz = (float)powerInfo[0].MaxMhz; retrieved = true; } + if (!retrieved) { + 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) {