mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-26 08:29:54 -06:00
Merge branch 'upstream-KWSys' into update-kwsys
* upstream-KWSys: KWSys 2017-02-14 (5c6f7836)
This commit is contained in:
@@ -35,8 +35,13 @@
|
|||||||
#include "SystemInformation.hxx.in"
|
#include "SystemInformation.hxx.in"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <bitset>
|
||||||
|
#include <cassert>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -394,7 +399,6 @@ public:
|
|||||||
bool SupportsMP;
|
bool SupportsMP;
|
||||||
bool HasMMXPlus;
|
bool HasMMXPlus;
|
||||||
bool HasSSEMMX;
|
bool HasSSEMMX;
|
||||||
bool SupportsHyperthreading;
|
|
||||||
unsigned int LogicalProcessorsPerPhysical;
|
unsigned int LogicalProcessorsPerPhysical;
|
||||||
int APIC_ID;
|
int APIC_ID;
|
||||||
CPUPowerManagement PowerManagement;
|
CPUPowerManagement PowerManagement;
|
||||||
@@ -463,10 +467,9 @@ protected:
|
|||||||
unsigned int NumberOfLogicalCPU;
|
unsigned int NumberOfLogicalCPU;
|
||||||
unsigned int NumberOfPhysicalCPU;
|
unsigned int NumberOfPhysicalCPU;
|
||||||
|
|
||||||
int CPUCount(); // For windows
|
void CPUCountWindows(); // For windows
|
||||||
unsigned char LogicalCPUPerPhysicalCPU();
|
|
||||||
unsigned char GetAPICId(); // For windows
|
unsigned char GetAPICId(); // For windows
|
||||||
bool IsHyperThreadingSupported();
|
bool IsSMTSupported();
|
||||||
static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows
|
static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows
|
||||||
|
|
||||||
// For Linux and Cygwin, /proc/cpuinfo formats are slightly different
|
// For Linux and Cygwin, /proc/cpuinfo formats are slightly different
|
||||||
@@ -1542,7 +1545,7 @@ void SystemInformationImplementation::RunCPUCheck()
|
|||||||
RetrieveProcessorSerialNumber();
|
RetrieveProcessorSerialNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->CPUCount();
|
this->CPUCountWindows();
|
||||||
|
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
this->ParseSysCtl();
|
this->ParseSysCtl();
|
||||||
@@ -2090,16 +2093,10 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
|
|||||||
|
|
||||||
// Retrieve Intel specific extended features.
|
// Retrieve Intel specific extended features.
|
||||||
if (this->ChipManufacturer == Intel) {
|
if (this->ChipManufacturer == Intel) {
|
||||||
this->Features.ExtendedFeatures.SupportsHyperthreading =
|
bool SupportsSMT =
|
||||||
((cpuinfo[3] & 0x10000000) !=
|
((cpuinfo[3] & 0x10000000) != 0); // Intel specific: SMT --> Bit 28
|
||||||
0); // Intel specific: Hyperthreading --> Bit 28
|
|
||||||
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
|
|
||||||
(this->Features.ExtendedFeatures.SupportsHyperthreading)
|
|
||||||
? ((cpuinfo[1] & 0x00FF0000) >> 16)
|
|
||||||
: 1;
|
|
||||||
|
|
||||||
if ((this->Features.ExtendedFeatures.SupportsHyperthreading) &&
|
if ((SupportsSMT) && (this->Features.HasAPIC)) {
|
||||||
(this->Features.HasAPIC)) {
|
|
||||||
// Retrieve APIC information if there is one present.
|
// Retrieve APIC information if there is one present.
|
||||||
this->Features.ExtendedFeatures.APIC_ID =
|
this->Features.ExtendedFeatures.APIC_ID =
|
||||||
((cpuinfo[1] & 0xFF000000) >> 24);
|
((cpuinfo[1] & 0xFF000000) >> 24);
|
||||||
@@ -3401,7 +3398,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
|
|||||||
fclose(fd);
|
fclose(fd);
|
||||||
buffer.resize(fileSize - 2);
|
buffer.resize(fileSize - 2);
|
||||||
// Number of logical CPUs (combination of multiple processors, multi-core
|
// Number of logical CPUs (combination of multiple processors, multi-core
|
||||||
// and hyperthreading)
|
// and SMT)
|
||||||
size_t pos = buffer.find("processor\t");
|
size_t pos = buffer.find("processor\t");
|
||||||
while (pos != buffer.npos) {
|
while (pos != buffer.npos) {
|
||||||
this->NumberOfLogicalCPU++;
|
this->NumberOfLogicalCPU++;
|
||||||
@@ -3409,30 +3406,25 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux
|
#ifdef __linux
|
||||||
// Find the largest physical id.
|
// Count sockets.
|
||||||
int maxId = -1;
|
std::set<int> PhysicalIDs;
|
||||||
std::string idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id");
|
std::string idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id");
|
||||||
while (this->CurrentPositionInFile != buffer.npos) {
|
while (this->CurrentPositionInFile != buffer.npos) {
|
||||||
int id = atoi(idc.c_str());
|
int id = atoi(idc.c_str());
|
||||||
if (id > maxId) {
|
PhysicalIDs.insert(id);
|
||||||
maxId = id;
|
|
||||||
}
|
|
||||||
idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id",
|
idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id",
|
||||||
this->CurrentPositionInFile + 1);
|
this->CurrentPositionInFile + 1);
|
||||||
}
|
}
|
||||||
|
uint64_t NumberOfSockets = PhysicalIDs.size();
|
||||||
|
NumberOfSockets = std::max(NumberOfSockets, (uint64_t)1);
|
||||||
// Physical ids returned by Linux don't distinguish cores.
|
// Physical ids returned by Linux don't distinguish cores.
|
||||||
// We want to record the total number of cores in this->NumberOfPhysicalCPU
|
// We want to record the total number of cores in this->NumberOfPhysicalCPU
|
||||||
// (checking only the first proc)
|
// (checking only the first proc)
|
||||||
std::string cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores");
|
std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores");
|
||||||
int numberOfCoresPerCPU = atoi(cores.c_str());
|
unsigned int NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str());
|
||||||
if (maxId > 0) {
|
NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u);
|
||||||
this->NumberOfPhysicalCPU =
|
this->NumberOfPhysicalCPU =
|
||||||
static_cast<unsigned int>(numberOfCoresPerCPU * (maxId + 1));
|
NumberOfCoresPerSocket * (unsigned int)NumberOfSockets;
|
||||||
} else {
|
|
||||||
// Linux Sparc: get cpu count
|
|
||||||
this->NumberOfPhysicalCPU =
|
|
||||||
atoi(this->ExtractValueFromCpuInfoFile(buffer, "ncpus active").c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // __CYGWIN__
|
#else // __CYGWIN__
|
||||||
// does not have "physical id" entries, neither "cpu cores"
|
// does not have "physical id" entries, neither "cpu cores"
|
||||||
@@ -3447,7 +3439,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
|
|||||||
if (this->NumberOfPhysicalCPU <= 0) {
|
if (this->NumberOfPhysicalCPU <= 0) {
|
||||||
this->NumberOfPhysicalCPU = 1;
|
this->NumberOfPhysicalCPU = 1;
|
||||||
}
|
}
|
||||||
// LogicalProcessorsPerPhysical>1 => hyperthreading.
|
// LogicalProcessorsPerPhysical>1 => SMT.
|
||||||
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
|
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
|
||||||
this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU;
|
this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU;
|
||||||
|
|
||||||
@@ -4322,68 +4314,10 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS)
|
|||||||
(void)uiMS;
|
(void)uiMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the number of logical CPU per physical CPUs Works only for windows
|
|
||||||
*/
|
|
||||||
unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void)
|
|
||||||
{
|
|
||||||
#ifdef __APPLE__
|
|
||||||
size_t len = 4;
|
|
||||||
int cores_per_package = 0;
|
|
||||||
int err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package,
|
|
||||||
&len, NULL, 0);
|
|
||||||
if (err != 0) {
|
|
||||||
return 1; // That name was not found, default to 1
|
|
||||||
}
|
|
||||||
return static_cast<unsigned char>(cores_per_package);
|
|
||||||
#else
|
|
||||||
int Regs[4] = { 0, 0, 0, 0 };
|
|
||||||
#if USE_CPUID
|
|
||||||
if (!this->IsHyperThreadingSupported()) {
|
|
||||||
return static_cast<unsigned char>(1); // HT not supported
|
|
||||||
}
|
|
||||||
call_cpuid(1, Regs);
|
|
||||||
#endif
|
|
||||||
return static_cast<unsigned char>((Regs[1] & NUM_LOGICAL_BITS) >> 16);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Works only for windows */
|
/** Works only for windows */
|
||||||
bool SystemInformationImplementation::IsHyperThreadingSupported()
|
bool SystemInformationImplementation::IsSMTSupported()
|
||||||
{
|
{
|
||||||
if (this->Features.ExtendedFeatures.SupportsHyperthreading) {
|
return this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical > 1;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if USE_CPUID
|
|
||||||
int Regs[4] = { 0, 0, 0, 0 }, VendorId[4] = { 0, 0, 0, 0 };
|
|
||||||
// Get vendor id string
|
|
||||||
if (!call_cpuid(0, VendorId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// eax contains family processor type
|
|
||||||
// edx has info about the availability of hyper-Threading
|
|
||||||
if (!call_cpuid(1, Regs)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID)) {
|
|
||||||
if (VendorId[1] == 0x756e6547) // 'uneG'
|
|
||||||
{
|
|
||||||
if (VendorId[3] == 0x49656e69) // 'Ieni'
|
|
||||||
{
|
|
||||||
if (VendorId[2] == 0x6c65746e) // 'letn'
|
|
||||||
{
|
|
||||||
// Genuine Intel with hyper-Threading technology
|
|
||||||
this->Features.ExtendedFeatures.SupportsHyperthreading =
|
|
||||||
((Regs[3] & HT_BIT) != 0);
|
|
||||||
return this->Features.ExtendedFeatures.SupportsHyperthreading;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0; // Not genuine Intel processor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the APIC Id. Works only for windows. */
|
/** Return the APIC Id. Works only for windows. */
|
||||||
@@ -4392,7 +4326,7 @@ unsigned char SystemInformationImplementation::GetAPICId()
|
|||||||
int Regs[4] = { 0, 0, 0, 0 };
|
int Regs[4] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
#if USE_CPUID
|
#if USE_CPUID
|
||||||
if (!this->IsHyperThreadingSupported()) {
|
if (!this->IsSMTSupported()) {
|
||||||
return static_cast<unsigned char>(-1); // HT not supported
|
return static_cast<unsigned char>(-1); // HT not supported
|
||||||
} // Logical processor = 1
|
} // Logical processor = 1
|
||||||
call_cpuid(1, Regs);
|
call_cpuid(1, Regs);
|
||||||
@@ -4402,102 +4336,46 @@ unsigned char SystemInformationImplementation::GetAPICId()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Count the number of CPUs. Works only on windows. */
|
/** Count the number of CPUs. Works only on windows. */
|
||||||
int SystemInformationImplementation::CPUCount()
|
void SystemInformationImplementation::CPUCountWindows()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
unsigned char StatusFlag = 0;
|
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> ProcInfo;
|
||||||
SYSTEM_INFO info;
|
|
||||||
|
|
||||||
this->NumberOfPhysicalCPU = 0;
|
this->NumberOfPhysicalCPU = 0;
|
||||||
this->NumberOfLogicalCPU = 0;
|
this->NumberOfLogicalCPU = 0;
|
||||||
info.dwNumberOfProcessors = 0;
|
|
||||||
GetSystemInfo(&info);
|
|
||||||
|
|
||||||
// Number of physical processors in a non-Intel system
|
{
|
||||||
// or in a 32-bit Intel system with Hyper-Threading technology disabled
|
DWORD Length = 0;
|
||||||
this->NumberOfPhysicalCPU = (unsigned char)info.dwNumberOfProcessors;
|
DWORD rc = GetLogicalProcessorInformation(NULL, &Length);
|
||||||
|
assert(FALSE == rc);
|
||||||
if (this->IsHyperThreadingSupported()) {
|
(void)rc; // Silence unused variable warning in Borland C++ 5.81
|
||||||
unsigned char HT_Enabled = 0;
|
assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
|
||||||
this->NumberOfLogicalCPU = this->LogicalCPUPerPhysicalCPU();
|
ProcInfo.resize(Length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
|
||||||
if (this->NumberOfLogicalCPU >=
|
rc = GetLogicalProcessorInformation(&ProcInfo[0], &Length);
|
||||||
1) // >1 Doesn't mean HT is enabled in the BIOS
|
assert(rc != FALSE);
|
||||||
{
|
(void)rc; // Silence unused variable warning in Borland C++ 5.81
|
||||||
HANDLE hCurrentProcessHandle;
|
|
||||||
#ifndef _WIN64
|
|
||||||
#define DWORD_PTR DWORD
|
|
||||||
#endif
|
|
||||||
DWORD_PTR dwProcessAffinity;
|
|
||||||
DWORD_PTR dwSystemAffinity;
|
|
||||||
DWORD dwAffinityMask;
|
|
||||||
|
|
||||||
// Calculate the appropriate shifts and mask based on the
|
|
||||||
// number of logical processors.
|
|
||||||
unsigned int i = 1;
|
|
||||||
unsigned char PHY_ID_MASK = 0xFF;
|
|
||||||
// unsigned char PHY_ID_SHIFT = 0;
|
|
||||||
|
|
||||||
while (i < this->NumberOfLogicalCPU) {
|
|
||||||
i *= 2;
|
|
||||||
PHY_ID_MASK <<= 1;
|
|
||||||
// PHY_ID_SHIFT++;
|
|
||||||
}
|
|
||||||
|
|
||||||
hCurrentProcessHandle = GetCurrentProcess();
|
|
||||||
GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity,
|
|
||||||
&dwSystemAffinity);
|
|
||||||
|
|
||||||
// Check if available process affinity mask is equal to the
|
|
||||||
// available system affinity mask
|
|
||||||
if (dwProcessAffinity != dwSystemAffinity) {
|
|
||||||
StatusFlag = HT_CANNOT_DETECT;
|
|
||||||
this->NumberOfPhysicalCPU = (unsigned char)-1;
|
|
||||||
return StatusFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
dwAffinityMask = 1;
|
|
||||||
while (dwAffinityMask != 0 && dwAffinityMask <= dwProcessAffinity) {
|
|
||||||
// Check if this CPU is available
|
|
||||||
if (dwAffinityMask & dwProcessAffinity) {
|
|
||||||
if (SetProcessAffinityMask(hCurrentProcessHandle, dwAffinityMask)) {
|
|
||||||
unsigned char APIC_ID, LOG_ID;
|
|
||||||
Sleep(0); // Give OS time to switch CPU
|
|
||||||
|
|
||||||
APIC_ID = GetAPICId();
|
|
||||||
LOG_ID = APIC_ID & ~PHY_ID_MASK;
|
|
||||||
|
|
||||||
if (LOG_ID != 0) {
|
|
||||||
HT_Enabled = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dwAffinityMask = dwAffinityMask << 1;
|
|
||||||
}
|
|
||||||
// Reset the processor affinity
|
|
||||||
SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity);
|
|
||||||
|
|
||||||
if (this->NumberOfLogicalCPU ==
|
|
||||||
1) // Normal P4 : HT is disabled in hardware
|
|
||||||
{
|
|
||||||
StatusFlag = HT_DISABLED;
|
|
||||||
} else {
|
|
||||||
if (HT_Enabled) {
|
|
||||||
// Total physical processors in a Hyper-Threading enabled system.
|
|
||||||
this->NumberOfPhysicalCPU /= (this->NumberOfLogicalCPU);
|
|
||||||
StatusFlag = HT_ENABLED;
|
|
||||||
} else {
|
|
||||||
StatusFlag = HT_SUPPORTED_NOT_ENABLED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Processors do not have Hyper-Threading technology
|
|
||||||
StatusFlag = HT_NOT_CAPABLE;
|
|
||||||
this->NumberOfLogicalCPU = 1;
|
|
||||||
}
|
}
|
||||||
return StatusFlag;
|
|
||||||
|
typedef std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>::iterator
|
||||||
|
pinfoIt_t;
|
||||||
|
for (pinfoIt_t it = ProcInfo.begin(); it != ProcInfo.end(); ++it) {
|
||||||
|
SYSTEM_LOGICAL_PROCESSOR_INFORMATION PInfo = *it;
|
||||||
|
if (PInfo.Relationship != RelationProcessorCore) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::bitset<std::numeric_limits<ULONG_PTR>::digits> ProcMask(
|
||||||
|
(unsigned long long)PInfo.ProcessorMask);
|
||||||
|
unsigned int count = (unsigned int)ProcMask.count();
|
||||||
|
if (count == 0) { // I think this should never happen, but just to be safe.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this->NumberOfPhysicalCPU++;
|
||||||
|
this->NumberOfLogicalCPU += (unsigned int)count;
|
||||||
|
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = count;
|
||||||
|
}
|
||||||
|
this->NumberOfPhysicalCPU = std::max(1u, this->NumberOfPhysicalCPU);
|
||||||
|
this->NumberOfLogicalCPU = std::max(1u, this->NumberOfLogicalCPU);
|
||||||
#else
|
#else
|
||||||
return 0;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4559,8 +4437,14 @@ bool SystemInformationImplementation::ParseSysCtl()
|
|||||||
sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0);
|
sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0);
|
||||||
len = sizeof(this->NumberOfLogicalCPU);
|
len = sizeof(this->NumberOfLogicalCPU);
|
||||||
sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0);
|
sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0);
|
||||||
|
|
||||||
|
int cores_per_package = 0;
|
||||||
|
len = sizeof(cores_per_package);
|
||||||
|
err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, &len,
|
||||||
|
NULL, 0);
|
||||||
|
// That name was not found, default to 1
|
||||||
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
|
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
|
||||||
this->LogicalCPUPerPhysicalCPU();
|
err != 0 ? 1 : static_cast<unsigned char>(cores_per_package);
|
||||||
|
|
||||||
len = sizeof(value);
|
len = sizeof(value);
|
||||||
sysctlbyname("hw.cpufrequency", &value, &len, NULL, 0);
|
sysctlbyname("hw.cpufrequency", &value, &len, NULL, 0);
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public:
|
|||||||
|
|
||||||
bool Is64Bits();
|
bool Is64Bits();
|
||||||
|
|
||||||
unsigned int GetNumberOfLogicalCPU(); // per physical cpu
|
unsigned int GetNumberOfLogicalCPU();
|
||||||
unsigned int GetNumberOfPhysicalCPU();
|
unsigned int GetNumberOfPhysicalCPU();
|
||||||
|
|
||||||
bool DoesCPUSupportCPUID();
|
bool DoesCPUSupportCPUID();
|
||||||
|
|||||||
Reference in New Issue
Block a user