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 |
23 | static ulonglong query_performance_frequency; |
24 | typedef void (WINAPI* get_system_time_as_filetime_t)(LPFILETIME); |
25 | static 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 | |
51 | ulonglong 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 | |
85 | my_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 | */ |
114 | my_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 | |
125 | void 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 | |
146 | ulonglong 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 | |