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