📄 speed.c
字号:
{
ulong total_ticks=0, ticks; // Microseconds elapsed
// during test
ulong total_cycles=0, cycles; // Clock cycles elapsed
// during test
ulong stamp0, stamp1; // Time Stamp Variable
// for beginning and end
ushort u0,u1; // 16-bit variables for time
ushort v0,v1; // stamp reads. These are
// later merged into
// stamp0, and stamp1
// (32-bit variables)
ulong freq; // Most current frequ. calculation
ulong freq2; // 2nd most current frequ. calc.
ulong freq3; // 3rd most current frequ. calc.
ulong total; // Sum of previous three frequency
// calculations
int manual=0; // Specifies whether the user
// manually entered the number of
// cycles for the BSF instruction.
int tries=0; // Number of times a calculation has
// been made on this call to
// cpuspeed
struct FREQ_INFO cpu_speed; // Return structure for
// cpuspeed
DWORD t0,t1; // Variables to store
// timeGetTime values
memset(&cpu_speed, 0x00, sizeof(cpu_speed));
// On Pentium Processors or above use
// the Read Time Stamp method which
// compares elapsed time on from the
// timeGetTime call with elaped
// cycles on the Time Stamp Register.
do { // This do loop runs up to 20 times or
// until the average of the previous
// three calculated frequencies is
// within 2 MHz of each of the
// individual calculated frequencies.
// This resampling increases the
// accuracy of the results since
// outside factors could affect this
// calculation
tries++; // Increment number of times sampled
// on this call to cpuspeed
freq3 = freq2; // Shift frequencies back to make
freq2 = freq; // room for new frequency
// measurement
t0 = timeGetTime();
t1 = t0; // Set Initial Time
while ( t1 - t0 < INITIAL_DELAY ) {
// Loop until three ticks have
// passed since last read of
// timeGetTime. This accounts for
// overhead later.
t1 = timeGetTime();
}
__asm // Read Time Stamp...
{
RDTSC
MOV CL, 16
MOV u0, AX
OPND32
SHR AX,CL
MOV u1, AX
}
t0 = t1; // Reset Initial Time
while ( t1 - t0 < SAMPLING_DELAY ) {
// Loop until 60 ticks have passed
// since last timeGetTime read.
// This allows for elapsed time
// for sampling
t1 = timeGetTime();
}
__asm // Read Time Stamp...
{
RDTSC
MOV CL, 16
MOV v0, AX
OPND32
SHR AX,CL
MOV v1, AX
}
stamp0 = (ulong) u1*65536 + u0;
stamp1 = (ulong) v1*65536 + v0;
// Move two 16-bit values into one
// 32-bit value for the time stamp
// read at both the beginning and
// end of the test.
cycles = stamp1 - stamp0; // Number of internal
// clock cycles is
// difference between
// two time stamp
// readings.
ticks = (ulong) t1 - t0; // Number of external
// ticks is difference
// between two
// timeGetTime reads
ticks = ticks * 1000; // Convert ticks to us
// (since the
// timeGetTime
// frequency is 1
// tick/ms).
total_ticks += ticks;
total_cycles += cycles;
freq = cycles/ticks; // Cycles / us = MHz
if ( cycles%ticks > ticks/2 )
freq++; // Round up if necessary
total = ( freq + freq2 + freq3 );
// Total last three frequency
// calculations
} while((tries<3) ||
(tries<MAX_TRIES)&&
((abs(3*(int)freq -(int)total)>3*TOLERANCE)||
(abs(3*(int)freq2-(int)total)>3*TOLERANCE)||
(abs(3*(int)freq3-(int)total)>3*TOLERANCE)));
// Compare last three calculations to
// average of last three calculations.
// Try one more significant digit.
freq3 = ( total_cycles * 10 ) / total_ticks;
freq2 = ( total_cycles * 100 ) / total_ticks;
if ( freq2 - (freq3 * 10) >= ROUND_THRESHOLD )
freq3++;
cpu_speed.raw_freq = total_cycles / total_ticks;
cpu_speed.norm_freq = cpu_speed.raw_freq;
freq = cpu_speed.raw_freq * 10;
if( (freq3 - freq) >= ROUND_THRESHOLD )
cpu_speed.norm_freq++;
cpu_speed.ex_ticks = total_ticks;
cpu_speed.in_cycles = total_cycles;
return cpu_speed;
}
static int GetCmosTick(void)
{
int tick = 0;
// __asm mov ah, 02h
// __asm int 1Ah
// __asm mov al, dh
// __asm and ax, 000Fh
__asm xor ax, ax
__asm out 070h, al
__asm xor ax, ax
__asm in al, 071h
// _outp( 0x70, offset );
// base = _inp( 0x71 );
// value returned in ax by function
__asm mov word ptr tick, ax
return tick;
}
//#define ABS_TICK(a,b) (b<a)?b+60-a:b-a
// since I am only interested in single ticks
#define ABS_TICK(a,b) (b<a)?b+10-a:b-a
static struct FREQ_INFO GetCmosCpuSpeed()
{
int timeStart, timeStop, lapseTime;
unsigned long temp;
unsigned long temp1;
struct FREQ_INFO cpu_speed;
unsigned long cpuSpeed = 0l;
ulong stamp0, stamp1; // Time Stamp Variable
// for beginning and end
ushort u0,u1; // 16-bit variables for time
ushort v0,v1; // stamp reads. These are
// later merged into
// stamp0, and stamp1
// (32-bit variables)
memset(&cpu_speed, 0x00, sizeof(cpu_speed));
// This loop waits for the next tick
// so that we begin speed test on a tick edge
timeStart = GetCmosTick();
for(;;)
{
timeStop = GetCmosTick();
if ( ABS_TICK(timeStart,timeStop) > 0 )
{
__asm // Read Time Stamp...
{
RDTSC
MOV CL, 16
MOV u0, AX
OPND32
SHR AX,CL
MOV u1, AX
}
break;
}
}
timeStart = timeStop;
for(;;)
{
timeStop = GetCmosTick();
if ( ABS_TICK(timeStart,timeStop) > 0 )
{
__asm // Read Time Stamp...
{
RDTSC
MOV CL, 16
MOV v0, AX
OPND32
SHR AX,CL
MOV v1, AX
}
break;
}
}
// convert into long values
stamp0 = (ulong) u1*65536 + u0;
stamp1 = (ulong) v1*65536 + v0;
lapseTime = ABS_TICK(timeStart,timeStop);
cpuSpeed = stamp1 - stamp0; ///lapseTime;
cpu_speed.in_cycles = cpuSpeed; // Cycles count since we in this routine
//round to nearest digit
temp = cpuSpeed/1000000;
temp1 = cpuSpeed/100000;
temp = temp * 10; // realign with last digit = zero
cpuSpeed = cpuSpeed/1000000; // cpuSpeed/1000000;
cpu_speed.raw_freq = cpuSpeed;
if( (temp1 - temp) >= ROUND_THRESHOLD )
cpuSpeed++;
cpu_speed.norm_freq = cpuSpeed;
cpu_speed.ex_ticks = (timeStop - timeStart) * 1000000;
return cpu_speed;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -