static inline u64 rdtsc() {
u32 lo, hi;
__asm__ __volatile__ (
"rdtsc" : "=a" (lo), "=d" (hi)
);
return ((u64)hi << 32) | lo;
}
The function you've provided is a small, but quite powerful piece of code used for performance measurement and optimization in low-level system programming. It's written in C with inline assembly, targeting x86 processors. This function retrieves the current value of the processor's Time Stamp Counter (TSC). Let's break down its components and functionality in detail:
- Name:
rdtsc
- Return type:
u64
(unsigned 64-bit integer) - Purpose: Retrieves the current value of the processor's Time Stamp Counter (TSC).
-
static inline
:static
: This keyword limits the visibility of the function to the file in which it's declared. It won't be accessible or visible to other files during linking.inline
: This suggests to the compiler that it should attempt to embed the function's code into the code of its caller, to avoid the performance penalty of a function call. It's a hint, and compilers may ignore it, especially if the function is too complex.
-
u64
:- This is a type alias, typically representing an unsigned 64-bit integer. It's used here to make sure the function can return the full 64-bit value of the TSC.
-
Local Variables (
u32 lo, hi
):u32
: Type alias for an unsigned 32-bit integer.lo, hi
: These variables are used to store the lower and higher 32 bits of the 64-bit TSC value, respectively.
-
Inline Assembly (
__asm__ __volatile__
):__asm__
: This keyword is used to integrate assembly code within C/C++ code.__volatile__
: This keyword tells the compiler not to optimize this assembly code away, even if it appears that the code is not doing anything useful (compilers can be very aggressive in optimizing, sometimes to the detriment of carefully crafted low-level functionalities).
-
Assembly Instruction (
"rdtsc"
):rdtsc
: This is the assembly instruction itself. It stands for 'Read Time-Stamp Counter'. It reads the processor's time-stamp counter and stores the result into two registers: EDX:EAX. The EDX register receives the high 32 bits, and the EAX register receives the low 32 bits.
-
Output Operands (
"=a" (lo), "=d" (hi)
):- This part of the assembly syntax specifies where the results of the assembly code should be stored.
"=a" (lo)
: This means that the value in the EAX register (used for the lower 32 bits of the TSC) should be stored in thelo
variable."=d" (hi)
: This means that the value in the EDX register (used for the higher 32 bits of the TSC) should be stored in thehi
variable.
-
Combining the High and Low Parts:
return ((u64)hi << 32) | lo;
: This line combines the high and low parts of the TSC into a single 64-bit value.((u64)hi << 32)
: This shifts thehi
value to the left by 32 bits, making room for thelo
value.| lo
: This uses the bitwise OR operator to combine thehi
andlo
values.
The TSC is a 64-bit register present in most x86 processors. It counts the number of cycles since reset. Reading this counter is extremely fast and has minimal overhead, making it highly valuable for performance monitoring and benchmarking, where precise measurements are crucial. However, the actual rate at which the TSC increments is processor-specific and can vary with power saving measures, so careful calibration and understanding of the specific processor behavior are required.
In summary, this function is a compact and efficient piece of code for accessing a high-resolution, low-overhead timing mechanism in x86 processors, which is particularly valuable in performance-critical and low-level system monitoring tasks.