Determining CPU frequency

This is a discussion on Determining CPU frequency within the Linux Programming forums, part of the Platform Specific Boards category; Hi, is there any way one can determine the current CPU frequency? I was trying to figure out a way ...

  1. #1
    Registered User
    Join Date
    Mar 2008
    Posts
    15

    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

  2. #2
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,248
    Quote Originally Posted by pgzh View Post
    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.

  3. #3
    Registered User
    Join Date
    Mar 2008
    Posts
    15
    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

  4. #4
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,248
    Quote Originally Posted by pgzh View Post
    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.

    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".

  5. #5
    Registered User
    Join Date
    Mar 2008
    Posts
    15
    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

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,676

  7. #7
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,248
    Quote Originally Posted by pgzh View Post
    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)

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    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].

    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
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. questions on multiple thread programming
    By lehe in forum C Programming
    Replies: 11
    Last Post: 03-27-2009, 07:44 AM
  2. Upgrading my old CPU (for another old one!)
    By foxman in forum Tech Board
    Replies: 16
    Last Post: 01-11-2008, 04:41 PM
  3. Can you still view the bios screen with a bad CPU?
    By HyperCreep in forum Tech Board
    Replies: 4
    Last Post: 12-31-2006, 05:57 PM
  4. CPU temp
    By PING in forum Tech Board
    Replies: 5
    Last Post: 01-28-2006, 05:25 AM
  5. determining frequency
    By lakai02 in forum C Programming
    Replies: 4
    Last Post: 10-03-2002, 05:03 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21