Determining CPU frequency

• 03-14-2008
pgzh
Determining CPU frequency
Hi,

is there any way one can determine the current CPU frequency?
I was trying to figure out a way to do this but couldn't find a way that works. My approach was to use the TSC (Time Stamp Counter), but with the tickless feature in the kernel the TSC gets unstable and can't be used for frequency calculation anymore.

Here's a draft of this idea (though on my systems with tickless enabled the calculated frequency is absolutely wrong):
Code:

```#include <stdio.h> #include <sys/time.h> #include <string.h> #include <unistd.h> unsigned long long int rdtsc(void) {         unsigned long long int x;         __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));         return x; } int main() {         struct timezone tz;         struct timeval tvstart, tvstop;         unsigned long long int cycles[2];         unsigned long microseconds;         int mhz;         memset(&tz, 0, sizeof(tz));         gettimeofday(&tvstart, &tz);         cycles[0] = rdtsc();         gettimeofday(&tvstart, &tz);         usleep(250000);         gettimeofday(&tvstop, &tz);         cycles[1] = rdtsc();         gettimeofday(&tvstop, &tz);         microseconds = ((tvstop.tv_sec-tvstart.tv_sec)*1000000) + (tvstop.tv_usec-tvstart.tv_usec);         mhz = (int) (cycles[1]-cycles[0]) / microseconds;         printf("%i MHz\n",mhz);   return 0; }```
The idea is to read the TSC, wait a small amount of time and read the TSC again. TSCnow-TSCstart / waited_time will return the CPU frequency provided the TSC is stable.
With tickless this gets all messed up and I can't come up with any other idea...

Peter
• 03-14-2008
brewbuck
Quote:

Originally Posted by pgzh
The idea is to read the TSC, wait a small amount of time and read the TSC again. TSCnow-TSCstart / waited_time will return the CPU frequency provided the TSC is stable.

In fact, this is exactly how Linux computes the frequency...

If you're on Linux, just read the frequency from /proc/cpuinfo. Calculating it yourself on a live system is going to be impossible.

I thought maybe the CPUID instruction would give you the processor frequency, but it doesn't seem to. You might also be able to query the BIOS somehow, but I doubt you can do that from a booted operating system.
• 03-14-2008
pgzh
Are you sure Linux reads the TSC for frequency calculation? The cpu mhz info in /proc/cpuinfo changes when using cpufreq with ondemand, but the TSC does not tick constant if tickless is enabled - and therefore it's impossible to calculate the frequency after booting up with the TSC.

Reading /proc/cpuinfo seems like quite a cheap solution, but I really can't think of any better way to get the cpu frequency.

I don't know if MS Windows implements something comparable to the tickless feature of Linux, because there are lots of tools for Windows that can calculate the cpu frequency quite accurately. Or maybe there is another way to get the current cpu mhz?

Anyway - thanks for the tip!

Peter
• 03-14-2008
brewbuck
Quote:

Originally Posted by pgzh
Are you sure Linux reads the TSC for frequency calculation? The cpu mhz info in /proc/cpuinfo changes when using cpufreq with ondemand, but the TSC does not tick constant if tickless is enabled - and therefore it's impossible to calculate the frequency after booting up with the TSC.

I based my statement on code I see in Linux 2.4.15. It may be different now in 2.6.

Quote:

Reading /proc/cpuinfo seems like quite a cheap solution, but I really can't think of any better way to get the cpu frequency.
I don't think you can do any better. Linux /proc is unusual because it generates human-readable output. Other UNIX systems produce binary structures which are easier to deal with. On Linux you are left calling fgets() and parsing lines. Sucks for the programmer but makes it easier for the user who just wants to "cat /proc/whatever".
• 03-15-2008
pgzh
Where exactly in the Linux source code did you look? Maybe I can look for the way this is handled in 2.6 myself.

Peter
• 03-15-2008
Codeplug
• 03-17-2008
brewbuck
Quote:

Originally Posted by pgzh
Where exactly in the Linux source code did you look? Maybe I can look for the way this is handled in 2.6 myself.

The (quite confusing) algorithm is located in arch/i386/kernel/time.c (but that was 2.4)
• 03-17-2008
matsp
Quote:

Are you sure Linux reads the TSC for frequency calculation?
If it should have ANY chance to figure out the speed of a modern x86 CPU, yes. There is realistically no other method that works. [Yes, you can run loops, and based on "clocks per instruction" calculate what the processor is running at - but you need to be VERY careful, because different processor models will have different levels of parallelism and different clock counts for the same instructions].

Quote:

but the TSC does not tick constant if tickless is enabled
I'm pretty sure this is NOT related to tickless. tickless just means that the machine will not have a x Hz timer tick that interrupts x times per second, but rather set up the timer interrupt to interrupt "when it's needed" [e.g. if the next thing waiting is waiting for 250000 microseconds to elapse, then set a timer for 250 us from now]. Since it's very likely that waiting processes aren't waiting for the next timer tick most of the time, it's a good saving to just set it to tick when there's actually something waiting for that time to come up. [It is rather complicated to implement a tickless kernel, however, which is why it wasn't implemented before].

If TSC is varying, then it's most likely because you are running the power management and it detects idle CPU and stops/slows down the CPU. This SHOULD happen whether you are running with or without ticks, however.

--
Mats