Hi

Is there an easy/accurate way to calculate the tsc timecounter frequency?
like Time Stamp Counters <http://blog.tinola.com/?e=54> on Linux. (on a
Sandy Bridge cpu)

Another reference Converting Sandy Bridge TSC to wall clock time
<https://software.intel.com/en-us/forums/intel-isa-extensions/topic/284137>.

The code below works but i don't really know how accurate it is, at best
10,000 Hz.

Cheers
Adam

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>

uint64_t rdtscp()
{
    uint32_t lo, hi;
     __asm__ __volatile__ ("RDTSCP\n\t"
                           "mov %%edx, %0\n\t"
                           "mov %%eax, %1\n\t"
                           "CPUID\n\t": "=r" (hi), "=r" (lo):: "%rax",
"%rbx", "%rcx", "%rdx");
    return (uint64_t)hi << 32 | lo;
}

uint64_t rdtsc()
{
    uint32_t lo, hi;
     __asm__ __volatile__ ("CPUID\n\t"
                           "RDTSC\n\t"
                           "mov %%edx, %0\n\t"
                           "mov %%eax, %1\n\t": "=r" (hi), "=r" (lo)::
                           "%rax", "%rbx", "%rcx", "%rdx");;
    return (uint64_t)hi << 32 | lo;
}

uint64_t get_tsc_freq_hz()
{
    uint64_t start_timestamp, end_timestamp;
    struct timeval tv_start, tv_end;

    gettimeofday(&tv_start, NULL);
    start_timestamp = rdtsc();
    while (1) {
        gettimeofday(&tv_end, NULL);
        if (tv_end.tv_sec > tv_start.tv_sec + 1)
            break;
    }
    end_timestamp = rdtscp();

    uint64_t cycles = end_timestamp - start_timestamp;
    uint64_t usec = (tv_end.tv_sec - tv_start.tv_sec) * 1000000 +
(tv_end.tv_usec - tv_start.tv_usec);
    // convert to cycles per second need to muliple the result by 1000000
    uint64_t tsc_freq = 1000000 * cycles / usec;

    return tsc_freq;
}

int main (int argc, char *argv[])
{
    uint64_t tsc_freq = get_tsc_freq_hz();

    printf("TSC frequency = %llu Hz\n", tsc_freq);

    return 0;
}

Reply via email to