I use the GetSystemInfo to get how many processors and the manufacturer of
it the system has, but I still need a method that works on all Windows ver's
for getting how many MHz the CPU is...
PLEASE HELP :)
Nitro`
The problem is not Windows, the problem is not all CPUs make it easy to
determine the CPU speed. Below is some code I have used to determine the CPU
speed and the vendor string. Note that it will only work on CPUs that support
the rdtsc instruction, which is most Pentium class and higher. It compiles with
MSVC 5 and 6.
One note: The code below calls the function Mpause, which is my own high
accuracy millisecond timer based on QueryPerformanceCounter();
/* cpuspeed.c
*
* Copyright 1999 Hawk Software
*
* Written by Phil Frisbie, Jr.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the author be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely.
*
* This software will be able to determine the CPU speed of
* any CPU that supports the rdtsc instruction, which includes
* Intel Pentium or higher CPUs, AMD K6 or higher CPUs, and
* some Cyrix CPUs.
*
*/
#include <windows.h>
#include "cpuinfo.h"
#include "timer.h"
#define CPUID __asm _emit 0x0f __asm _emit 0xa2
#define RDTSC __asm _emit 0x0f __asm _emit 0x31
#define TIME_PERIOD 100 /* Time in ms to count cycles, increase for more
accuracy */
char no_name[16] = "NoVendorName";
long name[4];
BOOL cpuHasCPUID(void)
{
BOOL has_cpuid = FALSE;
__asm{
pushfd ; push eflags
pop eax ; move to eflags to aex
mov edx,eax ; make a copy
xor eax,200000h ; toggle the bit
push eax ; push copy of eflags
popfd ; check if CPUID flag could toggle
pushfd ; save it, so we can check it
pop eax ; get it
xor eax,edx ; did bit toggle?
jz end_label ; can't use CPUID instruction
mov has_cpuid, TRUE ; can use CPUID instruction
end_label:
push edx ; push origianl copy of EFLAGS
popfd ; restore original EFLAGS value
}
return has_cpuid;
}
void cpuGetInfo(int level, int *a, int *b, int *c, int *d)
{
long A, B, C, D;
__asm{
mov eax, level ; function (level)
CPUID ; get the name
mov A, eax ; copy register
mov B, ebx ; copy register
mov C, ecx ; copy register
mov D, edx ; copy register
}
*a = A;
*b = B;
*c = C;
*d = D;
}
unsigned long rdtsc(void)
{
unsigned long a;
__asm{
RDTSC ; get the count
mov a, eax ; copy register
}
return a;
}
BOOL cpuHasRDTSC(void)
{
BOOL hasRDTSC = FALSE;
int a, b, c, d;
if(!cpuHasCPUID())
{
return FALSE;
}
cpuGetInfo(1, &a, &b, &c, &d);
hasRDTSC = (d & 0x10 ? TRUE:FALSE);
return hasRDTSC;
}
long cpuspeed(void)
{
unsigned long a, b, s;
int tp, pp;
HANDLE t, p;
if(!cpuHasRDTSC())
{
return 0;
}
initTimer(1000);
t = GetCurrentThread();
tp = GetThreadPriority(t);
SetThreadPriority(t, THREAD_PRIORITY_TIME_CRITICAL);
p = GetCurrentProcess();
pp = GetPriorityClass(p);
SetPriorityClass(p, REALTIME_PRIORITY_CLASS);
Mpause(1);
a = rdtsc(); /* read the performance counter */
Mpause(TIME_PERIOD); /* pause */
b = rdtsc(); /* read the performance counter */
if(a > b) /* we wrapped past zero */
{
a = b;
Mpause(TIME_PERIOD);/* pause again */
b = rdtsc();/* read again */
}
s = b - a;
SetThreadPriority(t, tp);
SetPriorityClass(p, pp);
return s/(TIME_PERIOD * 1000);/* convert to MHz */
}
char *cpuvendor(void)
{
long a = 0, b, c, d;
if(!cpuHasCPUID())
{
return no_name;
}
__asm{
mov eax, a ; function 0
CPUID ; get the name
mov a, eax ; copy register
mov b, ebx ; copy register
mov c, ecx ; copy register
mov d, edx ; copy register
}
name[0] = b;
name[1] = d;
name[2] = c;
name[3] = 0;
return (char *)name;
}
Phil Frisbie, Jr.
Lead Developer, Hawk Software
http://www.hawksoft.com