With best regards, Thinker.
<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
With best regards, Thinker.
<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
With best regards, Thinker.
<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
Здравствуйте, Thinker, Вы писали:
сразу извиняюсь — это куски из проекта.
все не публикую ...
будут вопросы — пиши
Это хидер
#define SYSCPUSPEED_REPEAT 10
namespace pay {
class CSysCPUInfo : public ISysInfo {
public:
enum enumProcessorManufacturer {
Unknown = 0, AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta
};
enum enumCPUFeatures {
MMX_FEATURE = 0x00000001,
MMX_PLUS_FEATURE = 0x00000002,
SSE_FEATURE = 0x00000004,
SSE2_FEATURE = 0x00000008,
AMD_3DNOW_FEATURE = 0x00000010,
AMD_3DNOW_PLUS_FEATURE = 0x00000020,
IA64_FEATURE = 0x00000040,
MP_CAPABLE = 0x00000080,
HYPERTHREAD_FEATURE = 0x00000100,
SERIALNUMBER_FEATURE = 0x00000200,
APIC_FEATURE = 0x00000400,
SSE_FP_FEATURE = 0x00000800,
SSE_MMX_FEATURE = 0x00001000,
CMOV_FEATURE = 0x00002000,
MTRR_FEATURE = 0x00004000,
L1CACHE_FEATURE = 0x00008000,
L2CACHE_FEATURE = 0x00010000,
L3CACHE_FEATURE = 0x00020000,
ACPI_FEATURE = 0x00040000,
THERMALMONITOR_FEATURE = 0x00080000,
TEMPSENSEDIODE_FEATURE = 0x00100000,
FREQUENCYID_FEATURE = 0x00200000,
VOLTAGEID_FREQUENCY = 0x00400000
};
typedef struct tagCPUPowerManagement {
bool HasVoltageID;
bool HasFrequencyID;
bool HasTempSenseDiode;
} CPUPowerManagement;
typedef struct tagCPUExtendedFeatures {
bool Has3DNow;
bool Has3DNowPlus;
bool SupportsMP;
bool HasMMXPlus;
bool HasSSEMMX;
bool SupportsHyperthreading;
int LogicalProcessorsPerPhysical;
int APIC_ID;
CPUPowerManagement PowerManagement;
} CPUExtendedFeatures;
typedef struct tagCPUFeatures {
bool HasFPU;
bool HasTSC;
bool HasMMX;
bool HasSSE;
bool HasSSEFP;
bool HasSSE2;
bool HasIA64;
bool HasAPIC;
bool HasCMOV;
bool HasMTRR;
bool HasACPI;
bool HasSerial;
bool HasThermal;
int L1CacheSize;
int L2CacheSize;
int L3CacheSize;
CPUExtendedFeatures ExtendedFeatures;
} CPUFeatures;
typedef struct _CPUID {
int dwProcessorUsage;
TCHAR szSerialNumber[30];
} CPUID, PCPUID;
typedef struct _CPUINFO {
DWORD dwNumProcessors;
DWORD dwMhz;
DWORD dwPageSize;
DWORD dwChipManufacturer;
DWORD dwType;
DWORD dwFamily;
DWORD dwModel;
DWORD dwRevision;
DWORD dwExtendedFamily;
DWORD dwExtendedModel;
DWORD dwCPUFeatures;
CPUFeatures Features;
TCHAR szProcessorArchitecture[MAX_PATH];
TCHAR szProcessorName[MAX_PATH];
TCHAR szVendorName[MAX_PATH];
vector<CPUID> idCPU;
} CPUINFO, *PCPUINFO;
void getInfo();
string getSysInfoName();
EnumSysInfo getSysInfoNum();
/**
получить исчерпывающую информацию о процессоре
*/
static BOOL getCPUInfo( CPUINFO &);
/**
получить информацию о производителе процессора
*/
static string getProcessorVendor();
/**
получить информацию о тактовой частоте на процессоре
*/
static DWORD getProcessorSpeed();
/**
получить уникальный фабричный номер процессора
Параметры
[input] dwProcNum - номер запрашиваемого процессора ( 0 - первый проц )
*/
static string getProcessorID( DWORD dwProcNum = 0 );
/**
получить информацию о загрузке процессора dwProcNum
*/
static DWORD getProcessorUsage( DWORD dwProcNum = 0 );
/**
количество процессоров
*/
static DWORD getNumProcessors();
/**
архитектура процессора
*/
static string getProcessorArchitecture();
/**
*/
static string getProcessorLevel();
/**
*/
static DWORD getProcessorPageSize();
/**
возращает строку с названием фирмы-производителя процессора
*/
static string GetVendorID (enumProcessorManufacturer dwChipManufacturer);
/**
проверяет - можно ли получить CPU ID
*/
static BOOL checkCPUID();
// static BOOL getCPUID(CPUINFO &cpuinfo);
void getInfoAsXML(ISysXMLInfo & );
static DWORD getProcessorType();
static DWORD getProcessorFamily();
static DWORD getProcessorModel();
static DWORD getProcessorStepping();
static string getProcessorIdentifier();
static string getProcessorSerialNumber(DWORD dwNum);
static DWORD getLogicalProcessorsPerPhysical ();
static DWORD getProcessorCacheXSize (DWORD dwCacheID);
static BOOL checkCPUSupportFeature(enumCPUFeatures Feature);
static BOOL getCPUFeatures(DWORD &dwFeature);
static DWORD getProcessorExtendedFamily();
static DWORD getProcessorExtendedModel();
static DWORD getProcessorFeatures();
static DWORD getProcessorRevision();
static string getProcessorManufacturer( enumProcessorManufacturer ChipManufacturer);
private:
static CPUINFO m_cpuinfo;
// static CPUFeatures Features;
static void getProcessorArchitectureAndLevel();
static BOOL m_bChecked;
static TCHAR *ssCPUVendors[];
};
}
а это код
#include <tchar.h>
#include <process.h>
#include <Aclapi.h>
// #include "ntdll.h"
#include "SysOSInfo.h"
#include "SysCPUInfo.h"
#define STORE_TLBCACHE_INFO(x,y) x = (x < y) ? y : x
#define VENDOR_STRING_LENGTH (12 + 1)
#define CHIPNAME_STRING_LENGTH (48 + 1)
#define SERIALNUMBER_STRING_LENGTH (29 + 1)
#define TLBCACHE_INFO_UNITS (15)
#define CLASSICAL_CPU_FREQ_LOOP 10000000
#define I16TO32(x, y) (((DWORD) x << 16) + y)
#define I32TO64(x, y) (((__int64) x << 32) + y)
#define RDTSC_INSTRUCTION _asm _emit 0x0f _asm _emit 0x31
#ifdef CPUID_AWARE_COMPILER
#define CPUID_INSTRUCTION cpuid
#else
#define CPUID_INSTRUCTION _asm _emit 0x0f _asm _emit 0xa2
#endif
typedef LONG NTSTATUS;
typedef struct _SYSTEM_PROCESSOR_TIMES {//Information Class 8
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER DpcTime;
LARGE_INTEGER InterruptTime;
ULONG InterruptCount;
}SYSTEM_PROCESSOR_TIMES,*PSYSTEM_PROCESSOR_TIMES;
typedef void (*DELAY_FUNC)(unsigned int uiMS);
pay::CSysCPUInfo::CPUINFO pay::CSysCPUInfo::m_cpuinfo; // = {0,0,0,0,0,0,0,0};
BOOL pay::CSysCPUInfo::m_bChecked = FALSE;
TCHAR *pay::CSysCPUInfo::ssCPUVendors[] = {
"Unknown Manufacturer",
"Advanced Micro Devices",
"Intel Corporation",
"National Semiconductor",
"United Microelectronics Corp.",
"Cyrix Corp., VIA Inc.",
"NexGen Inc., Advanced Micro Devices",
"IDT\\Centaur, Via Inc.",
"Rise",
"Transmeta"
};
int getProcessorSignature() {
int CPUSignature,APICID;
// Use assembly to detect CPUID information...
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser doesn't know about <<CPUID>>, and so doesn't expect
; these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
; eax = 1
; eax: CPU ID - bits 31..16 - unused,
; bits 15..12 - type,
; bits 11..8 - family,
; bits 7..4 - model,
; bits 3..0 - mask revision
; ebx: 31..24 - default APIC ID,
; 23..16 - logical processsor ID,
; 15..8 - CFLUSH chunk size ,
; 7..0 - brand ID
; edx: CPU feature flags
mov eax,1
CPUID_INSTRUCTION
mov CPUSignature, eax
mov APICID, ebx
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
} __except (1) {
// A generic catch-all just to be sure...
return 0;
}
return I16TO32(APICID,CPUSignature);
}
DWORD pay::CSysCPUInfo::getProcessorCacheXSize(DWORD dwCacheID) {
// Return the chosen cache size.
if (!m_bChecked)
m_bChecked = getCPUInfo(m_cpuinfo);
switch (dwCacheID) {
case L1CACHE_FEATURE:
return m_cpuinfo.Features.L1CacheSize;
case L2CACHE_FEATURE:
return m_cpuinfo.Features.L2CacheSize;
case L3CACHE_FEATURE:
return m_cpuinfo.Features.L3CacheSize;
}
// The user did something strange just return and error.
return -1;
}
BOOL pay::CSysCPUInfo::checkCPUSupportFeature(enumCPUFeatures dwFeature) {
BOOL bHasFeature = FALSE;
// DWORD dwFeature = (DWORD)Feature;
if ( !m_bChecked )
m_bChecked = getCPUInfo(m_cpuinfo);
// Check for MMX instructions.
if (((dwFeature & MMX_FEATURE) != 0) && m_cpuinfo.Features.HasMMX) bHasFeature = TRUE;
// Check for MMX+ instructions.
if (((dwFeature & MMX_PLUS_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.HasMMXPlus) bHasFeature = TRUE;
// Check for SSE FP instructions.
if (((dwFeature & SSE_FEATURE) != 0) && m_cpuinfo.Features.HasSSE) bHasFeature = TRUE;
// Check for SSE FP instructions.
if (((dwFeature & SSE_FP_FEATURE) != 0) && m_cpuinfo.Features.HasSSEFP) bHasFeature = TRUE;
// Check for SSE MMX instructions.
if (((dwFeature & SSE_MMX_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.HasSSEMMX) bHasFeature = TRUE;
// Check for SSE2 instructions.
if (((dwFeature & SSE2_FEATURE) != 0) && m_cpuinfo.Features.HasSSE2) bHasFeature = TRUE;
// Check for 3DNow! instructions.
if (((dwFeature & AMD_3DNOW_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.Has3DNow) bHasFeature = TRUE;
// Check for 3DNow+ instructions.
if (((dwFeature & AMD_3DNOW_PLUS_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.Has3DNowPlus) bHasFeature = TRUE;
// Check for IA64 instructions.
if (((dwFeature & IA64_FEATURE) != 0) && m_cpuinfo.Features.HasIA64) bHasFeature = TRUE;
// Check for MP capable.
if (((dwFeature & MP_CAPABLE) != 0) && m_cpuinfo.Features.ExtendedFeatures.SupportsMP) bHasFeature = TRUE;
// Check for a serial number for the processor.
if (((dwFeature & SERIALNUMBER_FEATURE) != 0) && m_cpuinfo.Features.HasSerial) bHasFeature = TRUE;
// Check for a local APIC in the processor.
if (((dwFeature & APIC_FEATURE) != 0) && m_cpuinfo.Features.HasAPIC) bHasFeature = TRUE;
// Check for CMOV instructions.
if (((dwFeature & CMOV_FEATURE) != 0) && m_cpuinfo.Features.HasCMOV) bHasFeature = TRUE;
// Check for MTRR instructions.
if (((dwFeature & MTRR_FEATURE) != 0) && m_cpuinfo.Features.HasMTRR) bHasFeature = TRUE;
// Check for L1 cache size.
if (((dwFeature & L1CACHE_FEATURE) != 0) && (m_cpuinfo.Features.L1CacheSize != -1)) bHasFeature = TRUE;
// Check for L2 cache size.
if (((dwFeature & L2CACHE_FEATURE) != 0) && (m_cpuinfo.Features.L2CacheSize != -1)) bHasFeature = TRUE;
// Check for L3 cache size.
if (((dwFeature & L3CACHE_FEATURE) != 0) && (m_cpuinfo.Features.L3CacheSize != -1)) bHasFeature = TRUE;
// Check for ACPI capability.
if (((dwFeature & ACPI_FEATURE) != 0) && m_cpuinfo.Features.HasACPI) bHasFeature = TRUE;
// Check for thermal monitor support.
if (((dwFeature & THERMALMONITOR_FEATURE) != 0) && m_cpuinfo.Features.HasThermal) bHasFeature = TRUE;
// Check for temperature sensing diode support.
if (((dwFeature & TEMPSENSEDIODE_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode) bHasFeature = TRUE;
// Check for frequency ID support.
if (((dwFeature & FREQUENCYID_FEATURE) != 0) && m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasFrequencyID) bHasFeature = TRUE;
// Check for voltage ID support.
if (((dwFeature & VOLTAGEID_FREQUENCY) != 0) && m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasVoltageID) bHasFeature = TRUE;
return bHasFeature;
}
bool RetrieveCPUExtendedLevelSupport (int CPULevelToCheck, pay::CSysCPUInfo::CPUINFO &cpu ) {
int MaxCPUExtendedLevel = 0;
// The extended CPUID is supported by various vendors starting with the following CPU models:
//
// Manufacturer & Chip Name | Family Model Revision
//
// AMD K6, K6-2 | 5 6 x
// Cyrix GXm, Cyrix III "Joshua" | 5 4 x
// IDT C6-2 | 5 8 x
// VIA Cyrix III | 6 5 x
// Transmeta Crusoe | 5 x x
// Intel Pentium 4 | f x x
//
// We check to see if a supported processor is present...
if (cpu.dwChipManufacturer == pay::CSysCPUInfo::AMD) {
if (cpu.dwFamily < 5) return false;
if ((cpu.dwFamily == 5) && (cpu.dwModel < 6)) return false;
}
else if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Cyrix) {
if (cpu.dwFamily < 5) return false;
if ((cpu.dwFamily == 5) && (cpu.dwModel < 4)) return false;
if ((cpu.dwFamily == 6) && (cpu.dwModel < 5)) return false;
}
else if (cpu.dwChipManufacturer == pay::CSysCPUInfo::IDT) {
if (cpu.dwFamily < 5) return false;
if ((cpu.dwFamily == 5) && (cpu.dwModel < 8)) return false;
}
else if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Transmeta) {
if (cpu.dwFamily < 5) return false;
}
else if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Intel) {
if (cpu.dwFamily < 0xf) return false;
}
// Use assembly to detect CPUID information...
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser doesn't know about <<CPUID>>, and so doesn't expect
; these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
; eax = 0x80000000 --> eax: maximum supported extended level
mov eax,0x80000000
CPUID_INSTRUCTION
mov MaxCPUExtendedLevel, eax
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
}
// A generic catch-all just to be sure...
__except (1) {
return false;
}
// Now we have to check the level wanted vs level returned...
int nLevelWanted = (CPULevelToCheck & 0x7FFFFFFF);
int nLevelReturn = (MaxCPUExtendedLevel & 0x7FFFFFFF);
// Check to see if the level provided is supported...
if (nLevelWanted > nLevelReturn) return false;
return true;
}
bool RetrieveExtendedCPUFeatures( pay::CSysCPUInfo::CPUINFO &cpu ) {
int CPUExtendedFeatures = 0;
// Check that we are not using an Intel processor as it does not support this.
if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Intel) return false;
// Check to see if what we are about to do is supported...
if (!RetrieveCPUExtendedLevelSupport (0x80000001,cpu)) return false;
// Use assembly to detect CPUID information...
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser doesn't know about <<CPUID>>, and so doesn't expect
; these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
; eax = 0x80000001 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
; edx: CPU feature flags
mov eax,0x80000001
CPUID_INSTRUCTION
mov CPUExtendedFeatures, edx
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
}
// A generic catch-all just to be sure...
__except (1) {
return false;
}
// Retrieve the extended features of CPU present.
cpu.Features.ExtendedFeatures.Has3DNow = ((CPUExtendedFeatures & 0x80000000) != 0); // 3DNow Present --> Bit 31.
cpu.Features.ExtendedFeatures.Has3DNowPlus = ((CPUExtendedFeatures & 0x40000000) != 0); // 3DNow+ Present -- > Bit 30.
cpu.Features.ExtendedFeatures.HasSSEMMX = ((CPUExtendedFeatures & 0x00400000) != 0); // SSE MMX Present --> Bit 22.
cpu.Features.ExtendedFeatures.SupportsMP = ((CPUExtendedFeatures & 0x00080000) != 0); // MP Capable -- > Bit 19.
// Retrieve AMD specific extended features.
if (cpu.dwChipManufacturer == pay::CSysCPUInfo::AMD) {
cpu.Features.ExtendedFeatures.HasMMXPlus = ((CPUExtendedFeatures & 0x00400000) != 0); // AMD specific: MMX-SSE --> Bit 22
}
// Retrieve Cyrix specific extended features.
if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Cyrix) {
cpu.Features.ExtendedFeatures.HasMMXPlus = ((CPUExtendedFeatures & 0x01000000) != 0); // Cyrix specific: Extended MMX --> Bit 24
}
return true;
}
bool RetrieveExtendedCPUIdentity (pay::CSysCPUInfo::CPUINFO &cpu) {
int ProcessorNameStartPos = 0;
int CPUExtendedIdentity[12];
// Check to see if what we are about to do is supported...
if (!RetrieveCPUExtendedLevelSupport (0x80000002,cpu)) return false;
if (!RetrieveCPUExtendedLevelSupport (0x80000003,cpu)) return false;
if (!RetrieveCPUExtendedLevelSupport (0x80000004,cpu)) return false;
// Use assembly to detect CPUID information...
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser doesn't know about <<CPUID>>, and so doesn't expect
; these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
; eax = 0x80000002 --> eax, ebx, ecx, edx: get processor name string (part 1)
mov eax,0x80000002
CPUID_INSTRUCTION
mov CPUExtendedIdentity[0 * TYPE int], eax
mov CPUExtendedIdentity[1 * TYPE int], ebx
mov CPUExtendedIdentity[2 * TYPE int], ecx
mov CPUExtendedIdentity[3 * TYPE int], edx
; <<CPUID>>
; eax = 0x80000003 --> eax, ebx, ecx, edx: get processor name string (part 2)
mov eax,0x80000003
CPUID_INSTRUCTION
mov CPUExtendedIdentity[4 * TYPE int], eax
mov CPUExtendedIdentity[5 * TYPE int], ebx
mov CPUExtendedIdentity[6 * TYPE int], ecx
mov CPUExtendedIdentity[7 * TYPE int], edx
; <<CPUID>>
; eax = 0x80000004 --> eax, ebx, ecx, edx: get processor name string (part 3)
mov eax,0x80000004
CPUID_INSTRUCTION
mov CPUExtendedIdentity[8 * TYPE int], eax
mov CPUExtendedIdentity[9 * TYPE int], ebx
mov CPUExtendedIdentity[10 * TYPE int], ecx
mov CPUExtendedIdentity[11 * TYPE int], edx
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
}
// A generic catch-all just to be sure...
__except (1) {
return false;
}
// Process the returned information.
memcpy (cpu.szProcessorName, &(CPUExtendedIdentity[0]), sizeof (int));
memcpy (&(cpu.szProcessorName[4]), &(CPUExtendedIdentity[1]), sizeof (int));
memcpy (&(cpu.szProcessorName[8]), &(CPUExtendedIdentity[2]), sizeof (int));
memcpy (&(cpu.szProcessorName[12]), &(CPUExtendedIdentity[3]), sizeof (int));
memcpy (&(cpu.szProcessorName[16]), &(CPUExtendedIdentity[4]), sizeof (int));
memcpy (&(cpu.szProcessorName[20]), &(CPUExtendedIdentity[5]), sizeof (int));
memcpy (&(cpu.szProcessorName[24]), &(CPUExtendedIdentity[6]), sizeof (int));
memcpy (&(cpu.szProcessorName[28]), &(CPUExtendedIdentity[7]), sizeof (int));
memcpy (&(cpu.szProcessorName[32]), &(CPUExtendedIdentity[8]), sizeof (int));
memcpy (&(cpu.szProcessorName[36]), &(CPUExtendedIdentity[9]), sizeof (int));
memcpy (&(cpu.szProcessorName[40]), &(CPUExtendedIdentity[10]), sizeof (int));
memcpy (&(cpu.szProcessorName[44]), &(CPUExtendedIdentity[11]), sizeof (int));
cpu.szProcessorName[48] = '\0';
// Because some manufacturers (<cough>Intel</cough>) have leading white space - we have to post-process the name.
if (cpu.dwChipManufacturer == pay::CSysCPUInfo::Intel) {
for (int nCounter = 0; nCounter < CHIPNAME_STRING_LENGTH; nCounter ++) {
// There will either be NULL (\0) or spaces ( ) as the leading characters.
if ((cpu.szProcessorName[nCounter] != '\0') && (cpu.szProcessorName[nCounter] != ' ')) {
// We have found the starting position of the name.
ProcessorNameStartPos = nCounter;
// Terminate the loop.
break;
}
}
// Check to see if there is any white space at the start.
if (ProcessorNameStartPos == 0) return true;
// Now move the name forward so that there is no white space.
memmove (cpu.szProcessorName, &(cpu.szProcessorName[ProcessorNameStartPos]), (CHIPNAME_STRING_LENGTH - ProcessorNameStartPos));
}
return true;
}
bool RetrieveCPUCacheDetails(pay::CSysCPUInfo::CPUINFO &cpu) {
bool bRes = true;
int L1Cache[4] = { 0, 0, 0, 0 };
int L2Cache[4] = { 0, 0, 0, 0 };
// Check to see if what we are about to do is supported...
if (RetrieveCPUExtendedLevelSupport (0x80000005,cpu)) {
// Use assembly to retrieve the L1 cache information ...
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser doesn't know about <<CPUID>>, and so doesn't expect
; these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
; eax = 0x80000005 --> eax: L1 cache information - Part 1 of 4.
; ebx: L1 cache information - Part 2 of 4.
; edx: L1 cache information - Part 3 of 4.
; ecx: L1 cache information - Part 4 of 4.
mov eax, 0x80000005
CPUID_INSTRUCTION
mov L1Cache[0 * TYPE int], eax
mov L1Cache[1 * TYPE int], ebx
mov L1Cache[2 * TYPE int], ecx
mov L1Cache[3 * TYPE int], edx
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
}
// A generic catch-all just to be sure...
__except (1) {
return false;
}
// Save the L1 data cache size (in KB) from ecx: bits 31..24 as well as data cache size from edx: bits 31..24.
cpu.Features.L1CacheSize = ((L1Cache[2] & 0xFF000000) >> 24);
cpu.Features.L1CacheSize += ((L1Cache[3] & 0xFF000000) >> 24);
} else {
// Store -1 to indicate the cache could not be queried.
cpu.Features.L1CacheSize = -1;
}
// Check to see if what we are about to do is supported...
if (RetrieveCPUExtendedLevelSupport (0x80000006,cpu)) {
// Use assembly to retrieve the L2 cache information ...
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser doesn't know about <<CPUID>>, and so doesn't expect
; these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
; eax = 0x80000006 --> eax: L2 cache information - Part 1 of 4.
; ebx: L2 cache information - Part 2 of 4.
; edx: L2 cache information - Part 3 of 4.
; ecx: L2 cache information - Part 4 of 4.
mov eax, 0x80000006
CPUID_INSTRUCTION
mov L2Cache[0 * TYPE int], eax
mov L2Cache[1 * TYPE int], ebx
mov L2Cache[2 * TYPE int], ecx
mov L2Cache[3 * TYPE int], edx
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
}
// A generic catch-all just to be sure...
__except (1) {
return false;
}
// Save the L2 unified cache size (in KB) from ecx: bits 31..16.
cpu.Features.L2CacheSize = ((L2Cache[2] & 0xFFFF0000) >> 16);
} else {
// Store -1 to indicate the cache could not be queried.
cpu.Features.L2CacheSize = -1;
}
// Define L3 as being not present as we cannot test for it.
cpu.Features.L3CacheSize = -1;
// Return failure if we cannot detect either cache with this method.
bRes = ((cpu.Features.L1CacheSize == -1) && (cpu.Features.L2CacheSize == -1)) ? false : true;
if (!bRes) {
int TLBCode = -1, TLBData = -1, L1Code = -1, L1Data = -1, L1Trace = -1, L2Unified = -1, L3Unified = -1;
int TLBCacheData[4] = { 0, 0, 0, 0 };
int TLBPassCounter = 0;
int TLBCacheUnit = 0;
do {
// Use assembly to retrieve the L2 cache information ...
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser doesn't know about <<CPUID>>, and so doesn't expect
; these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
; eax = 2 --> eax: TLB and cache information - Part 1 of 4.
; ebx: TLB and cache information - Part 2 of 4.
; ecx: TLB and cache information - Part 3 of 4.
; edx: TLB and cache information - Part 4 of 4.
mov eax, 2
CPUID_INSTRUCTION
mov TLBCacheData[0 * TYPE int], eax
mov TLBCacheData[1 * TYPE int], ebx
mov TLBCacheData[2 * TYPE int], ecx
mov TLBCacheData[3 * TYPE int], edx
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
}
// A generic catch-all just to be sure...
__except (1) {
return false;
}
int bob = ((TLBCacheData[0] & 0x00FF0000) >> 16);
// Process the returned TLB and cache information.
for (int nCounter = 0; nCounter < TLBCACHE_INFO_UNITS; nCounter ++) {
// First of all - decide which unit we are dealing with.
switch (nCounter) {
// eax: bits 8..15 : bits 16..23 : bits 24..31
case 0: TLBCacheUnit = ((TLBCacheData[0] & 0x0000FF00) >> 8); break;
case 1: TLBCacheUnit = ((TLBCacheData[0] & 0x00FF0000) >> 16); break;
case 2: TLBCacheUnit = ((TLBCacheData[0] & 0xFF000000) >> 24); break;
// ebx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
case 3: TLBCacheUnit = ((TLBCacheData[1] & 0x000000FF) >> 0); break;
case 4: TLBCacheUnit = ((TLBCacheData[1] & 0x0000FF00) >> 8); break;
case 5: TLBCacheUnit = ((TLBCacheData[1] & 0x00FF0000) >> 16); break;
case 6: TLBCacheUnit = ((TLBCacheData[1] & 0xFF000000) >> 24); break;
// ecx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
case 7: TLBCacheUnit = ((TLBCacheData[2] & 0x000000FF) >> 0); break;
case 8: TLBCacheUnit = ((TLBCacheData[2] & 0x0000FF00) >> 8); break;
case 9: TLBCacheUnit = ((TLBCacheData[2] & 0x00FF0000) >> 16); break;
case 10: TLBCacheUnit = ((TLBCacheData[2] & 0xFF000000) >> 24); break;
// edx: bits 0..7 : bits 8..15 : bits 16..23 : bits 24..31
case 11: TLBCacheUnit = ((TLBCacheData[3] & 0x000000FF) >> 0); break;
case 12: TLBCacheUnit = ((TLBCacheData[3] & 0x0000FF00) >> 8); break;
case 13: TLBCacheUnit = ((TLBCacheData[3] & 0x00FF0000) >> 16); break;
case 14: TLBCacheUnit = ((TLBCacheData[3] & 0xFF000000) >> 24); break;
// Default case - an error has occured.
default: return false;
}
// Now process the resulting unit to see what it means....
switch (TLBCacheUnit) {
case 0x00: break;
case 0x01: STORE_TLBCACHE_INFO (TLBCode, 4); break;
case 0x02: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
case 0x03: STORE_TLBCACHE_INFO (TLBData, 4); break;
case 0x04: STORE_TLBCACHE_INFO (TLBData, 4096); break;
case 0x06: STORE_TLBCACHE_INFO (L1Code, 8); break;
case 0x08: STORE_TLBCACHE_INFO (L1Code, 16); break;
case 0x0a: STORE_TLBCACHE_INFO (L1Data, 8); break;
case 0x0c: STORE_TLBCACHE_INFO (L1Data, 16); break;
case 0x10: STORE_TLBCACHE_INFO (L1Data, 16); break; // <-- FIXME: IA-64 Only
case 0x15: STORE_TLBCACHE_INFO (L1Code, 16); break; // <-- FIXME: IA-64 Only
case 0x1a: STORE_TLBCACHE_INFO (L2Unified, 96); break; // <-- FIXME: IA-64 Only
case 0x22: STORE_TLBCACHE_INFO (L3Unified, 512); break;
case 0x23: STORE_TLBCACHE_INFO (L3Unified, 1024); break;
case 0x25: STORE_TLBCACHE_INFO (L3Unified, 2048); break;
case 0x29: STORE_TLBCACHE_INFO (L3Unified, 4096); break;
case 0x39: STORE_TLBCACHE_INFO (L2Unified, 128); break;
case 0x3c: STORE_TLBCACHE_INFO (L2Unified, 256); break;
case 0x40: STORE_TLBCACHE_INFO (L2Unified, 0); break; // <-- FIXME: No integrated L2 cache (P6 core) or L3 cache (P4 core).
case 0x41: STORE_TLBCACHE_INFO (L2Unified, 128); break;
case 0x42: STORE_TLBCACHE_INFO (L2Unified, 256); break;
case 0x43: STORE_TLBCACHE_INFO (L2Unified, 512); break;
case 0x44: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
case 0x45: STORE_TLBCACHE_INFO (L2Unified, 2048); break;
case 0x50: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
case 0x51: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
case 0x52: STORE_TLBCACHE_INFO (TLBCode, 4096); break;
case 0x5b: STORE_TLBCACHE_INFO (TLBData, 4096); break;
case 0x5c: STORE_TLBCACHE_INFO (TLBData, 4096); break;
case 0x5d: STORE_TLBCACHE_INFO (TLBData, 4096); break;
case 0x66: STORE_TLBCACHE_INFO (L1Data, 8); break;
case 0x67: STORE_TLBCACHE_INFO (L1Data, 16); break;
case 0x68: STORE_TLBCACHE_INFO (L1Data, 32); break;
case 0x70: STORE_TLBCACHE_INFO (L1Trace, 12); break;
case 0x71: STORE_TLBCACHE_INFO (L1Trace, 16); break;
case 0x72: STORE_TLBCACHE_INFO (L1Trace, 32); break;
case 0x77: STORE_TLBCACHE_INFO (L1Code, 16); break; // <-- FIXME: IA-64 Only
case 0x79: STORE_TLBCACHE_INFO (L2Unified, 128); break;
case 0x7a: STORE_TLBCACHE_INFO (L2Unified, 256); break;
case 0x7b: STORE_TLBCACHE_INFO (L2Unified, 512); break;
case 0x7c: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
case 0x7e: STORE_TLBCACHE_INFO (L2Unified, 256); break;
case 0x81: STORE_TLBCACHE_INFO (L2Unified, 128); break;
case 0x82: STORE_TLBCACHE_INFO (L2Unified, 256); break;
case 0x83: STORE_TLBCACHE_INFO (L2Unified, 512); break;
case 0x84: STORE_TLBCACHE_INFO (L2Unified, 1024); break;
case 0x85: STORE_TLBCACHE_INFO (L2Unified, 2048); break;
case 0x88: STORE_TLBCACHE_INFO (L3Unified, 2048); break; // <-- FIXME: IA-64 Only
case 0x89: STORE_TLBCACHE_INFO (L3Unified, 4096); break; // <-- FIXME: IA-64 Only
case 0x8a: STORE_TLBCACHE_INFO (L3Unified, 8192); break; // <-- FIXME: IA-64 Only
case 0x8d: STORE_TLBCACHE_INFO (L3Unified, 3096); break; // <-- FIXME: IA-64 Only
case 0x90: STORE_TLBCACHE_INFO (TLBCode, 262144); break; // <-- FIXME: IA-64 Only
case 0x96: STORE_TLBCACHE_INFO (TLBCode, 262144); break; // <-- FIXME: IA-64 Only
case 0x9b: STORE_TLBCACHE_INFO (TLBCode, 262144); break; // <-- FIXME: IA-64 Only
// Default case - an error has occured.
default: return false;
}
}
// Increment the TLB pass counter.
TLBPassCounter ++;
} while ((TLBCacheData[0] & 0x000000FF) > TLBPassCounter);
// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
if ((L1Code == -1) && (L1Data == -1) && (L1Trace == -1)) cpu.Features.L1CacheSize = -1;
else if ((L1Code == -1) && (L1Data == -1) && (L1Trace != -1)) cpu.Features.L1CacheSize = L1Trace;
else if ((L1Code != -1) && (L1Data == -1)) cpu.Features.L1CacheSize = L1Code;
else if ((L1Code == -1) && (L1Data != -1)) cpu.Features.L1CacheSize = L1Data;
else if ((L1Code != -1) && (L1Data != -1)) cpu.Features.L1CacheSize = L1Code + L1Data;
else cpu.Features.L1CacheSize = -1;
// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
if (L2Unified == -1) cpu.Features.L2CacheSize = -1;
else cpu.Features.L2CacheSize = L2Unified;
// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
if (L3Unified == -1) cpu.Features.L3CacheSize = -1;
else cpu.Features.L3CacheSize = L3Unified;
}
return true;
}
bool getCPUPowerManagement( pay::CSysCPUInfo::CPUINFO &cpu ) {
int CPUPowerManagement = 0;
// Check to see if what we are about to do is supported...
if (!RetrieveCPUExtendedLevelSupport (0x80000007, cpu)) {
cpu.Features.ExtendedFeatures.PowerManagement.HasFrequencyID = false;
cpu.Features.ExtendedFeatures.PowerManagement.HasVoltageID = false;
cpu.Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = false;
return false;
}
// Use assembly to detect CPUID information...
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser doesn't know about <<CPUID>>, and so doesn't expect
; these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
; eax = 0x80000007 --> edx: get processor power management
mov eax,0x80000007
CPUID_INSTRUCTION
mov CPUPowerManagement, edx
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
}
// A generic catch-all just to be sure...
__except (1) {
return false;
}
// Check for the power management capabilities of the CPU.
cpu.Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = ((CPUPowerManagement & 0x00000001) != 0);
cpu.Features.ExtendedFeatures.PowerManagement.HasFrequencyID = ((CPUPowerManagement & 0x00000002) != 0);
cpu.Features.ExtendedFeatures.PowerManagement.HasVoltageID = ((CPUPowerManagement & 0x00000004) != 0);
return true;
}
DWORD pay::CSysCPUInfo::getLogicalProcessorsPerPhysical () {
// Return the logical processors per physical.
if ( !m_bChecked )
m_bChecked = getCPUInfo(m_cpuinfo);
return m_cpuinfo.Features.ExtendedFeatures.LogicalProcessorsPerPhysical;
}
DWORD pay::CSysCPUInfo::getProcessorFeatures() {
int CPUFeatures = 0;
int CPUAdvanced = 0;
DWORD dwFeature = 0;
// Use assembly to detect CPUID information...
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
// we must push/pop the registers <<CPUID>> writes to, as the
// optimiser doesn't know about <<CPUID>>, and so doesn't expect
// these registers to change.
push eax
push ebx
push ecx
push edx
#endif
// <<CPUID>>
// eax = 1 --> eax: CPU ID - bits 31..16 - unused,
// bits 15..12 - type,
// bits 11..8 - family,
// bits 7..4 - model,
// bits 3..0 - mask revision
// ebx: 31..24 - default APIC ID,
// 23..16 - logical processsor ID,
// 15..8 - CFLUSH chunk size
// 7..0 - brand ID
// edx: CPU feature flags
mov eax,1
CPUID_INSTRUCTION
mov CPUAdvanced, ebx
mov CPUFeatures, edx
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
} __except (1) {
// A generic catch-all just to be sure...
return dwFeature;
}
dwFeature = I16TO32(CPUAdvanced,CPUFeatures);
return dwFeature;
}
DWORD pay::CSysCPUInfo::getProcessorStepping() {
return getProcessorRevision();
}
DWORD pay::CSysCPUInfo::getProcessorExtendedFamily() {
if ( m_bChecked )
return m_cpuinfo.dwExtendedFamily;
int CPUSignature = getProcessorSignature();
return ((CPUSignature & 0x0FF00000) >> 20);
}
DWORD pay::CSysCPUInfo::getProcessorExtendedModel() {
if ( m_bChecked )
return m_cpuinfo.dwExtendedModel;
int CPUSignature = getProcessorSignature();
return ((CPUSignature & 0x000F0000) >> 16);
}
DWORD pay::CSysCPUInfo::getProcessorRevision() {
if ( m_bChecked )
return m_cpuinfo.dwRevision;
int CPUSignature = getProcessorSignature();
return ((CPUSignature & 0x0000000F) >> 0);
}
DWORD pay::CSysCPUInfo::getProcessorType() {
if ( m_bChecked )
return m_cpuinfo.dwType;
int CPUSignature = getProcessorSignature();
return ((CPUSignature & 0x0000F000) >> 12); // Bits 15..12 Used
}
DWORD pay::CSysCPUInfo::getProcessorFamily() {
// Return the family of the CPU present.
if ( m_bChecked )
return m_cpuinfo.dwFamily;
int CPUSignature = getProcessorSignature();
return ((CPUSignature & 0x00000F00) >> 8); // Bits 11..8 Used
}
DWORD pay::CSysCPUInfo::getProcessorModel() {
// Return the model of CPU present.
if ( m_bChecked )
return m_cpuinfo.dwModel;
int CPUSignature = getProcessorSignature();
return ((CPUSignature & 0x000000F0) >> 4); // Bits 7..4 Used
}
unsigned __stdcall _getProcessorSerialNumber(void *ipSerialNumber) {
// Use assembly to detect CPUID information...
int SerialNumber[3];
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser doesn't know about <<CPUID>>, and so doesn't expect
; these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
; eax = 3 --> ebx: top 32 bits are the processor signature bits --> NB: Transmeta only ?!?
; ecx: middle 32 bits are the processor signature bits
; edx: bottom 32 bits are the processor signature bits
mov eax, 3
CPUID_INSTRUCTION
mov SerialNumber[0 * TYPE int], ebx
mov SerialNumber[1 * TYPE int], ecx
mov SerialNumber[2 * TYPE int], edx
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
} __except (1) {
// A generic catch-all just to be sure...
SerialNumber[0] = 0;
SerialNumber[1] = 0;
SerialNumber[2] = 0;
}
memcpy(ipSerialNumber,SerialNumber,sizeof(SerialNumber));
return 0;
}
string pay::CSysCPUInfo::getProcessorSerialNumber(DWORD dwNum) {
string sRes;
if ( m_bChecked ) {
if (m_cpuinfo.Features.HasSerial)
sRes = m_cpuinfo.idCPU[dwNum].szSerialNumber;
} else {
DWORD dwCPUFeatures = getProcessorFeatures();
// Retrieve the features of CPU present.
BOOL HasSerial = ((dwCPUFeatures & 0x00040000) != 0); // Serial Present --> Bit 18
if ( HasSerial ) {
// Check to see if the processor supports the processor serial number.
int SerialNumber[3];
HANDLE hThread;
// Create the thread.
hThread = (HANDLE)::_beginthreadex( NULL, 0, &_getProcessorSerialNumber, NULL, CREATE_SUSPENDED, (unsigned *)SerialNumber );
// Wait until second thread has terminated. If you comment out the line below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to 1000000 yet.
BOOL isNT;
isNT = ( ( m_SysWindowsImpl && m_SysWindowsImpl->m_isWinNT ) || pay::CSysOSInfo::isNTPlatform() );
DWORD dwThreadAffinityMask = 1;
if ( isNT )
dwThreadAffinityMask <<= dwNum;
if ( !::SetThreadAffinityMask(hThread,dwThreadAffinityMask) ) {
::ResumeThread(hThread);
::WaitForSingleObject( hThread, INFINITE );
}
// Destroy the thread object.
CloseHandle( hThread );
if ( ( SerialNumber[0] != 0 ) || ( SerialNumber[1] != 0 ) || ( SerialNumber[2] != 0 ) ) {
TCHAR szRes[30];
// Process the returned information.
sprintf (szRes, "%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x",
((SerialNumber[0] & 0xff000000) >> 24),
((SerialNumber[0] & 0x00ff0000) >> 16),
((SerialNumber[0] & 0x0000ff00) >> 8),
((SerialNumber[0] & 0x000000ff) >> 0),
((SerialNumber[1] & 0xff000000) >> 24),
((SerialNumber[1] & 0x00ff0000) >> 16),
((SerialNumber[1] & 0x0000ff00) >> 8),
((SerialNumber[1] & 0x000000ff) >> 0),
((SerialNumber[2] & 0xff000000) >> 24),
((SerialNumber[2] & 0x00ff0000) >> 16),
((SerialNumber[2] & 0x0000ff00) >> 8),
((SerialNumber[2] & 0x000000ff) >> 0));
sRes = szRes;
}
}
}
return sRes;
}
_int64 __cdecl getCyclesDifference (DELAY_FUNC DelayFunction, unsigned int uiParameter) {
unsigned int edx1, eax1;
unsigned int edx2, eax2;
// Calculate the frequency of the CPU instructions.
__try {
_asm {
push uiParameter ; push parameter param
mov ebx, DelayFunction ; store func in ebx
RDTSC_INSTRUCTION
mov esi, eax ; esi = eax
mov edi, edx ; edi = edx
call ebx ; call the delay functions
RDTSC_INSTRUCTION
pop ebx
mov edx2, edx ; edx2 = edx
mov eax2, eax ; eax2 = eax
mov edx1, edi ; edx2 = edi
mov eax1, esi ; eax2 = esi
}
}
// A generic catch-all just to be sure...
__except (1) {
return -1;
}
return (I32TO64 (edx2, eax2) - I32TO64 (edx1, eax1));
}
void DelayNoOverhead (unsigned int uiMS)
{
LARGE_INTEGER Frequency, StartCounter, EndCounter;
__int64 x;
// Get the frequency of the high performance counter.
if (!QueryPerformanceFrequency (&Frequency)) return;
x = Frequency.QuadPart / 1000 * uiMS;
// Get the starting position of the counter.
::QueryPerformanceCounter (&StartCounter);
do {
// Get the ending position of the counter.
::QueryPerformanceCounter (&EndCounter);
} while (EndCounter.QuadPart - StartCounter.QuadPart < x);
}
void DelayOverhead (unsigned int uiMS) {
LARGE_INTEGER Frequency, StartCounter, EndCounter;
__int64 x;
// Get the frequency of the high performance counter.
if (!QueryPerformanceFrequency (&Frequency)) return;
x = Frequency.QuadPart / 1000 * uiMS;
// Get the starting position of the counter.
::QueryPerformanceCounter (&StartCounter);
do {
// Get the ending position of the counter.
QueryPerformanceCounter (&EndCounter);
} while (EndCounter.QuadPart - StartCounter.QuadPart == x);
}
BOOL pay::CSysCPUInfo::checkCPUID () {
int CPUIDPresent = 0;
#ifdef _WIN32
// Use SEH to determine CPUID presence
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the
; optimiser doesn't know about <<CPUID>>, and so doesn't expect
; these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
mov eax, 0
CPUID_INSTRUCTION
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
}
// A generic catch-all just to be sure...
__except (1) {
// Stop the class from trying to use CPUID again!
CPUIDPresent = FALSE;
return FALSE;
}
#else
// The "right" way, which doesn't work under certain Windows versions
__try {
_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 cpuid_present ; if so, mark
mov eax, -1 ; CPUID not present - disable its usage
jmp no_features
cpuid_present:
mov eax, 0 ; CPUID capable CPU - enable its usage.
no_features:
mov CPUIDPresent, eax ; Save the value in eax to a variable.
}
}
// A generic catch-all just to be sure...
__except (1) {
// Stop the class from trying to use CPUID again!
CPUIDPresent = FALSE;
return FALSE;
}
#endif
// Return true to indicate support or false to indicate lack.
return (CPUIDPresent == 0) ? TRUE : FALSE;
}
DWORD pay::CSysCPUInfo::getProcessorSpeed() {
if (m_bChecked)
return m_cpuinfo.dwMhz;
HKEY hKey;
// Get the processor speed info.
DWORD data = 0;
BOOL isNT;
isNT = ( ( m_SysWindowsImpl && m_SysWindowsImpl->m_isWinNT ) || pay::CSysOSInfo::isNTPlatform() );
if ( isNT ) {
if ( !RegOpenKeyEx (HKEY_LOCAL_MACHINE,"Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey) ) {
DWORD dataSize = sizeof(DWORD);
::RegQueryValueEx (hKey, _T("~MHz"), NULL, NULL,(LPBYTE)&data, &dataSize);
// Make sure to close the reg key
RegCloseKey (hKey);
}
} else {
unsigned int uiRepetitions = SYSCPUSPEED_REPEAT;
unsigned int uiMSecPerRepetition = 50;
__int64 i64Total = 0, i64Overhead = 0;
for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++) {
i64Total += getCyclesDifference (DelayNoOverhead, uiMSecPerRepetition);
i64Overhead += getCyclesDifference (DelayOverhead, uiMSecPerRepetition);
}
// Calculate the MHz speed.
i64Total -= i64Overhead;
i64Total /= uiRepetitions;
i64Total /= uiMSecPerRepetition;
i64Total /= 1000;
// Save the CPU speed.
data = (DWORD) i64Total;
}
DWORD NF[] = {0, 20, 33, 50, 60, 66, 80, 90, 100};
DWORD Freq, RF, Hi, Lo;
RF = 0;
DWORD dwData;
Freq = data % 100;
for (int i = 0; i < 8; i++ ) {
if ( Freq < NF[i] ) {
Hi = i;
Lo = i-1;
if ( ( NF[Hi] - Freq ) > ( Freq - NF[Lo] ) )
RF = NF[Lo]-Freq;
else
RF = NF[Hi]-Freq;
break;
}
}
dwData = data+RF;
return data;
}
DWORD pay::CSysCPUInfo::getNumProcessors() {
SYSTEM_INFO siSysInfo;
// Get the hardware information
// Copy the hardware information to the SYSTEM_INFO structure.
if ( !m_bChecked ) {
::GetSystemInfo(&siSysInfo);
return siSysInfo.dwNumberOfProcessors;
}
return m_cpuinfo.dwNumProcessors;
}
DWORD pay::CSysCPUInfo::getProcessorPageSize() {
if ( !m_bChecked ) {
SYSTEM_INFO siSysInfo;
::GetSystemInfo(&siSysInfo);
return siSysInfo.dwPageSize;
}
return m_cpuinfo.dwPageSize;
}
BOOL _getProcessorVendor( TCHAR *szVendorName ) {
int CPUVendor[3];
// Use assembly to detect CPUID information...
__try {
_asm {
#ifdef CPUID_AWARE_COMPILER
; we must push/pop the registers <<CPUID>> writes to, as the optimiser doesn't know about <<CPUID>>,
; and so doesn't expect these registers to change.
push eax
push ebx
push ecx
push edx
#endif
; <<CPUID>>
; eax = 0 --> eax: maximum value of CPUID instruction.
; ebx: part 1 of 3; CPU signature.
; edx: part 2 of 3; CPU signature.
; ecx: part 3 of 3; CPU signature.
mov eax, 0
CPUID_INSTRUCTION
mov CPUVendor[0 * TYPE int], ebx
mov CPUVendor[1 * TYPE int], edx
mov CPUVendor[2 * TYPE int], ecx
#ifdef CPUID_AWARE_COMPILER
pop edx
pop ecx
pop ebx
pop eax
#endif
}
}
// A generic catch-all just to be sure...
__except (1) {
return FALSE;
}
// Process the returned information.
memcpy ( szVendorName, &(CPUVendor[0]), sizeof (int));
memcpy (&(szVendorName[4]), &(CPUVendor[1]), sizeof (int));
memcpy (&(szVendorName[8]), &(CPUVendor[2]), sizeof (int));
szVendorName[12] = '\0';
return true;
}
string pay::CSysCPUInfo::getProcessorVendor() {
string sRes;
if ( m_bChecked ) {
sRes = m_cpuinfo.szVendorName;
} else {
TCHAR szVendorName[15];
::memset(szVendorName,0,sizeof(szVendorName));
BOOL isNT;
isNT = ( ( m_SysWindowsImpl && m_SysWindowsImpl->m_isWinNT ) || pay::CSysOSInfo::isNTPlatform() );
if ( isNT ) {
// get the info from the registry
HKEY hKey;
if ( !RegOpenKeyEx (HKEY_LOCAL_MACHINE,"Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey) ) {
DWORD dataSize = 15;
RegQueryValueEx (hKey, _T("VendorIdentifier"), NULL, NULL,(LPBYTE)szVendorName, &dataSize);
// sRes = szVendorName;
// Make sure to close the reg key
RegCloseKey (hKey);
}
} else {
_getProcessorVendor(szVendorName);
}
sRes = szVendorName;
}
return sRes;
}
bool _getProcessorIdentifier(TCHAR *szCPUName) {
bool bRes = true;
TCHAR CPUName[47];
__try {
__asm {
PUSH EAX
PUSH EBP
PUSH EBX
PUSH ECX
PUSH EDI
PUSH EDX
PUSH ESI
MOV EAX, 0x80000002
CPUID_INSTRUCTION
MOV DWORD PTR [CPUName], EAX
MOV DWORD PTR [CPUName + 4], EBX
MOV DWORD PTR [CPUName + 8], ECX
MOV DWORD PTR [CPUName + 12], EDX
MOV EAX, 0x80000003
CPUID_INSTRUCTION
MOV DWORD PTR [CPUName + 16], EAX
MOV DWORD PTR [CPUName + 20], EBX
MOV DWORD PTR [CPUName + 24], ECX
MOV DWORD PTR [CPUName + 28], EDX
MOV EAX, 0x80000004
CPUID_INSTRUCTION
MOV DWORD PTR [CPUName + 32], EAX
MOV DWORD PTR [CPUName + 36], EBX
MOV DWORD PTR [CPUName + 40], ECX
MOV DWORD PTR [CPUName + 44], EDX
POP ESI
POP EDX
POP EDI
POP ECX
POP EBX
POP EBP
POP EAX
}
memcpy(szCPUName,CPUName,sizeof(CPUName));
} __except ( 1 ) {
bRes = false;
}
return bRes;
}
string pay::CSysCPUInfo::getProcessorIdentifier() {
string sRes;
TCHAR vendorData[47];
DWORD dataSize = 47;
BOOL isNT;
isNT = ( ( m_SysWindowsImpl && m_SysWindowsImpl->m_isWinNT ) || pay::CSysOSInfo::isNTPlatform() );
if ( isNT ) {
// get the info from the registry
HKEY hKey;
if ( !RegOpenKeyEx (HKEY_LOCAL_MACHINE,"Hardware\\Description\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey) ) {
if ( !::RegQueryValueEx (hKey, _T("Identifier"), NULL, NULL,(LPBYTE)vendorData, &dataSize) )
sRes = vendorData;
// Make sure to close the reg key
RegCloseKey (hKey);
}
} else {
TCHAR CPUName[47];
bool bRes = _getProcessorIdentifier(CPUName);
if (bRes) {
sRes = CPUName;
} else {
sprintf( vendorData,"%s Family %d Model %d Stepping %d",getProcessorVendor().c_str(),getProcessorFamily(),getProcessorModel(),getProcessorRevision());
sRes = vendorData;
}
}
return sRes;
}
DWORD pay::CSysCPUInfo::getProcessorUsage( DWORD dwProcNum ) {
DWORD dwRes = 0;
BOOL isNT;
isNT = ( ( m_SysWindowsImpl && m_SysWindowsImpl->m_isWinNT ) || pay::CSysOSInfo::isNTPlatform() );
if ( !isNT ) {
HKEY hKey;
DWORD dwBuff;
if ( !RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT("PerfStats\\StartStat"), 0, KEY_QUERY_VALUE, &hKey) ) {
DWORD dataSize = sizeof(dwBuff);
DWORD dataType = sizeof(dwBuff);
if ( !::RegQueryValueEx (hKey, TEXT("KERNEL\\CPUUsage"), NULL, &dataType, (LPBYTE)&dwBuff, &dataSize) ) {
if ( dataType == REG_DWORD )
dwRes = dwBuff;
}
// Make sure to close the reg key
RegCloseKey (hKey);
}
} else {
SYSTEM_PROCESSOR_TIMES *CPUNTUsage;
HMODULE NTDLL_DLL;
NTSTATUS (__cdecl *ZwQuerySystemInformation)( UINT SystemInformationClass,
PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ) = NULL;
NTDLL_DLL = GetModuleHandle(_T("NTDLL.DLL"));
if ( NTDLL_DLL != 0 ) {
(FARPROC&)ZwQuerySystemInformation = ::GetProcAddress(NTDLL_DLL,"ZwQuerySystemInformation");
ULONG size = sizeof(SYSTEM_PROCESSOR_TIMES)*getNumProcessors();
CPUNTUsage = (SYSTEM_PROCESSOR_TIMES *)malloc(size);
if (CPUNTUsage) {
ZwQuerySystemInformation(8,CPUNTUsage,size,NULL);
LARGE_INTEGER numer1,numer2;
numer1 = (LARGE_INTEGER)((
(pt->DpcTime -oldtime->DpcTime.QuadPart) +
(pt->IdleTime.QuadPart - oldtime->IdleTime.QuadPart) +
(pt->InterruptTime.QuadPart - oldtime->InterruptTime.QuadPart) +
(pt->KernelTime.QuadPart - oldtime->KernelTime.QuadPart) +
(pt->UserTime.QuadPart - oldtime->UserTime.QuadPart))/1000);
Sleep(1000);
ZwQuerySystemInformation(8,CPUNTUsage,size,NULL);
numer2 = (LONGLONG)((
(pt->DpcTime.QuadPart - oldtime->DpcTime.QuadPart) +
(pt->InterruptTime.QuadPart - oldtime->InterruptTime.QuadPart) +
(pt->KernelTime.QuadPart - oldtime->KernelTime.QuadPart) +
(pt->UserTime.QuadPart - oldtime->UserTime.QuadPart))/1000);
dwRes = CPUNTUsage[dwProcNum].DpcTime;
dwRes = (DWORD)(deno*100/numer);
free(CPUNTUsage);
dwRes =
}
}
}
return dwRes;
}
string pay::CSysCPUInfo::getProcessorManufacturer( enumProcessorManufacturer ChipManufacturer) {
// DWORD dwChipManufacturer = m_cpuinfo.dwChipManufacturer;
string sRes = ssCPUVendors[((ChipManufacturer>9)?0:ChipManufacturer)];
return sRes;
}
bool checkSSEFP(){
// Attempt to __try some SSE FP instructions.
__try {
// Perform: orps xmm0, xmm0
_asm {
_emit 0x0f
_emit 0x56
_emit 0xc0
}
} __except (1) {
// A generic catch-all just to be sure...
// bad instruction - processor or OS cannot handle SSE FP.
return false;
}
// SSE FP capable processor.
return true;
}
string getCPUIdentity( pay::CSysCPUInfo::CPUINFO &cpu ) {
string sRes;
// Start by decided which manufacturer we are using....
switch (cpu.dwChipManufacturer) {
case pay::CSysCPUInfo::Intel:
// Check the family / model / revision to determine the CPU ID.
switch (cpu.dwFamily) {
case 3:
sRes = _T("Newer i80386 family");
break;
case 4:
switch (cpu.dwModel) {
case 0: sRes = _T("i80486DX-25/33"); break;
case 1: sRes = _T("i80486DX-50"); break;
case 2: sRes = _T("i80486SX"); break;
case 3: sRes = _T ("i80486DX2"); break;
case 4: sRes = _T ("i80486SL"); break;
case 5: sRes = _T ("i80486SX2"); break;
case 7: sRes = _T ("i80486DX2 WriteBack"); break;
case 8: sRes = _T ("i80486DX4"); break;
case 9: sRes = _T ("i80486DX4 WriteBack"); break;
default: sRes = _T ("Unknown 80486 family"); return false;
}
break;
case 5:
switch (cpu.dwModel) {
case 0: sRes = _T ("Pentium P5 A-Step (0,80µm)"); break;
case 1: sRes = _T ("Pentium P5 (0,50µm)"); break;
case 2: sRes = _T ("Pentium P54C (0,50µm)"); break;
case 3: sRes = _T ("Pentium P24T OverDrive"); break;
case 4: sRes = _T ("Pentium MMX P55C (0,28µm)"); break;
case 5: sRes = _T ("DX4"); break;
case 6: sRes = _T ("Pentium P5"); break;
case 7: sRes = _T ("Pentium P54C (0,35µm)"); break;
case 8: sRes = _T ("Pentium MMX (mobile) P55C Tillamook (0.25µm)"); break;
default: sRes = _T ("Unknown Pentium® family"); return false;
}
break;
case 6:
switch (cpu.dwModel) {
case 0: sRes = _T ("Pentium Pro P6 A-Step (0.50 µm)"); break;
case 1: sRes = _T ("Pentium Pro P6 (0.35 µm)"); break;
case 3:
if ( cpu.Features.L2CacheSize == 333 )
sRes = _T ("Pentium® II P6T (0.25 µm)");
else
sRes = _T ("Pentium® II Klamath (0.35 µm)");
if (cpu.dwType == 1)
sRes.append(" OverDrive");
break;
case 4: sRes = _T ("Pentium® II P55CT (P54 OverDrive)"); break;
case 5:
if ( cpu.Features.L2CacheSize <= 512 )
if ( cpu.Features.L2CacheSize == 0 )
sRes = _T ("Celeron Covington (0,25µm)");
else
sRes = _T ("Pentium® II Deschutes (0.25 µm)");
else
sRes = _T ("Pentium® II Xeon Deschutes (0.25 µm)");
break;
case 6:
if ( cpu.Features.L2CacheSize < 256 )
sRes = _T ("Celeron A Mendocino (0.25 µm)");
else
sRes = _T ("Pentium® II PE (mobile) Dixon (0.25 µm)");
break;
case 7:
if ( cpu.Features.L2CacheSize <= 512 )
sRes = _T ("Pentium® III Katmai (0.25 µm)");
else
sRes = _T ("Pentium® III Tanner (0.25 µm)");
break;
case 8: sRes = _T ("Pentium® III Coppermine (0.18 µm) With 256 KB On-Die L2 Cache "); break;
case 0xa: sRes = _T ("Pentium® III (0.18 µm) With 1 Or 2 MB On-Die L2 Cache "); break;
case 0xb: sRes = _T ("Pentium® III (0.13 µm) With 256 Or 512 KB On-Die L2 Cache "); break;
default: sRes = _T ("Unknown P6 family"); return false;
}
break;
case 7:
case 8: {
DWORD dwBrand;
dwBrand = (cpu.dwCPUFeatures >> 16 ) & 0x00FF;
switch (dwBrand) {
case 1: sRes = _T ("Celeron"); break;
case 3: sRes = _T ("Pentium® II Xeon"); break;
case 4: sRes = _T ("Pentium® IV"); break;
default:
if ( cpu.Features.L2CacheSize <= 1024 )
sRes = _T ("Pentium® III");
else
sRes = _T ("Pentium® III Xeon");
break;
}
// sRes = _T ("Intel Merced (IA-64)");
}
break;
case 0xa:
sRes = _T ("Pentium® II Xeon");
break;
case 0xf:
// Check the extended family bits...
switch (cpu.dwExtendedFamily) {
case 0:
switch (cpu.dwModel) {
case 0: sRes = _T ("Pentium® IV (0.18 µm)"); break;
case 1: sRes = _T ("Pentium® IV (0.18 µm)"); break;
case 2: sRes = _T ("Pentium® IV (0.13 µm)"); break;
default: sRes = _T ("Unknown Pentium 4 family"); return false;
}
break;
case 1:
sRes = _T ("Intel McKinley (IA-64)");
break;
}
break;
default:
sRes = _T ("Unknown Intel family");
return false;
}
break;
case pay::CSysCPUInfo::AMD:
// Check the family / model / revision to determine the CPU ID.
switch (cpu.dwFamily) {
case 4:
switch (cpu.dwModel) {
case 0: sRes = _T ("Am486DX P4"); break;
case 3: sRes = _T ("80486DX2 P24"); break;
case 7: sRes = _T ("80486DX2 P24 WriteBack"); break;
case 8: sRes = _T ("80486DX4 P24C"); break;
case 9: sRes = _T ("80486DX4 P24C WriteBack"); break;
case 0xe: sRes = _T ("Am5x86 X5"); break;
case 0xf: sRes = _T ("Am5x86WB X5"); break;
default: sRes = _T ("Unknown 80486 family"); return false;
}
break;
case 5:
switch (cpu.dwModel) {
case 0: sRes = _T ("K5 SSA5 (PR75, PR90, PR100) (0.50-0.35 µm)"); break;
case 1: sRes = _T ("K5-5k86 (PR120, PR133) (0.35 µm)"); break;
case 2: sRes = _T ("5k86 (PR166)"); break;
case 3: sRes = _T ("5k86 (PR200)"); break;
case 6: sRes = _T ("K6 (0.30 µm)"); break;
case 7: sRes = _T ("K6 Little Foot (0.25 µm)"); break;
case 8: sRes = _T ("K6-II Chomper (0.25 µm)"); break;
case 9: sRes = _T ("K6-III Slarptooth (0.25 µm)"); break;
case 0xd: sRes = _T ("K6-2+ or K6-III+ (0.18 µm)"); break;
default: sRes = _T ("Unknown 80586 family"); return false;
}
break;
case 6:
switch (cpu.dwModel) {
case 1: sRes = _T ("Athlon™ (0.25 µm)"); break;
case 2: sRes = _T ("Athlon™ (0.18 µm)"); break;
case 3: sRes = _T ("Duron™ (SF core)"); break;
case 4: sRes = _T ("Athlon™ (Thunderbird core)"); break;
case 6: sRes = _T ("Athlon™ (Palomino core)"); break;
case 7: sRes = _T ("Duron™ (Morgan core)"); break;
case 8:
if (cpu.Features.ExtendedFeatures.SupportsMP)
sRes = _T ("Athlon™ MP (Thoroughbred core)");
else
sRes = _T ("Athlon™ XP (Thoroughbred core)");
break;
default: sRes = _T ("Unknown K7 family");
return false;
}
break;
default:
sRes = _T ("Unknown AMD family");
return false;
}
break;
case pay::CSysCPUInfo::Transmeta:
switch (cpu.dwFamily) {
case 5:
switch (cpu.dwModel) {
case 4: sRes = _T ("Crusoe TM3x00 and TM5x00");
break;
default: sRes = _T ("Unknown Crusoe family");
return false;
}
break;
default:
sRes = _T ("Unknown Transmeta family");
return false;
}
break;
case pay::CSysCPUInfo::Rise:
switch (cpu.dwFamily) {
case 5:
switch (cpu.dwModel) {
case 0: sRes = _T ("mP6 (0.25 µm)"); break;
case 2: sRes = _T ("mP6 (0.18 µm)"); break;
default: sRes = _T ("Unknown Rise family"); return false;
}
break;
default:
sRes = _T ("Unknown Rise family");
return false;
}
break;
case pay::CSysCPUInfo::UMC:
switch (cpu.dwFamily) {
case 4:
switch (cpu.dwModel) {
case 1: sRes = _T ("U5D"); break;
case 2: sRes = _T ("U5S"); break;
case 3: sRes = _T ("U486DX2"); break;
case 4: sRes = _T ("U486SX2"); break;
default: sRes = _T ("Unknown UMC family"); return false;
}
break;
default:
sRes = _T ("Unknown UMC family");
return false;
}
break;
case pay::CSysCPUInfo::IDT:
switch (cpu.dwFamily) {
case 5:
switch (cpu.dwModel) {
case 4: sRes = _T ("WinChip C6 (0.35 µm)"); break;
case 8: sRes = _T ("WinChip C2 2x W2x (0.35-0.25 µm)"); break;
case 9: sRes = _T ("WinChip C3 W3 (0.25 µm)"); break;
default: sRes = _T ("Unknown IDT\\Centaur family"); return false;
}
break;
case 6:
switch (cpu.dwModel) {
case 6: sRes = _T ("VIA Cyrix III - Samuel"); break;
default: sRes = _T ("Unknown IDT\\Centaur family"); return false;
}
break;
default:
sRes = _T ("Unknown IDT\\Centaur family");
return false;
}
break;
case pay::CSysCPUInfo::Cyrix:
switch (cpu.dwFamily) {
case 4:
switch (cpu.dwModel) {
case 0: sRes = _T ("Cx486SLC/DLC or Cx486S or Cx486DX/DX2/DX4"); break;
case 4: sRes = _T ("MediaGX GX, GXm"); break;
case 9: sRes = _T ("5x86"); break;
default: sRes = _T ("Unknown Cx5x86 family"); return false;
}
break;
case 5:
switch (cpu.dwModel) {
case 2: sRes = _T ("Cx6x86 M1 (0.65 µm) or M1L (0.35 µm)"); break;
case 4: sRes = _T ("MediaGX GXm"); break;
default: sRes = _T ("Unknown Cx6x86 family"); return false;
}
break;
case 6:
switch (cpu.dwModel) {
case 0: sRes = _T ("6x86MX"); break;
case 5: sRes = _T ("Cyrix M2 Core"); break;
case 6: sRes = _T ("WinChip C5A Core"); break;
case 7: sRes = _T ("WinChip C5B\\C5C Core"); break;
case 8: sRes = _T ("WinChip C5C-T Core"); break;
default: sRes = _T ("Unknown 6x86MX\\Cyrix III family"); return false;
}
break;
default:
sRes = _T ("Unknown Cyrix family");
return false;
}
break;
case pay::CSysCPUInfo::NexGen:
switch (cpu.dwFamily) {
case 5:
switch (cpu.dwModel) {
case 0: sRes = _T ("Nx586 or Nx586FPU (0.50-0.44 µm)"); break;
case 6: sRes = _T ("Nx686 HA (0,50µm)"); break;
default: sRes = _T ("Unknown NexGen family"); return false;
}
break;
default:
sRes = _T ("Unknown NexGen family");
return false;
}
break;
case pay::CSysCPUInfo::NSC:
sRes = _T ("Cx486SLC \\ DLC \\ Cx486S A-Step");
break;
default:
// We cannot identify the processor.
sRes = _T ("Unknown family");
return false;
}
return sRes;
}
string pay::CSysCPUInfo::getSysInfoName() {
return string(SYSINFO_CPU_PATH);
}
pay::EnumSysInfo pay::CSysCPUInfo::getSysInfoNum() {
return pay::siCPU;
}
void pay::CSysCPUInfo::getInfo() {
if (!m_bChecked)
m_bChecked = getCPUInfo(m_cpuinfo);
}
void pay::CSysCPUInfo::getInfoAsXML(ISysXMLInfo &xmlInfo) {
if (!m_bChecked)
m_bChecked = getCPUInfo(m_cpuinfo);
// get SYSINFO_CPU_PATH
TiXmlElement *xmlCategory = xmlInfo.getCategory(SYSINFO_CPU_PATH);
if (m_cpuinfo.dwNumProcessors)
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_NUMPROC,m_cpuinfo.dwNumProcessors);
if (m_cpuinfo.dwMhz)
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_MHZ,m_cpuinfo.dwMhz);
if (m_cpuinfo.dwPageSize)
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_PAGESIZE,m_cpuinfo.dwPageSize);
if (m_cpuinfo.szProcessorName[0])
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_VENDOR,m_cpuinfo.szVendorName);
if (m_cpuinfo.szProcessorArchitecture[0])
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_ARCHITECTURE,m_cpuinfo.szProcessorArchitecture);
if (m_cpuinfo.szProcessorName[0])
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_PROCESSORNAME,m_cpuinfo.szProcessorName);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_CHIPMANUFACTURER,getProcessorManufacturer((enumProcessorManufacturer)m_cpuinfo.dwChipManufacturer).c_str());
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_TYPE,m_cpuinfo.dwType);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FAMILY,m_cpuinfo.dwFamily);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_REVISION,m_cpuinfo.dwRevision);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_MODEL,m_cpuinfo.dwModel);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_TYPE,m_cpuinfo.dwType);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_EXTENDEDFAMILY,m_cpuinfo.dwExtendedFamily);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_EXTENDEDMODEL,m_cpuinfo.dwExtendedModel);
xmlCategory = xmlInfo.getCategory(SYSINFO_CPU_FEATURES_PATH);
TCHAR *ssSupport[] = {"Not Supported","Supported"};
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_FPU,ssSupport[m_cpuinfo.Features.HasFPU]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_TSC,ssSupport[m_cpuinfo.Features.HasTSC]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_MMX,ssSupport[m_cpuinfo.Features.HasMMX]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SSE,ssSupport[m_cpuinfo.Features.HasSSE]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SSEFP,ssSupport[m_cpuinfo.Features.HasSSEFP]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SSE2,ssSupport[m_cpuinfo.Features.HasSSE2]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_IA64,ssSupport[m_cpuinfo.Features.HasIA64]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_APIC,ssSupport[m_cpuinfo.Features.HasAPIC]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_CMOV,ssSupport[m_cpuinfo.Features.HasCMOV]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_MTRR,ssSupport[m_cpuinfo.Features.HasMTRR]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_ACPI,ssSupport[m_cpuinfo.Features.HasACPI]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SERIAL,ssSupport[m_cpuinfo.Features.HasSerial]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_THERMAL,ssSupport[m_cpuinfo.Features.HasThermal]);
if (m_cpuinfo.Features.L1CacheSize != -1)
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_L1CACHESIZE,(DWORD)m_cpuinfo.Features.L1CacheSize);
if (m_cpuinfo.Features.L2CacheSize != -1)
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_L2CACHESIZE,(DWORD)m_cpuinfo.Features.L2CacheSize);
if (m_cpuinfo.Features.L3CacheSize != -1)
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_L3CACHESIZE,(DWORD)m_cpuinfo.Features.L3CacheSize);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_3DNOW,ssSupport[m_cpuinfo.Features.ExtendedFeatures.Has3DNow]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_3DNOW,ssSupport[m_cpuinfo.Features.ExtendedFeatures.Has3DNowPlus]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SUPPORTSMP,ssSupport[m_cpuinfo.Features.ExtendedFeatures.SupportsMP]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_MMXPLUS,ssSupport[m_cpuinfo.Features.ExtendedFeatures.HasMMXPlus]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SSEMMX,ssSupport[m_cpuinfo.Features.ExtendedFeatures.HasSSEMMX]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_SUPPORTSHYPERTHREADING,ssSupport[m_cpuinfo.Features.ExtendedFeatures.SupportsHyperthreading]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_LOGICALPROCESSORSPERPHYSICAL,(DWORD)m_cpuinfo.Features.ExtendedFeatures.LogicalProcessorsPerPhysical);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_VOLTAGEID,ssSupport[m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasVoltageID]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_FREQUENCYID,ssSupport[m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasFrequencyID]);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_FEATURES_TEMPSENSEDIODE,ssSupport[m_cpuinfo.Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode]);
xmlInfo.deleteCategory(SYSINFO_CPU_PROCESSORID_PATH);
DWORD i = 0;
// if (m_cpuinfo.Features.HasSerial)
for (vector<CPUID>::iterator it = m_cpuinfo.idCPU.begin(); it != m_cpuinfo.idCPU.end(); it++ ) {
xmlCategory = xmlInfo.getCategory(SYSINFO_CPU_PROCESSORID_PATH,true);
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_NUM,++i);
if ( (*it).dwProcessorUsage != -1 )
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_USAGE,(DWORD)((*it).dwProcessorUsage));
if ( (*it).szSerialNumber[0] )
xmlInfo.updateValue(xmlCategory,SYSINFO_CPU_ID,(*it).szSerialNumber);
}
}
BOOL pay::CSysCPUInfo::getCPUInfo( pay::CSysCPUInfo::CPUINFO &cpu ) {
if ( m_bChecked ) {
memcpy(&cpu,&m_cpuinfo,sizeof(pay::CSysCPUInfo::CPUINFO));
cpu.idCPU.clear();
for (vector<CPUID>::iterator it = m_cpuinfo.idCPU.begin(); it != m_cpuinfo.idCPU.end(); it++ )
cpu.idCPU.push_back(*it);
return TRUE;
}
// get processor vendor
strncpy(cpu.szVendorName,getProcessorVendor().c_str(),sizeof(cpu.szVendorName));
// Attempt to retrieve the manufacturer from the vendor string.
if (strcmp (cpu.szVendorName, "GenuineIntel") == 0) cpu.dwChipManufacturer = Intel; // Intel Corp.
else if (strcmp (cpu.szVendorName, "UMC UMC UMC ") == 0) cpu.dwChipManufacturer = UMC; // United Microelectronics Corp.
else if (strcmp (cpu.szVendorName, "AuthenticAMD") == 0) cpu.dwChipManufacturer = AMD; // Advanced Micro Devices
else if (strcmp (cpu.szVendorName, "AMD ISBETTER") == 0) cpu.dwChipManufacturer = AMD; // Advanced Micro Devices (1994)
else if (strcmp (cpu.szVendorName, "CyrixInstead") == 0) cpu.dwChipManufacturer = Cyrix; // Cyrix Corp., VIA Inc.
else if (strcmp (cpu.szVendorName, "NexGenDriven") == 0) cpu.dwChipManufacturer = NexGen; // NexGen Inc. (now AMD)
else if (strcmp (cpu.szVendorName, "CentaurHauls") == 0) cpu.dwChipManufacturer = IDT; // IDT/Centaur (now VIA)
else if (strcmp (cpu.szVendorName, "RiseRiseRise") == 0) cpu.dwChipManufacturer = Rise; // Rise
else if (strcmp (cpu.szVendorName, "GenuineTMx86") == 0) cpu.dwChipManufacturer = Transmeta; // Transmeta
else if (strcmp (cpu.szVendorName, "TransmetaCPU") == 0) cpu.dwChipManufacturer = Transmeta; // Transmeta
else if (strcmp (cpu.szVendorName, "Geode By NSC") == 0) cpu.dwChipManufacturer = NSC; // National Semiconductor
else cpu.dwChipManufacturer = Unknown; // Unknown manufacturer
// get processor speed
cpu.dwMhz = getProcessorSpeed();
// get number of processors
cpu.dwNumProcessors = getNumProcessors();
// get processor page size
cpu.dwPageSize = getProcessorPageSize();
// get processor identifier
strncpy(cpu.szProcessorArchitecture,getProcessorIdentifier().c_str(),sizeof(cpu.szProcessorArchitecture));
// Retrieve the family of CPU present.
int CPUSignature = getProcessorSignature();
cpu.dwExtendedFamily = ((CPUSignature & 0x0FF00000) >> 20); // Bits 27..20 Used
cpu.dwExtendedModel = ((CPUSignature & 0x000F0000) >> 16); // Bits 19..16 Used
cpu.dwType = ((CPUSignature & 0x0000F000) >> 12); // Bits 15..12 Used
cpu.dwFamily = ((CPUSignature & 0x00000F00) >> 8); // Bits 11..8 Used
cpu.dwModel = ((CPUSignature & 0x000000F0) >> 4); // Bits 7..4 Used
cpu.dwRevision = ((CPUSignature & 0x0000000F) >> 0); // Bits 3..0 Used
cpu.dwCPUFeatures = getProcessorFeatures();
// Retrieve the features of CPU present.
cpu.Features.HasFPU = ((cpu.dwCPUFeatures & 0x00000001) != 0); // FPU Present --> Bit 0
cpu.Features.HasTSC = ((cpu.dwCPUFeatures & 0x00000010) != 0); // TSC Present --> Bit 4
cpu.Features.HasAPIC = ((cpu.dwCPUFeatures & 0x00000200) != 0); // APIC Present --> Bit 9
cpu.Features.HasMTRR = ((cpu.dwCPUFeatures & 0x00001000) != 0); // MTRR Present --> Bit 12
cpu.Features.HasCMOV = ((cpu.dwCPUFeatures & 0x00008000) != 0); // CMOV Present --> Bit 15
cpu.Features.HasSerial = ((cpu.dwCPUFeatures & 0x00040000) != 0); // Serial Present --> Bit 18
cpu.Features.HasACPI = ((cpu.dwCPUFeatures & 0x00400000) != 0); // ACPI Capable --> Bit 22
cpu.Features.HasMMX = ((cpu.dwCPUFeatures & 0x00800000) != 0); // MMX Present --> Bit 23
cpu.Features.HasSSE = ((cpu.dwCPUFeatures & 0x02000000) != 0); // SSE Present --> Bit 25
cpu.Features.HasSSE2 = ((cpu.dwCPUFeatures & 0x04000000) != 0); // SSE2 Present --> Bit 26
cpu.Features.HasThermal = ((cpu.dwCPUFeatures & 0x20000000) != 0); // Thermal Monitor Present --> Bit 29
cpu.Features.HasIA64 = ((cpu.dwCPUFeatures & 0x40000000) != 0); // IA64 Present --> Bit 30
// Retrieve extended SSE capabilities if SSE is available.
if (cpu.Features.HasSSE)
cpu.Features.HasSSEFP = checkSSEFP();
else
cpu.Features.HasSSEFP = false;
// Retrieve Intel specific extended features.
if (cpu.dwChipManufacturer == Intel) {
cpu.Features.ExtendedFeatures.SupportsHyperthreading = ((cpu.dwCPUFeatures & 0x10000000) != 0); // Intel specific: Hyperthreading --> Bit 28
cpu.Features.ExtendedFeatures.LogicalProcessorsPerPhysical = (cpu.Features.ExtendedFeatures.SupportsHyperthreading) ? ((cpu.dwCPUFeatures & 0x00FF0000) >> 16) : 1;
if ((cpu.Features.ExtendedFeatures.SupportsHyperthreading) && (cpu.Features.HasAPIC)){
// Retrieve APIC information if there is one present.
cpu.Features.ExtendedFeatures.APIC_ID = ((cpu.dwCPUFeatures & 0xFF000000) >> 24);
}
}
// Retrieve the CPU details.
// RetrieveCPUFeatures(cpu);
// Attempt to retrieve cache information.
RetrieveCPUCacheDetails(cpu);
// Retrieve the extended CPU details.
RetrieveExtendedCPUIdentity (cpu);
RetrieveExtendedCPUFeatures (cpu);
strncpy(cpu.szProcessorName,getCPUIdentity(cpu).c_str(),sizeof(cpu.szProcessorName));
// if (cpu.Features.HasSerial)
for (DWORD i = 0; i < cpu.dwNumProcessors; i++) {
CPUID cpuid;
cpuid.szSerialNumber[0] = 0;
cpuid.dwProcessorUsage = -1;
// Now attempt to retrieve the serial number (if possible).
memcpy(cpuid.szSerialNumber,getProcessorSerialNumber(i).c_str(),sizeof(cpuid.szSerialNumber));
cpu.idCPU.push_back(cpuid);
}
return TRUE;
}
... << RSDN@Home 1.0 beta 6a >>
With best regards, Thinker.
<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
With best regards, Thinker.
<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >
With best regards, Thinker.
<Только начали жить хорошо — деньги закончились. Только деньги появились нас обокрали :((( >