Add cpu id and cpu frequency functions.

This commit is contained in:
aignacio_sf 2008-01-04 00:57:10 +00:00
parent 732215ed61
commit 601f094d8d
3 changed files with 801 additions and 2 deletions

View File

@ -30,6 +30,12 @@ DisplayInformation::
if (_display_mode_array != NULL) {
delete _display_mode_array;
}
if (_cpu_id_data != NULL) {
delete _cpu_id_data;
}
if (_cpu_brand_string != NULL) {
delete _cpu_brand_string;
}
}
////////////////////////////////////////////////////////////////////
@ -94,8 +100,20 @@ DisplayInformation() {
_vendor_id = 0;
_device_id = 0;
_cpu_id_version = 1;
_cpu_id_size = 0;
_cpu_id_data = 0;
_cpu_vendor_string = 0;
_cpu_brand_string = 0;
_cpu_version_information = 0;
_cpu_brand_index = 0;
_cpu_frequency = 0;
_get_memory_information_function = 0;
_cpu_time_function = 0;
}
////////////////////////////////////////////////////////////////////
@ -413,3 +431,123 @@ int DisplayInformation::
get_device_id() {
return _device_id;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayInformation::get_cpu_id_version
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
int DisplayInformation::
get_cpu_id_version() {
return _cpu_id_version;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayInformation::get_cpu_id_size
// Access: Published
// Description: Returns the number of 32-bit values for cpu id
// binary data.
////////////////////////////////////////////////////////////////////
int DisplayInformation::
get_cpu_id_size() {
return _cpu_id_size;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayInformation::get_cpu_id_data
// Access: Published
// Description: Returns part of cpu id binary data based on the
// index.
////////////////////////////////////////////////////////////////////
unsigned int DisplayInformation::
get_cpu_id_data(int index) {
unsigned int data;
data = 0;
if (index >= 0 && index < _cpu_id_size) {
data = _cpu_id_data [index];
}
return data;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayInformation::get_cpu_vendor_string
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
char *DisplayInformation::
get_cpu_vendor_string() {
char *string;
string = _cpu_vendor_string;
if (string == 0) {
string = "";
}
return string;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayInformation::get_cpu_brand_string
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
char *DisplayInformation::
get_cpu_brand_string() {
char *string;
string = _cpu_brand_string;
if (string == 0) {
string = "";
}
return string;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayInformation::get_cpu_version_information
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
unsigned int DisplayInformation::
get_cpu_version_information() {
return _cpu_version_information;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayInformation::get_cpu_brand_index
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
unsigned int DisplayInformation::
get_cpu_brand_index() {
return _cpu_brand_index;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayInformation::get_cpu_frequency
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
PN_uint64 DisplayInformation::
get_cpu_frequency() {
return _cpu_frequency;
}
////////////////////////////////////////////////////////////////////
// Function: DisplayInformation::get_cpu_time
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
PN_uint64 DisplayInformation::
get_cpu_time() {
PN_uint64 cpu_time;
cpu_time = 0;
if (_cpu_time_function) {
cpu_time = _cpu_time_function();
}
return cpu_time;
}

View File

@ -85,6 +85,18 @@ PUBLISHED:
int get_vendor_id();
int get_device_id();
int get_cpu_id_version();
int get_cpu_id_size();
unsigned int get_cpu_id_data(int index);
char *get_cpu_vendor_string();
char *get_cpu_brand_string();
unsigned int get_cpu_version_information();
unsigned int get_cpu_brand_index();
PN_uint64 get_cpu_frequency();
PN_uint64 get_cpu_time();
public:
DetectionState _state;
@ -116,8 +128,20 @@ public:
int _vendor_id;
int _device_id;
int _cpu_id_version;
int _cpu_id_size;
unsigned int *_cpu_id_data;
char *_cpu_vendor_string;
char *_cpu_brand_string;
unsigned int _cpu_version_information;
unsigned int _cpu_brand_index;
PN_uint64 _cpu_frequency;
void (*_get_memory_information_function) (DisplayInformation *display_information);
PN_uint64 (*_cpu_time_function) (void);
};
#endif

View File

@ -100,6 +100,547 @@ void get_memory_information (DisplayInformation *display_information)
}
}
typedef union
{
PN_uint64 long_integer;
}
LONG_INTEGER;
PN_uint64 cpu_time_function (void) {
LONG_INTEGER long_integer;
LONG_INTEGER *long_integer_pointer;
long_integer_pointer = &long_integer;
__asm
{
mov ebx,[long_integer_pointer]
rdtsc
mov [ebx + 0], eax
mov [ebx + 4], edx
}
return long_integer.long_integer;
}
typedef union
{
struct
{
union
{
struct
{
unsigned char al;
unsigned char ah;
};
unsigned int eax;
};
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
};
}
CPU_ID_REGISTERS;
typedef struct
{
union
{
struct
{
int maximum_cpu_id_input;
char cpu_vendor [16];
};
CPU_ID_REGISTERS cpu_id_registers_0;
};
union
{
CPU_ID_REGISTERS cpu_id_registers_1;
struct
{
// eax
union
{
unsigned int eax;
unsigned int version_information;
struct
{
unsigned int stepping_id : 4;
unsigned int model : 4;
unsigned int family : 4;
unsigned int processor_type : 2;
unsigned int reserved_0 : 2;
unsigned int extended_model_id : 4;
unsigned int extended_family_id : 8;
unsigned int reserved_1 : 4;
};
};
// ebx
union
{
unsigned int ebx;
struct
{
unsigned int brand_index : 8;
unsigned int clflush : 8;
unsigned int maximum_logical_processors : 8;
unsigned int initial_apic_id : 8;
};
};
// ecx
union
{
unsigned int ecx;
struct
{
unsigned int sse3 : 1;
unsigned int reserved_1_to_2 : 2;
unsigned int monitor : 1;
unsigned int ds_cpl : 1;
unsigned int vmx : 1;
unsigned int reserved_6 : 1;
unsigned int est : 1;
unsigned int tm2 : 1;
unsigned int reserved_9 : 1;
unsigned int cnxt_id : 1;
unsigned int reserved_11_to_12 : 2;
unsigned int cmpxchg16b : 1;
unsigned int xtpr_disable : 1;
unsigned int reserved_15_to_31 : 17;
};
};
// edx
union
{
unsigned int edx;
struct
{
unsigned int fpu : 1;
unsigned int vme : 1;
unsigned int de : 1;
unsigned int pse : 1;
unsigned int tsc : 1;
unsigned int msr : 1;
unsigned int pae : 1;
unsigned int mce : 1;
unsigned int cx8 : 1;
unsigned int apic : 1;
unsigned int reserved_10 : 1;
unsigned int sep : 1;
unsigned int mtrr : 1;
unsigned int pge : 1;
unsigned int mca : 1;
unsigned int cmov : 1;
unsigned int pat : 1;
unsigned int pse_36 : 1;
unsigned int psn : 1;
unsigned int cflush : 1;
unsigned int reserved_20 : 1;
unsigned int ds : 1;
unsigned int acpi : 1;
unsigned int mmx : 1;
unsigned int fxsr : 1;
unsigned int sse : 1;
unsigned int sse2 : 1;
unsigned int ss : 1;
unsigned int htt : 1;
unsigned int tm : 1;
unsigned int reserved_30 : 1;
unsigned int pbe : 1;
};
};
};
};
#define MAXIMUM_2 8
#define MAXIMUM_CHARACTERS (MAXIMUM_2 * sizeof (CPU_ID_REGISTERS))
union
{
CPU_ID_REGISTERS cpu_id_registers_2;
unsigned char character_array_2 [MAXIMUM_CHARACTERS];
CPU_ID_REGISTERS cpu_id_registers_2_array [MAXIMUM_2];
};
union
{
CPU_ID_REGISTERS cpu_id_registers_0x80000000;
};
union
{
CPU_ID_REGISTERS cpu_id_registers_0x80000001;
};
union
{
char cpu_brand_string [sizeof (CPU_ID_REGISTERS) * 3];
struct
{
CPU_ID_REGISTERS cpu_id_registers_0x80000002;
CPU_ID_REGISTERS cpu_id_registers_0x80000003;
CPU_ID_REGISTERS cpu_id_registers_0x80000004;
};
};
union
{
struct
{
// eax
union
{
unsigned int eax;
};
// ebx
union
{
unsigned int ebx;
};
// ecx
union
{
unsigned int ecx;
struct
{
unsigned int l1_data_cache_line_size : 8;
unsigned int l1_data_reserved_8_to_15 : 8;
unsigned int l1_data_associativity : 8;
unsigned int l1_data_cache_size : 8;
};
};
// edx
union
{
unsigned int edx;
struct
{
unsigned int l1_code_cache_line_size : 8;
unsigned int l1_code_reserved_8_to_15 : 8;
unsigned int l1_code_associativity : 8;
unsigned int l1_code_cache_size : 8;
};
};
};
CPU_ID_REGISTERS cpu_id_registers_0x80000005;
};
union
{
struct
{
// eax
union
{
unsigned int eax;
};
// ebx
union
{
unsigned int ebx;
};
// ecx
union
{
unsigned int ecx;
struct
{
unsigned int l2_cache_line_size : 8;
unsigned int l2_reserved_8_to_11 : 4;
unsigned int l2_associativity : 4;
unsigned int l2_cache_size : 16;
};
};
// edx
union
{
unsigned int edx;
};
};
CPU_ID_REGISTERS cpu_id_registers_0x80000006;
};
union
{
struct
{
// eax
union
{
unsigned int eax;
};
// ebx
union
{
unsigned int ebx;
};
// ecx
union
{
unsigned int ecx;
};
// edx
union
{
unsigned int edx;
};
};
CPU_ID_REGISTERS cpu_id_registers_0x80000008;
};
unsigned int cache_line_size;
unsigned int log_base_2_cache_line_size;
}
CPU_ID;
typedef struct
{
CPU_ID_REGISTERS cpu_id_registers_0;
CPU_ID_REGISTERS cpu_id_registers_1;
CPU_ID_REGISTERS cpu_id_registers_0x80000000;
CPU_ID_REGISTERS cpu_id_registers_0x80000001;
CPU_ID_REGISTERS cpu_id_registers_0x80000002;
CPU_ID_REGISTERS cpu_id_registers_0x80000003;
CPU_ID_REGISTERS cpu_id_registers_0x80000004;
CPU_ID_REGISTERS cpu_id_registers_0x80000006;
CPU_ID_REGISTERS cpu_id_registers_0x80000008;
}
CPU_ID_BINARY_DATA;
typedef struct
{
union
{
CPU_ID_BINARY_DATA cpu_binary_data;
unsigned int data_array [sizeof (CPU_ID_BINARY_DATA) / 4];
};
}
CPU_ID_BINARY_DATA_ARRAY;
void cpu_id_to_cpu_id_binary_data (CPU_ID *cpu_id, CPU_ID_BINARY_DATA *cpu_id_binary_data) {
cpu_id_binary_data -> cpu_id_registers_0 = cpu_id -> cpu_id_registers_0;
cpu_id_binary_data -> cpu_id_registers_1 = cpu_id -> cpu_id_registers_1;
cpu_id_binary_data -> cpu_id_registers_0x80000000 = cpu_id -> cpu_id_registers_0x80000000;
cpu_id_binary_data -> cpu_id_registers_0x80000001 = cpu_id -> cpu_id_registers_0x80000001;
cpu_id_binary_data -> cpu_id_registers_0x80000002 = cpu_id -> cpu_id_registers_0x80000002;
cpu_id_binary_data -> cpu_id_registers_0x80000003 = cpu_id -> cpu_id_registers_0x80000003;
cpu_id_binary_data -> cpu_id_registers_0x80000004 = cpu_id -> cpu_id_registers_0x80000004;
cpu_id_binary_data -> cpu_id_registers_0x80000006 = cpu_id -> cpu_id_registers_0x80000006;
cpu_id_binary_data -> cpu_id_registers_0x80000008 = cpu_id -> cpu_id_registers_0x80000008;
}
void cpu_id_binary_data_to_cpu_id (CPU_ID_BINARY_DATA *cpu_id_binary_data, CPU_ID *cpu_id) {
memset (cpu_id, 0, sizeof (CPU_ID));
cpu_id -> cpu_id_registers_0 = cpu_id_binary_data -> cpu_id_registers_0;
cpu_id -> cpu_id_registers_1 = cpu_id_binary_data -> cpu_id_registers_1;
cpu_id -> cpu_id_registers_0x80000000 = cpu_id_binary_data -> cpu_id_registers_0x80000000;
cpu_id -> cpu_id_registers_0x80000001 = cpu_id_binary_data -> cpu_id_registers_0x80000001;
cpu_id -> cpu_id_registers_0x80000002 = cpu_id_binary_data -> cpu_id_registers_0x80000002;
cpu_id -> cpu_id_registers_0x80000003 = cpu_id_binary_data -> cpu_id_registers_0x80000003;
cpu_id -> cpu_id_registers_0x80000004 = cpu_id_binary_data -> cpu_id_registers_0x80000004;
cpu_id -> cpu_id_registers_0x80000006 = cpu_id_binary_data -> cpu_id_registers_0x80000006;
cpu_id -> cpu_id_registers_0x80000008 = cpu_id_binary_data -> cpu_id_registers_0x80000008;
}
int cpuid (int input_eax, CPU_ID_REGISTERS *cpu_id_registers) {
int state;
state = false;
__try
{
if (input_eax == 0) {
// the order of ecx and edx is swapped when saved to make a proper vendor string
__asm
{
mov eax, [input_eax]
mov edi, [cpu_id_registers]
cpuid
mov [edi + 0], eax
mov [edi + 4], ebx
mov [edi + 8], edx
mov [edi + 12], ecx
}
}
else {
__asm
{
mov eax, [input_eax]
mov edi, [cpu_id_registers]
cpuid
mov [edi + 0], eax
mov [edi + 4], ebx
mov [edi + 8], ecx
mov [edi + 12], edx
}
}
state = true;
}
__except (1)
{
state = false;
}
return state;
}
void parse_cpu_id (CPU_ID *cpu_id) {
printf ("CPUID\n");
printf (" vendor = %s \n", cpu_id -> cpu_vendor);
printf (" brand string %s \n", cpu_id -> cpu_brand_string);
printf (" maximum_cpu_id_input = %u \n", cpu_id -> maximum_cpu_id_input);
printf (" maximum extended information = 0x%X \n", cpu_id -> cpu_id_registers_0x80000000.eax);
printf (" MMX = %u \n", cpu_id -> mmx);
printf (" SSE = %u \n", cpu_id -> sse);
printf (" SSE2 = %u \n", cpu_id -> sse2);
printf (" SSE3 = %u \n", cpu_id -> sse3);
printf (" EST = %u \n", cpu_id -> est);
if (cpu_id -> maximum_cpu_id_input >= 1) {
printf (" version_information \n");
printf (" stepping_id %u \n", cpu_id -> stepping_id);
printf (" model %u \n", cpu_id -> model);
printf (" family %u \n", cpu_id -> family);
printf (" processor_type %u \n", cpu_id -> processor_type);
printf (" extended_model_id %u \n", cpu_id -> extended_model_id);
printf (" extended_family_id %u \n", cpu_id -> extended_family_id);
printf (" brand_index %u \n", cpu_id -> brand_index);
printf (" clflush %u \n", cpu_id -> clflush);
printf (" maximum_logical_processors %u \n", cpu_id -> maximum_logical_processors);
printf (" initial_apic_id %u \n", cpu_id -> initial_apic_id);
// printf (" cache_line_size %u \n", cpu_id -> cache_line_size);
// printf (" log_base_2_cache_line_size %u \n", cpu_id -> log_base_2_cache_line_size);
}
if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000005) {
printf (" l1_data_cache_line_size %d \n", cpu_id -> l1_data_cache_line_size);
printf (" l1_data_associativity %d \n", cpu_id -> l1_data_associativity);
printf (" l1_data_cache_size %dK \n", cpu_id -> l1_data_cache_size);
printf (" l1_code_cache_line_size %d \n", cpu_id -> l1_code_cache_line_size);
printf (" l1_code_associativity %d \n", cpu_id -> l1_code_associativity);
printf (" l1_code_cache_size %dK \n", cpu_id -> l1_code_cache_size);
}
if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000006) {
printf (" l2_cache_line_size %d \n", cpu_id -> l2_cache_line_size);
printf (" l2_associativity %d \n", cpu_id -> l2_associativity);
printf (" l2_cache_size %dK \n", cpu_id -> l2_cache_size);
}
}
int initialize_cpu_id (CPU_ID *cpu_id) {
int state;
int debug;
state = false;
debug = false;
memset (cpu_id, 0, sizeof (CPU_ID));
if (cpuid (0, &cpu_id -> cpu_id_registers_0)) {
if (cpu_id -> maximum_cpu_id_input >= 1) {
cpuid (1, &cpu_id -> cpu_id_registers_1);
}
if (cpu_id -> maximum_cpu_id_input >= 2) {
unsigned int index;
cpuid (2, &cpu_id -> cpu_id_registers_2);
if (debug) {
printf (" al = %u \n", cpu_id -> cpu_id_registers_2.al);
}
for (index = 1; index < cpu_id -> cpu_id_registers_2.al && index < MAXIMUM_2; index++) {
cpuid (2, &cpu_id -> cpu_id_registers_2_array [index]);
}
for (index = 1; index < MAXIMUM_CHARACTERS; index++) {
if (cpu_id -> character_array_2 [index]) {
if (debug) {
printf (" cache/TLB byte = %X \n", cpu_id -> character_array_2 [index]);
}
switch (cpu_id -> character_array_2 [index])
{
case 0x0A:
case 0x0C:
cpu_id -> cache_line_size = 32;
cpu_id -> log_base_2_cache_line_size = 5;
break;
case 0x2C:
case 0x60:
case 0x66:
case 0x67:
case 0x68:
cpu_id -> cache_line_size = 64;
cpu_id -> log_base_2_cache_line_size = 6;
break;
}
}
}
}
cpuid (0x80000000, &cpu_id -> cpu_id_registers_0x80000000);
if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000001) {
cpuid (0x80000001, &cpu_id -> cpu_id_registers_0x80000001);
}
if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000004) {
cpuid (0x80000002, &cpu_id -> cpu_id_registers_0x80000002);
cpuid (0x80000003, &cpu_id -> cpu_id_registers_0x80000003);
cpuid (0x80000004, &cpu_id -> cpu_id_registers_0x80000004);
}
if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000005) {
cpuid (0x80000005, &cpu_id -> cpu_id_registers_0x80000005);
}
if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000006) {
cpuid (0x80000006, &cpu_id -> cpu_id_registers_0x80000006);
}
if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000008) {
cpuid (0x80000008, &cpu_id -> cpu_id_registers_0x80000008);
}
state = true;
}
return state;
}
////////////////////////////////////////////////////////////////////
// Function: WinGraphicsPipe::Constructor
// Access: Public
@ -109,6 +650,7 @@ WinGraphicsPipe::
WinGraphicsPipe() {
bool state;
char string [512];
state = false;
_supported_types = OT_window | OT_fullscreen_window;
@ -141,9 +683,104 @@ WinGraphicsPipe() {
state = true;
}
#endif
// set callback for memory function
_display_information -> _get_memory_information_function = get_memory_information;
// set callback for cpu time function
_display_information -> _cpu_time_function = cpu_time_function;
// determine CPU frequency
PN_uint64 time;
PN_uint64 end_time;
LARGE_INTEGER counter;
LARGE_INTEGER end;
LARGE_INTEGER frequency;
time = 0;
end_time = 0;
counter.QuadPart = 0;
end.QuadPart = 0;
frequency.QuadPart = 0;
int priority;
HANDLE thread;
windisplay_cat.info() << "begin QueryPerformanceFrequency\n";
thread = GetCurrentThread();
priority = GetThreadPriority (thread);
SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL);
if (QueryPerformanceFrequency(&frequency)) {
if (frequency.QuadPart > 0) {
if (QueryPerformanceCounter (&counter)) {
time = cpu_time_function();
end.QuadPart = counter.QuadPart + frequency.QuadPart;
while (QueryPerformanceCounter (&counter) && counter.QuadPart < end.QuadPart) {
}
end_time = cpu_time_function();
_display_information -> _cpu_frequency = end_time - time;
}
}
}
SetThreadPriority(thread, priority);
sprintf (string, "QueryPerformanceFrequency: %I64d\n", frequency.QuadPart);
windisplay_cat.info() << string;
sprintf (string, "CPU frequency: %I64d\n", _display_information -> _cpu_frequency);
windisplay_cat.info() << string;
// CPUID
int debug;
CPU_ID cpu_id;
debug = false;
windisplay_cat.info() << "start CPU ID\n";
if (initialize_cpu_id (&cpu_id)) {
CPU_ID_BINARY_DATA *cpu_id_binary_data;
cpu_id_binary_data = new (CPU_ID_BINARY_DATA);
if (cpu_id_binary_data) {
cpu_id_to_cpu_id_binary_data (&cpu_id, cpu_id_binary_data);
_display_information -> _cpu_id_size = sizeof (CPU_ID_BINARY_DATA) / sizeof (unsigned int);
_display_information -> _cpu_id_data = (unsigned int *) cpu_id_binary_data;
_display_information -> _cpu_vendor_string = strdup(cpu_id.cpu_vendor);
_display_information -> _cpu_brand_string = strdup(cpu_id.cpu_brand_string);
_display_information -> _cpu_version_information = cpu_id.version_information;
_display_information -> _cpu_brand_index = cpu_id.brand_index;
if (debug) {
printf ("%X|", _display_information -> _cpu_id_version);
int index;
for (index = 0; index < _display_information -> _cpu_id_size; index++) {
unsigned int data;
data = _display_information -> _cpu_id_data [index];
printf ("%X", data);
if (index < (_display_information -> _cpu_id_size - 1))
{
printf ("|");
}
}
printf ("\n");
}
}
if (debug) {
parse_cpu_id (&cpu_id);
}
}
windisplay_cat.info() << "end CPU ID\n";
if (state) {