1 #ifndef KMP_STATS_TIMING_H
2 #define KMP_STATS_TIMING_H
3 
4 /** @file kmp_stats_timing.h
5  * Access to real time clock and timers.
6  */
7 
8 
9 //===----------------------------------------------------------------------===//
10 //
11 //                     The LLVM Compiler Infrastructure
12 //
13 // This file is dual licensed under the MIT and the University of Illinois Open
14 // Source Licenses. See LICENSE.txt for details.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 
19 
20 #include <stdint.h>
21 #include <string>
22 #include <limits>
23 #include "kmp_os.h"
24 #if KMP_HAVE_X86INTRIN_H
25 # include <x86intrin.h>
26 #endif
27 
28 class tsc_tick_count {
29   private:
30     int64_t my_count;
31 
32   public:
33     class tsc_interval_t {
34         int64_t value;
35         explicit tsc_interval_t(int64_t _value) : value(_value) {}
36      public:
37         tsc_interval_t() : value(0) {}; // Construct 0 time duration
38 #if KMP_HAVE_TICK_TIME
39         double seconds() const; // Return the length of a time interval in seconds
40 #endif
41         double ticks() const { return double(value); }
42         int64_t getValue() const { return value; }
43         tsc_interval_t& operator=(int64_t nvalue) { value = nvalue; return *this; }
44 
45         friend class tsc_tick_count;
46 
47         friend tsc_interval_t operator-(const tsc_tick_count& t1,
48                                         const tsc_tick_count& t0);
49         friend tsc_interval_t operator-(const tsc_tick_count::tsc_interval_t& i1,
50                                         const tsc_tick_count::tsc_interval_t& i0);
51         friend tsc_interval_t& operator+=(tsc_tick_count::tsc_interval_t& i1,
52                                          const tsc_tick_count::tsc_interval_t& i0);
53     };
54 
55 #if KMP_HAVE___BUILTIN_READCYCLECOUNTER
56     tsc_tick_count() : my_count(static_cast<int64_t>(__builtin_readcyclecounter())) {}
57 #elif KMP_HAVE___RDTSC
58     tsc_tick_count() : my_count(static_cast<int64_t>(__rdtsc())) {};
59 #else
60 # error Must have high resolution timer defined
61 #endif
62     tsc_tick_count(int64_t value) : my_count(value) {};
63     int64_t getValue() const { return my_count; }
64     tsc_tick_count later (tsc_tick_count const other) const {
65         return my_count > other.my_count ? (*this) : other;
66     }
67     tsc_tick_count earlier(tsc_tick_count const other) const {
68         return my_count < other.my_count ? (*this) : other;
69     }
70 #if KMP_HAVE_TICK_TIME
71     static double tick_time(); // returns seconds per cycle (period) of clock
72 #endif
73     static tsc_tick_count now() { return tsc_tick_count(); } // returns the rdtsc register value
74     friend tsc_tick_count::tsc_interval_t operator-(const tsc_tick_count& t1, const tsc_tick_count& t0);
75 };
76 
77 inline tsc_tick_count::tsc_interval_t operator-(const tsc_tick_count& t1, const tsc_tick_count& t0)
78 {
79     return tsc_tick_count::tsc_interval_t( t1.my_count-t0.my_count );
80 }
81 
82 inline tsc_tick_count::tsc_interval_t operator-(const tsc_tick_count::tsc_interval_t& i1, const tsc_tick_count::tsc_interval_t& i0)
83 {
84     return tsc_tick_count::tsc_interval_t( i1.value-i0.value );
85 }
86 
87 inline tsc_tick_count::tsc_interval_t& operator+=(tsc_tick_count::tsc_interval_t& i1, const tsc_tick_count::tsc_interval_t& i0)
88 {
89     i1.value += i0.value;
90     return i1;
91 }
92 
93 #if KMP_HAVE_TICK_TIME
94 inline double tsc_tick_count::tsc_interval_t::seconds() const
95 {
96     return value*tick_time();
97 }
98 #endif
99 
100 extern std::string formatSI(double interval, int width, char unit);
101 
102 inline std::string formatSeconds(double interval, int width)
103 {
104     return formatSI(interval, width, 'S');
105 }
106 
107 inline std::string formatTicks(double interval, int width)
108 {
109     return formatSI(interval, width, 'T');
110 }
111 
112 #endif // KMP_STATS_TIMING_H
113