0

I need to measure time based on Time Stmp Counter (TSC) for some reasons. To read TSC, I am using the code below:

#include <stdio.h>
#include <inttypes.h>

inline volatile uint32_t RDTSC32() {
    register uint32_t TSC asm("eax");
    asm volatile (".byte 15, 49" : : : "eax", "edx");
    return TSC;
}

inline volatile uint64_t RDTSC64() {
    register uint64_t TSC asm("rax");
    asm volatile (".byte 15, 49" : : : "rax", "rdx");
    return TSC;
} 

int main() {
    while (1) {
        printf("%" PRIu64 "\n", RDTSC64());
    }
} 

When I've tested it, it works fine. Except one thing. When it reaches the maximum counter value (some value higher than 4,256,448,731, in my environment,) the counter value gets reset to 0 and keeps going on.

In this situation, is there any way to see how many times TSC has been reset?

For example, the code below does not print a correct time difference:

#include <stdio.h>

int main() {
    long long start, end;
    start = RDTSC64();
    // long long works to do
    end = RDTSC64();
    printf("%lld \n", end - start);
} 
Jeon
  • 4,000
  • 4
  • 28
  • 73

1 Answers1

2

The time stamp counter is always 64-bit, see this statement on the Wipedia page:

The Time Stamp Counter (TSC) is a 64-bit register present on all x86 processors since the Pentium.

For some reason you're getting a truncated value with only 32 bits, which is why it wraps. The 64-bit value will need 146 years of continuous counting at 4 GHz to wrap.

Your code seems to want to use both eax and edx to hold the two 32 bit halves, as expected. Something must go wrong when moving the values to the single C variable. I believe the snippet you're using is for GCC; perhaps that's no longer your compiler?

Inspect the generated assembly, and check the compiler docs for a proper intrinsic function instead. This question has some good answers, with compiler-specific assembly.

Community
  • 1
  • 1
unwind
  • 391,730
  • 64
  • 469
  • 606
  • Thanks for answer. I have a question. Is TSC still 64-bit when CPU is 32-bit? And, using `rax` instead `eax` will solve `reset` problem? – Jeon Nov 27 '14 at 07:02