This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  How To Read The TSC With GCC
  Submitted by



The RDTSC ("read time stamp counter") instruction available on recent processors is a great tool for accurate timing. It stores the number of elapsed clock-cycles since power-on as 64 bit integer with high 32 bits in register edx and low 32 bits in register eax. So by comparing the results of RDTSC before and after some action really could give run-time timing/profiling information accurate to clock cycles. In practice however, your favorive 32 bit multitasking OS will get into the way here and there, not letting you measure your process running exclusively - but nevertheless RDTSC gives the time that has physically elapsed (as seen by the user).

Studying the documentation of the gcc compiler, I stumbled upon the extended inline asm capabilites described in the section "C extensions". These are some really cool features that let you write assembler macros and tell the compiler how your asm code uses registers so the compiler can incorporate the hand written assembler-code into it's own data-flow analysis. The following piece of code is an inline function returning the TSC as 64 bit long long:

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



I declare the function RDTSC as volatile since the optimizer must not move calls to RDTSC() out of a loop. Then follows the declaration of a long long register variable explicitly using the register "eax". Of course eax itself is only 32 bits, but it seems, after analyzing the compiler output (never I found documentation for that), that gcc uses fixed register combinations for dealing with 64 bit integers, and that the special edx:eax combination is addressed this way. Anyway, the next statement is the RDTSC assembler instruction (hex opcode 0F 31) with the additional information that this instruction will spill the registers eax and edx. This tells the compiler that it must not assume contents in these registers to be preserved when calls to RDTSC() are inlined. The very last statement will return the value of TSC, which has been declared to reside in registers edx:eax.

Now let's be cool and write a small application:

int main() {
   cout << RDTSC();
} 



The output of the program will be something in the lines of

37773409822

or whatever your TSC is at the moment.

Ok, that's it. I have not yet read or heard of any implementations that allow reading the TSC as straightforward as a plain C function, so I thought this would be a contibution to the community.

chris

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

 

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.