FARGOS/VISTA Object Management Environment Core  ..
FARGOS/VISTA Object Management Environment Core Table of Contents
tick_time.h
Go to the documentation of this file.
1 #ifndef _TICK_TIME_H_
2 #define _TICK_TIME_H_ "$Id: tick_time.h 421 2020-07-14 17:11:44Z fargos $"
4 
7 
8 #include <stdint.h>
9 #if defined(_MSC_VER) || (__MINGW32__ == 1) /* Microsoft Visual Studio */
10 #include <intrin.h>
11 #endif
12 
13 #ifndef _WIN32
14 #include <sys/time.h>
15 #else
16 #ifndef CLOCK_REALTIME
17 #if (_MSC_VER >= 1900) || (__MINGW32__ == 1)
18 #include <time.h>
19 #else
20 struct timespec {
21  time_t tv_sec;
22  long tv_nsec;
23 };
24 #endif
25 
26 #define CLOCK_REALTIME 1
27 #endif
28 #endif
29 
42 #define USE_INTERPOLATED_TIME 1
43 
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47 
48 
49 #ifdef _MSC_VER
50 #define get_CPU_ticks() __rdtsc()
51 #else /* not Microsoft Visual Studio */
52 
53 #if defined(__x86_64__) || defined(__i386__)
54 
55 /* this is an x86-64-specific implementation for g++. */
56 #define rdtscll(val) do { \
57  uint32_t __a,__d; \
58  __asm__ __volatile__("rdtsc" : "=a" (__a), "=d" (__d)); \
59  (val) = ((uint64_t)__a) | (((uint64_t)__d)<<32); \
60 } while(0)
61 // end x86_64 or i386
62 #elif defined(__sparc__)
63 # ifndef __arch64__
64 inline uint64_t readSPARCtick()
65 {
66  unsigned long long result;
67 
68  result = gethrtime();
69  return (result);
70 }
71 # else
72 // 64-bit SPARC v9
73 inline uint64_t readSPARCtick()
74 {
75  unsigned long long result;
76 
77  __asm__ __volatile__(
78  "rd %%tick, %0"
79  : "=r"(result));
80  return (result);
81 }
82 # endif // __arch64__
83 // end __sparc__
84 #elif defined(__s390__) // Covers both s390 and s390x.
85 inline uint64_t readS390timestamp()
86 {
87  // Return the CPU clock.
88  uint64_t tsc;
89  asm("stck %0" : "=Q"(tsc) : : "cc");
90  return (tsc);
91 }
92 #elif defined(__aarch64__) // 64-bit ARM
93 inline uint64_t readAARCH64timer()
94 {
95  // System timer of ARMv8 runs at a different frequency than the CPU's.
96  // The frequency is fixed, typically in the range 1-50MHz. It can be
97  // read at CNTFRQ special register. We assume the OS has set up
98  // the virtual timer properly.
99  int64_t virtual_timer_value;
100  asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
101  return (virtual_timer_value);
102 }
103 #elif defined(__ARM_ARCH)
104  // V6 is the earliest arch that has a standard cyclecount
105  // Native Client validator doesn't allow MRC instructions.
106 #if (__ARM_ARCH >= 6)
107 inline uint64_t readARMperfCounter()
108 {
109  uint32_t pmccntr;
110  uint32_t pmuseren;
111  uint32_t pmcntenset;
112  // Read the user mode perf monitor counter access permissions.
113  asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren));
114  if (pmuseren & 1) { // Allows reading perfmon counters for user mode code.
115  asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset));
116  if (pmcntenset & 0x80000000ul) { // Is it counting?
117  asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
118  // The counter is set up to count every 64th cycle
119  return static_cast<int64_t>(pmccntr) * 64; // Should optimize to << 6
120  }
121  }
122  return (0); // not supported
123 }
124 #endif /* ARM_ARCH >= 6 */
125 #elif defined(__linux__)
126 // final fall back for Linux
127 #include <linux/perf_event.h>
128 #include <asm/unistd.h>
129 #include <sys/ioctl.h>
130 // used as final fall back on Linux
131 extern int initPerfEvent();
132 extern uint64_t getCPUcyclesPerfEvent();
133 extern int perfEvent_FD;
134 #endif
135 
136 extern uint64_t get_CPU_ticks() OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3");
137 
141 inline uint64_t get_CPU_ticks()
142 {
143  uint64_t result;
144 
145 #if defined(__i386__) || defined(__x86_64__)
146  rdtscll(result);
147 #elif defined(__sparc__)
148  result = readSPARCtick();
149 #elif defined(_WIN32)
150  result = rdtsc();
151 #elif defined(__s390__)
152  result = readS390timestamp();
153 #elif defined(__aarch64__) // 64-bit ARM
154  result = readAARCH64timer();
155 #elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_8A)
156  result = readARMperfCounter();
157 #elif defined(__linux__)
158 # warning "CPU type not yet supported by OMEgetCPUticks()\n";
159  if (perfEvent_FD == -1) { // not yet initialized
160  int rc = initPerfEvent();
161  if (rc == -1) {
162  result = 0;
163  return (result);
164  }
165  }
166  result = getCPUcyclesPerfEvent();
167 #if 0
168  uint32_t r = 0;
169  asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(r));
170  result = r;
171 #endif
172 #else
173 # error "CPU type not supported by get_CPU_ticks()\n";
174  result = 0;
175 #endif
176  return (result);
177 }
178 
179 #endif /* not Microsoft Visual Studio */
180 
182 void set_tick_rate(double ticksPerNanosecond);
183 
190 void set_max_clock_sample_interval(uint64_t nanoseconds);
191 
206 uint64_t profile_clock_rate(bool setGlobalRate);
207 
208 #if __linux__ == 1
209 
223 uint64_t get_clock_rate_estimate(bool setGlobalRate);
224 #endif
225 
239 typedef int (*Clock_GetTime_InterfaceFP)(struct timespec *result, bool force);
240 
256 int interpolated_clock_gettime(struct timespec *result, bool force);
257 
261 int simulated_clock_gettime(struct timespec *result, bool force);
262 
272 void set_external_rdtsc_variable(uint64_t *rdtsc_pointer);
273 
283 
285 
286 #if USE_INTERPOLATED_TIME == 1
287 // declare first with attributes
288 extern int clock_gettime_via_tick(struct timespec *result, bool force) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3");
289 
290 inline int clock_gettime_via_tick(struct timespec *result, bool force)
291 {
292  // make indirect call to active clock routine
293  return ((*clockRoutine_function)(result, force));
294 }
295 
296 #else
297 
300 #define clock_gettime_via_tick(r,f) clock_gettime(CLOCK_REALTIME, r)
301 #endif
302 
303 
304 #ifdef __cplusplus
305 }; // end extern C scope
306 #endif
307 
309 #endif
310 /* vim: set expandtab shiftwidth=4 tabstop=4: */
clock_gettime_via_tick
int clock_gettime_via_tick(struct timespec *result, bool force) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Definition: tick_time.h:290
ClockProfileState
ClockProfileState
Definition: tick_time.cpp:214
CLOCK_NOT_PROFILED
@ CLOCK_NOT_PROFILED
Definition: tick_time.cpp:214
set_max_clock_sample_interval
void set_max_clock_sample_interval(uint64_t nanoseconds)
Set maximum number of nanoseconds between forced retrieval of time from hardware clock when clock_get...
Definition: tick_time.cpp:238
s
const char s[]
Definition: t.cpp:4
Clock_GetTime_InterfaceFP
int(* Clock_GetTime_InterfaceFP)(struct timespec *result, bool force)
Defines the interface for clock_gettime_via_tick() or equivalent.
Definition: tick_time.h:239
stdout
#define stdout
Definition: tmp.o.cpp:3117
CLOCK_REALTIME
#define CLOCK_REALTIME
Definition: tmp.o.cpp:50
stderr
#define stderr
Definition: tmp.o.cpp:3115
profile_clock_rate
uint64_t profile_clock_rate(bool setGlobalRate)
Normal initialization routine to determine tick rate of underlying hardware.
Definition: tick_time.cpp:258
CLOCK_SECOND_SAMPLE
@ CLOCK_SECOND_SAMPLE
Definition: tick_time.cpp:215
OME_ALWAYS_OPTIMIZE
#define OME_ALWAYS_OPTIMIZE(level)
Mark a function to be compiled with a specific level of optimization.
Definition: compiler_hints.h:406
first_sample_time
struct timespec first_sample_time
Definition: tick_time.cpp:222
set_tick_rate
void set_tick_rate(double ticksPerNanosecond)
Manually set CPU tick rate per nanoseconds.
Definition: tick_time.cpp:226
simulated_clock_gettime
int simulated_clock_gettime(struct timespec *result, bool force)
Alternate of interpolated_clock_gettime() that can use an external RDTSC counter.
Definition: tick_time.cpp:377
CLOCK_PROFILE_COMPLETE
@ CLOCK_PROFILE_COMPLETE
Definition: tick_time.cpp:215
last_clock_gettime
struct timespec last_clock_gettime
Definition: tick_time.cpp:224
srcID
const char srcID[]
Definition: catSym.c:17
NANOSECONDS_IN_1_SEC
#define NANOSECONDS_IN_1_SEC
Definition: tick_time.cpp:27
ENOENT
#define ENOENT
Definition: tmp.o.cpp:114
OME_EXPECT_TRUE
#define OME_EXPECT_TRUE(expr)
Annotation macro for conditional expression expected to be true.
Definition: compiler_hints.h:541
CLOCK_FIRST_SAMPLE
@ CLOCK_FIRST_SAMPLE
Definition: tick_time.cpp:214
set_external_rdtsc_variable
void set_external_rdtsc_variable(uint64_t *rdtsc_ptr)
Sets the storage location from which the current time in nanoseconds will be read.
Definition: tick_time.cpp:390
set_clock_function
Clock_GetTime_InterfaceFP set_clock_function(Clock_GetTime_InterfaceFP func)
Set clock routine implementation.
Definition: tick_time.cpp:396
OME_USED
const char srcID[] OME_USED
Definition: tick_time.cpp:24
clockRoutine_function
Clock_GetTime_InterfaceFP clockRoutine_function
Definition: tick_time.cpp:388
interpolated_clock_gettime
int interpolated_clock_gettime(struct timespec *result, bool force)
Get time with nanosecond precision using interpolation of elapsed CPU ticks.
Definition: tick_time.cpp:315
CLOCK_RATE_ESTIMATED
@ CLOCK_RATE_ESTIMATED
Definition: tick_time.cpp:215
errno
int errno
Definition: ethers.c:41
compiler_hints.h
Compiler-specific macros to provide performance-related hints.
OME_EXPECT_FALSE
#define OME_EXPECT_FALSE(expr)
Annotation macro for conditional expression expected to be false.
Definition: compiler_hints.h:540
OME_ALWAYS_INLINE
#define OME_ALWAYS_INLINE
Tell the compiler to alway inline a function, regardless of optimization level.
Definition: compiler_hints.h:364
get_CPU_ticks
uint64_t get_CPU_ticks() OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Return value of CPU tick register.
Definition: tick_time.h:141
tick_time.h
FARGOS CPU tick routines.
rdtsc
unsigned __int64 rdtsc()
Definition: IAPerf.h:101
main
int main(int argc, const char *argv[])
Definition: tick_test.cpp:5
fd
int fd
Definition: ethers.c:41
Generated: Fri Jul 31 2020 18:19:15
Support Information