1/* Copyright (c) 2004, 2011, Oracle and/or its affiliates.
2 Copyright (c) 2009-2011 Monty Program Ab
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17
18#include "mysys_priv.h"
19#include "my_static.h"
20
21#ifdef _WIN32
22#define OFFSET_TO_EPOC 116444736000000000LL
23static ulonglong query_performance_frequency;
24typedef void (WINAPI* get_system_time_as_filetime_t)(LPFILETIME);
25static get_system_time_as_filetime_t
26 my_GetSystemTimePreciseAsFileTime= GetSystemTimeAsFileTime;
27#endif
28#ifdef HAVE_LINUX_UNISTD_H
29#include <linux/unistd.h>
30#endif
31
32/* For CYGWIN */
33#if !defined(CLOCK_THREAD_CPUTIME_ID) && defined(CLOCK_THREAD_CPUTIME)
34#define CLOCK_THREAD_CPUTIME_ID CLOCK_THREAD_CPUTIME
35#endif
36
37/*
38 return number of nanoseconds since unspecified (but always the same)
39 point in the past
40
41 NOTE:
42 Thus to get the current time we should use the system function
43 with the highest possible resolution
44
45 The value is not anchored to any specific point in time (e.g. epoch) nor
46 is it subject to resetting or drifting by way of adjtime() or settimeofday(),
47 and thus it is *NOT* appropriate for getting the current timestamp. It can be
48 used for calculating time intervals, though.
49*/
50
51ulonglong my_interval_timer()
52{
53#ifdef HAVE_CLOCK_GETTIME
54 struct timespec tp;
55 clock_gettime(CLOCK_MONOTONIC, &tp);
56 return tp.tv_sec*1000000000ULL+tp.tv_nsec;
57#elif defined(HAVE_GETHRTIME)
58 return gethrtime();
59#elif defined(_WIN32)
60 LARGE_INTEGER t_cnt;
61 if (query_performance_frequency)
62 {
63 QueryPerformanceCounter(&t_cnt);
64 return (t_cnt.QuadPart / query_performance_frequency * 1000000000ULL) +
65 ((t_cnt.QuadPart % query_performance_frequency) * 1000000000ULL /
66 query_performance_frequency);
67 }
68 else
69 {
70 ulonglong newtime;
71 my_GetSystemTimePreciseAsFileTime((FILETIME*)&newtime);
72 return newtime*100ULL;
73 }
74#else
75 /* TODO: check for other possibilities for hi-res timestamping */
76 struct timeval tv;
77 gettimeofday(&tv,NULL);
78 return tv.tv_sec*1000000000ULL+tv.tv_usec*1000ULL;
79#endif
80}
81
82
83/* Return current time in HRTIME_RESOLUTION (microseconds) since epoch */
84
85my_hrtime_t my_hrtime()
86{
87 my_hrtime_t hrtime;
88#if defined(_WIN32)
89 ulonglong newtime;
90 my_GetSystemTimePreciseAsFileTime((FILETIME*)&newtime);
91 hrtime.val= (newtime - OFFSET_TO_EPOC)/10;
92#elif defined(HAVE_CLOCK_GETTIME)
93 struct timespec tp;
94 clock_gettime(CLOCK_REALTIME, &tp);
95 hrtime.val= tp.tv_sec*1000000ULL+tp.tv_nsec/1000ULL;
96#else
97 struct timeval t;
98 /* The following loop is here because gettimeofday may fail */
99 while (gettimeofday(&t, NULL) != 0) {}
100 hrtime.val= t.tv_sec*1000000ULL + t.tv_usec;
101#endif
102 return hrtime;
103}
104
105#ifdef _WIN32
106
107/*
108 Low accuracy, "coarse" timer.
109 Has lower latency than my_hrtime(). Used in situations, where microsecond
110 precision is not needed, e.g in Windows pthread_cond_timedwait, where POSIX
111 interface needs nanoseconds, yet the underlying Windows function only
112 accepts millisecons.
113*/
114my_hrtime_t my_hrtime_coarse()
115{
116 my_hrtime_t hrtime;
117 ulonglong t;
118 GetSystemTimeAsFileTime((FILETIME*)&t);
119 hrtime.val= (t - OFFSET_TO_EPOC)/10;
120 return hrtime;
121}
122
123#endif
124
125void my_time_init()
126{
127#ifdef _WIN32
128 compile_time_assert(sizeof(LARGE_INTEGER) ==
129 sizeof(query_performance_frequency));
130 if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency) == 0)
131 query_performance_frequency= 0;
132
133 get_system_time_as_filetime_t f= (get_system_time_as_filetime_t)
134 GetProcAddress(GetModuleHandle("kernel32"),
135 "GetSystemTimePreciseAsFileTime");
136 if (f)
137 my_GetSystemTimePreciseAsFileTime= f;
138#endif
139}
140
141
142/*
143 Return cpu time in 1/10th on a microsecond (1e-7 s)
144*/
145
146ulonglong my_getcputime()
147{
148#ifdef CLOCK_THREAD_CPUTIME_ID
149 struct timespec tp;
150 if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp))
151 return 0;
152 return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100;
153#elif defined(__NR_clock_gettime)
154 struct timespec tp;
155 if (syscall(__NR_clock_gettime, CLOCK_THREAD_CPUTIME_ID, &tp))
156 return 0;
157 return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100;
158#endif /* CLOCK_THREAD_CPUTIME_ID */
159 return 0;
160}
161