FreeTDS API
Loading...
Searching...
No Matches
tsc.h
1// Support for using the TSC register on intel machines as a timing method.
2//
3// Should compile with -O to ensure inline attribute is honoured.
4//
5
6#ifndef __TSC_HDR
7#define __TSC_HDR
8
9#include <stdint.h>
10
11#define TSC_OVERHEAD_N 100000
12
13static inline void _sync_tsc(void)
14{
15 asm volatile("cpuid" : : : "%rax", "%rbx", "%rcx", "%rdx");
16}
17
18static inline uint64_t _rdtsc(void)
19{
20 unsigned a, d;
21 asm volatile("rdtsc" : "=a" (a), "=d" (d) : : "%rbx", "%rcx");
22 return ((uint64_t) a) | (((uint64_t) d) << 32);
23}
24
25static inline uint64_t _rdtscp(void)
26{
27 unsigned a, d;
28 asm volatile("rdtscp" : "=a" (a), "=d" (d) : : "%rbx", "%rcx");
29 return ((uint64_t) a) | (((uint64_t) d) << 32);
30}
31
32static inline uint64_t bench_start(void)
33{
34 // unsigned cycles_low, cycles_high;
35 // uint64_t t;
36 //
37 // asm volatile( "CPUID\n\t" // serialize
38 // "RDTSC\n\t" // read clock
39 // "mov %%edx, %0\n\t"
40 // "mov %%eax, %1\n\t"
41 // : "=r" (cycles_high), "=r" (cycles_low)
42 // :: "%rax", "%rbx", "%rcx", "%rdx" );
43 // return ((uint64_t) cycles_high << 32) | cycles_low;
44
45 _sync_tsc();
46 return _rdtsc();
47}
48
49static inline uint64_t bench_end(void)
50{
51 // unsigned cycles_low, cycles_high;
52 // uint64_t t;
53 //
54 // asm volatile( "RDTSCP\n\t" // read clock + serialize
55 // "mov %%edx, %0\n\t"
56 // "mov %%eax, %1\n\t"
57 // "CPUID\n\t" // serialze -- but outside clock region!
58 // : "=r" (cycles_high), "=r" (cycles_low)
59 // :: "%rax", "%rbx", "%rcx", "%rdx" );
60 // return ((uint64_t) cycles_high << 32) | cycles_low;
61
62 uint64_t t = _rdtscp();
63 _sync_tsc();
64 return t;
65}
66
67static uint64_t measure_tsc_overhead(void)
68{
69 uint64_t t0, t1, overhead = ~0;
70 int i;
71
72 for (i = 0; i < TSC_OVERHEAD_N; i++) {
73 t0 = bench_start();
74 asm volatile("");
75 t1 = bench_end();
76 if (t1 - t0 < overhead)
77 overhead = t1 - t0;
78 }
79
80 return overhead;
81}
82
83/*
84# TSC Frequency
85To convert from cycles to wall-clock time we need to know TSC frequency
86Frequency scaling on modern Intel chips doesn't affect the TSC.
87
88Sadly, there doesn't seem to be a good way to do this.
89
90# Intel V3B: 17.14
91That rate may be set by the maximum core-clock to bus-clock ratio of the
92processor or may be set by the maximum resolved frequency at which the
93processor is booted. The maximum resolved frequency may differ from the
94processor base frequency, see Section 18.15.5 for more detail. On certain
95processors, the TSC frequency may not be the same as the frequency in the brand
96string.
97
98# Linux Source
99http://lxr.free-electrons.com/source/arch/x86/kernel/tsc.c?v=2.6.31#L399
100
101Linux runs a calibration phase where it uses some hardware timers and checks
102how many TSC cycles occur in 50ms.
103*/
104#define TSC_FREQ_MHZ 3500
105
106static inline uint64_t cycles_to_ns(uint64_t cycles)
107{
108 // XXX: This is not safe! We don't have a good cross-platform way to
109 // determine the TSC frequency for some strange reason.
110 return cycles * 1000 / TSC_FREQ_MHZ;
111}
112
113#endif /* __TSC_HDR */