📄 cpuinfo.cpp
字号:
//------------------------------------------------------------------------------
// CpuInfo.cpp
//
// This file contains the class CpuInfo. It basically determines all
// pertinent information for the CPU. It currently gets in-depth
// information for both Intel and AMD CPUs.
//
// Parts of this code were submitted by and should be credited to:
// Alexandre Cesari [acesari@aclogic.com] -- CPU Speed detection
//
// Copyright (c) 2001 Paul Wendt [p-wendt@wideopenwest.com]
//
// Updates J. Michael McGarrah [mcgarrah@mcgarware.com]
//
#include "CpuInfo.h"
#include <tchar.h> // for _T [registry searches]
#include <sstream>
using namespace std;
//---------------------------------------------------------------------------
// CPU information defines -- VERY x86-dependent stuff going on here
//
#define CPU_ID __asm _emit 0xf __asm _emit 0xa2
const int CpuInfo::BRANDTABLESIZE = 4;
CpuInfo::CpuInfo(const bool fCpuSpeed/* = true*/, const bool fDebug /* = false */)
{
m_fDebug = fDebug;
m_strCpuSpeed = "0";
determineCpuInfo();
if (fCpuSpeed)
{
determineCpuSpeed();
}
m_osDebugResults << ends;
std::string d = m_osDebugResults.str();
}
CpuInfo::CpuInfo(const CpuInfo& source)
{
assign(source);
}
CpuInfo& CpuInfo::operator=(const CpuInfo& right)
{
if (this != &right)
{
assign(right);
}
return (*this);
}
CpuInfo::~CpuInfo()
{
// nothing to do yet
}
void CpuInfo::determineCpuInfo(void)
{
SYSTEM_INFO stCpuInfo;
GetSystemInfo(&stCpuInfo);
ostringstream os;
os << stCpuInfo.dwNumberOfProcessors << ends;
m_strNumProcessors = os.str();
if (m_fDebug) m_osDebugResults << "# CPUs detected: " << stCpuInfo.dwNumberOfProcessors << endl;
determineCpuStats(stCpuInfo.wProcessorArchitecture);
}
// this is pretty straight forward. as long as it's a fairly-recent processor, we'll
// try to get the speed. first, though, we set the priority to high ... so that
// we'll get a greater chance of getting the correct speed.
// the primary algorithm is very accurate, but not supported across all x86 processors.
// the second approach is to get the speed from the registry; this isn't supported
// on all platforms, so ...
// the third approach just does a crude and slow benchmark.
void CpuInfo::determineCpuSpeed(void)
{
if ( ((m_cpuStats.getVendor() == CpuStats::VENDOR_INTEL) && (m_cpuStats.getFamily() > 4)) ||
((m_cpuStats.getVendor() == CpuStats::VENDOR_AMD) && (m_cpuStats.getFamily() > 5)) )
{
DWORD dwStartingPriority = GetPriorityClass(GetCurrentProcess());
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
DWORD dwSpeed = calculateCpuSpeed();
if (m_fDebug) m_osDebugResults << "CPU Speed from QueryPerformanceFrequency: " << dwSpeed << endl;
if (dwSpeed == 0)
{
dwSpeed = getCpuSpeedFromRegistry();
if (m_fDebug) m_osDebugResults << "CPU Speed from Registry [NT only]" << dwSpeed << endl;
if (dwSpeed == 0)
{
dwSpeed = calculateCpuSpeedMethod2();
if (m_fDebug) m_osDebugResults << "CPU Speed -- old, slow method: " << dwSpeed << endl;
}
}
SetPriorityClass(GetCurrentProcess(), dwStartingPriority);
// if it's still 0 at this point, god help us all
if (dwSpeed == 0)
{
m_strCpuSpeed = "Unknown";
}
else
{
ostringstream os;
os << dwSpeed << " MHz" << ends;
m_strCpuSpeed = os.str();
}
}
if (m_fDebug) m_osDebugResults << "Final determined speed: " << m_strCpuSpeed << endl;
}
void CpuInfo::assign(const CpuInfo& source)
{
m_cpuStats = source.m_cpuStats;
m_strCpuSpeed = source.m_strCpuSpeed;
m_strNumProcessors = source.m_strNumProcessors;
m_fDebug = source.m_fDebug;
m_osDebugResults << source.m_osDebugResults.str();
}
void CpuInfo::determineCpuStats(WORD wProcessorArchitecture)
{
// make sure the cpu knows CPUID
if (!determineCpuId())
{
return;
}
m_cpuStats.setKnowsCpuId(true);
DWORD dwHighestCpuId = determineHighestCpuId();
switch (dwHighestCpuId)
{
default:
case 2: // intel cpu's find cache information here
determineIntelCacheInfo();
// no break;
case 1: // x86 cpu's do processor identification here
determineCpuIdentification();
break;
case 0: // don't do anything funky; return
return;
}
if (m_cpuStats.getVendor() == CpuStats::VENDOR_INTEL)
{
determineOldIntelName();
}
DWORD dwLargestExtendedFeature = determineLargestExtendedFeature();
if (dwLargestExtendedFeature >= AMD_L2CACHE_FEATURE)
{
determineAmdL2CacheInfo();
}
if (dwLargestExtendedFeature >= AMD_L1CACHE_FEATURE)
{
determineAmdL1CacheInfo();
}
if (dwLargestExtendedFeature >= NAMESTRING_FEATURE)
{
determineNameString();
}
if (dwLargestExtendedFeature >= AMD_EXTENDED_FEATURE)
{
determineExtendedFeature();
}
}
bool CpuInfo::determineCpuId(void)
{
int fKnowsCpuId = 0;
__asm
{
pushfd // save EFLAGS to stack.
pop eax // store EFLAGS in EAX.
mov edx, eax // save in EBX for testing later.
xor eax, 0200000h // switch bit 21.
push eax // copy "changed" value to stack.
popfd // save "changed" EAX to EFLAGS.
pushfd
pop eax
xor eax, edx // See if bit changeable.
jnz short has_cpuid // if so, mark
mov fKnowsCpuId, 0 // if not, put 0
jmp done
has_cpuid:
mov fKnowsCpuId, 1 // put 1
done:
}
if (m_fDebug) m_osDebugResults << "CPU knows CPUID: " << fKnowsCpuId << endl;
return ((bool)fKnowsCpuId);
}
DWORD CpuInfo::determineHighestCpuId(void)
{
DWORD dwHighest = 0;
char szTemp[16] = {0};
__asm
{
mov eax, 0
CPUID
test eax,eax // 0 is highest function, then don't query more info
jz no_features
mov dwHighest, eax // highest supported instruction
mov DWORD PTR [szTemp+0],ebx // Stash the manufacturer string for later
mov DWORD PTR [szTemp+4],edx
mov DWORD PTR [szTemp+8],ecx
no_features:
}
if (dwHighest != 0)
{
string strVendorId = szTemp;
m_cpuStats.setVendorId(strVendorId);
}
if (m_fDebug) m_osDebugResults << "Highest CPUID is: " << dwHighest << endl;
return (dwHighest);
}
void CpuInfo::determineCpuIdentification(void)
{
DWORD dwSignature = 0;
DWORD dwFeatureEbx = 0;
DWORD dwFeatureEcx = 0 ;
DWORD dwFeatures = 0;
__asm
{
mov eax, 1
CPUID
mov [dwSignature], eax // store CPU signature
mov [dwFeatureEbx], ebx
mov [dwFeatureEcx], ecx
mov [dwFeatures], edx // features
}
m_cpuStats.setSignature(dwSignature);
m_cpuStats.setFeatureEbx(dwFeatureEbx);
m_cpuStats.setFeatureEcx(dwFeatureEcx);
m_cpuStats.setFeatures(dwFeatures);
if (m_fDebug) m_osDebugResults << "CPU Signature: " << dwSignature << endl;
if (m_fDebug) m_osDebugResults << "CPU Feature EBX: " << dwFeatureEbx << endl;
if (m_fDebug) m_osDebugResults << "CPU Feature ECX: " << dwFeatureEcx << endl;
if (m_fDebug) m_osDebugResults << "CPU Features: " << dwFeatures << endl;
}
DWORD CpuInfo::determineLargestExtendedFeature(void)
{
DWORD dwHighest = 0;
__asm
{
mov eax, 0x80000000
CPUID
mov dwHighest, eax
}
if (m_fDebug) m_osDebugResults << "Largest extended CPU feature: " << dwHighest << endl;
return (dwHighest);
}
void CpuInfo::determineExtendedFeature(void)
{
DWORD dwExtendedFeatures = 0;
__asm
{
mov eax, 0x80000001
CPUID
mov dwExtendedFeatures, edx
}
m_cpuStats.setExtendedFeatures(dwExtendedFeatures);
if (m_fDebug) m_osDebugResults << "CPU Extended features: " << dwExtendedFeatures << endl;
}
void CpuInfo::determineNameString(void)
{
char szName[64] = {0};
__asm
{
mov eax, 0x80000002
CPUID
mov DWORD PTR [szName+0],eax
mov DWORD PTR [szName+4],ebx
mov DWORD PTR [szName+8],ecx
mov DWORD PTR [szName+12],edx
mov eax, 0x80000003
CPUID
mov DWORD PTR [szName+16],eax
mov DWORD PTR [szName+20],ebx
mov DWORD PTR [szName+24],ecx
mov DWORD PTR [szName+28],edx
mov eax, 0x80000004
CPUID
mov DWORD PTR [szName+32],eax
mov DWORD PTR [szName+36],ebx
mov DWORD PTR [szName+40],ecx
mov DWORD PTR [szName+44],edx
}
m_cpuStats.setName(szName);
if (m_fDebug) m_osDebugResults << "CPU name string: " << szName << endl;
}
void CpuInfo::determineAmdL1CacheInfo(void)
{
DWORD dwEax = 0;
DWORD dwEbx = 0;
DWORD dwEcx = 0;
DWORD dwEdx = 0;
__asm
{
mov eax, 0x80000005
CPUID
mov dwEax, eax
mov dwEbx, ebx
mov dwEcx, ecx
mov dwEdx, edx
}
m_cpuStats.setCacheEax(dwEax);
m_cpuStats.setCacheEbx(dwEbx);
m_cpuStats.setCacheEcx(dwEcx);
m_cpuStats.setCacheEdx(dwEdx);
if (m_fDebug) m_osDebugResults << "L1 Cache Info EAX: " << dwEax << endl;
if (m_fDebug) m_osDebugResults << "L1 Cache Info EBX: " << dwEbx << endl;
if (m_fDebug) m_osDebugResults << "L1 Cache Info ECX: " << dwEcx << endl;
if (m_fDebug) m_osDebugResults << "L1 Cache Info EDX: " << dwEdx << endl;
}
void CpuInfo::determineAmdL2CacheInfo(void)
{
DWORD dwEax = 0;
DWORD dwEbx = 0;
DWORD dwEcx = 0;
DWORD dwEdx = 0;
__asm
{
mov eax, 0x80000006
CPUID
mov dwEax, eax
mov dwEbx, ebx
mov dwEcx, ecx
mov dwEdx, edx
}
m_cpuStats.setCache2Eax(dwEax);
m_cpuStats.setCache2Ebx(dwEbx);
m_cpuStats.setCache2Ecx(dwEcx);
m_cpuStats.setCache2Edx(dwEdx);
if (m_fDebug) m_osDebugResults << "L2 Cache Info EAX: " << dwEax << endl;
if (m_fDebug) m_osDebugResults << "L2 Cache Info EBX: " << dwEbx << endl;
if (m_fDebug) m_osDebugResults << "L2 Cache Info ECX: " << dwEcx << endl;
if (m_fDebug) m_osDebugResults << "L2 Cache Info EDX: " << dwEdx << endl;
}
void CpuInfo::determineIntelCacheInfo(void)
{
DWORD dwEax = 0;
DWORD dwEbx = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -