Annotation of embedaddon/curl/lib/timeval.c, revision 1.1.1.1
1.1 misho 1: /***************************************************************************
2: * _ _ ____ _
3: * Project ___| | | | _ \| |
4: * / __| | | | |_) | |
5: * | (__| |_| | _ <| |___
6: * \___|\___/|_| \_\_____|
7: *
8: * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
9: *
10: * This software is licensed as described in the file COPYING, which
11: * you should have received as part of this distribution. The terms
12: * are also available at https://curl.haxx.se/docs/copyright.html.
13: *
14: * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15: * copies of the Software, and permit persons to whom the Software is
16: * furnished to do so, under the terms of the COPYING file.
17: *
18: * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19: * KIND, either express or implied.
20: *
21: ***************************************************************************/
22:
23: #include "timeval.h"
24:
25: #if defined(WIN32) && !defined(MSDOS)
26:
27: /* set in win32_init() */
28: extern LARGE_INTEGER Curl_freq;
29: extern bool Curl_isVistaOrGreater;
30:
31: /* In case of bug fix this function has a counterpart in tool_util.c */
32: struct curltime Curl_now(void)
33: {
34: struct curltime now;
35: if(Curl_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
36: LARGE_INTEGER count;
37: QueryPerformanceCounter(&count);
38: now.tv_sec = (time_t)(count.QuadPart / Curl_freq.QuadPart);
39: now.tv_usec = (int)((count.QuadPart % Curl_freq.QuadPart) * 1000000 /
40: Curl_freq.QuadPart);
41: }
42: else {
43: /* Disable /analyze warning that GetTickCount64 is preferred */
44: #if defined(_MSC_VER)
45: #pragma warning(push)
46: #pragma warning(disable:28159)
47: #endif
48: DWORD milliseconds = GetTickCount();
49: #if defined(_MSC_VER)
50: #pragma warning(pop)
51: #endif
52:
53: now.tv_sec = milliseconds / 1000;
54: now.tv_usec = (milliseconds % 1000) * 1000;
55: }
56: return now;
57: }
58:
59: #elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
60:
61: struct curltime Curl_now(void)
62: {
63: /*
64: ** clock_gettime() is granted to be increased monotonically when the
65: ** monotonic clock is queried. Time starting point is unspecified, it
66: ** could be the system start-up time, the Epoch, or something else,
67: ** in any case the time starting point does not change once that the
68: ** system has started up.
69: */
70: #ifdef HAVE_GETTIMEOFDAY
71: struct timeval now;
72: #endif
73: struct curltime cnow;
74: struct timespec tsnow;
75:
76: /*
77: ** clock_gettime() may be defined by Apple's SDK as weak symbol thus
78: ** code compiles but fails during run-time if clock_gettime() is
79: ** called on unsupported OS version.
80: */
81: #if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1)
82: bool have_clock_gettime = FALSE;
83: if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *))
84: have_clock_gettime = TRUE;
85: #endif
86:
87: if(
88: #if defined(__APPLE__) && (HAVE_BUILTIN_AVAILABLE == 1)
89: have_clock_gettime &&
90: #endif
91: (0 == clock_gettime(CLOCK_MONOTONIC, &tsnow))) {
92: cnow.tv_sec = tsnow.tv_sec;
93: cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000);
94: }
95: /*
96: ** Even when the configure process has truly detected monotonic clock
97: ** availability, it might happen that it is not actually available at
98: ** run-time. When this occurs simply fallback to other time source.
99: */
100: #ifdef HAVE_GETTIMEOFDAY
101: else {
102: (void)gettimeofday(&now, NULL);
103: cnow.tv_sec = now.tv_sec;
104: cnow.tv_usec = (unsigned int)now.tv_usec;
105: }
106: #else
107: else {
108: cnow.tv_sec = time(NULL);
109: cnow.tv_usec = 0;
110: }
111: #endif
112: return cnow;
113: }
114:
115: #elif defined(HAVE_MACH_ABSOLUTE_TIME)
116:
117: #include <stdint.h>
118: #include <mach/mach_time.h>
119:
120: struct curltime Curl_now(void)
121: {
122: /*
123: ** Monotonic timer on Mac OS is provided by mach_absolute_time(), which
124: ** returns time in Mach "absolute time units," which are platform-dependent.
125: ** To convert to nanoseconds, one must use conversion factors specified by
126: ** mach_timebase_info().
127: */
128: static mach_timebase_info_data_t timebase;
129: struct curltime cnow;
130: uint64_t usecs;
131:
132: if(0 == timebase.denom)
133: (void) mach_timebase_info(&timebase);
134:
135: usecs = mach_absolute_time();
136: usecs *= timebase.numer;
137: usecs /= timebase.denom;
138: usecs /= 1000;
139:
140: cnow.tv_sec = usecs / 1000000;
141: cnow.tv_usec = (int)(usecs % 1000000);
142:
143: return cnow;
144: }
145:
146: #elif defined(HAVE_GETTIMEOFDAY)
147:
148: struct curltime Curl_now(void)
149: {
150: /*
151: ** gettimeofday() is not granted to be increased monotonically, due to
152: ** clock drifting and external source time synchronization it can jump
153: ** forward or backward in time.
154: */
155: struct timeval now;
156: struct curltime ret;
157: (void)gettimeofday(&now, NULL);
158: ret.tv_sec = now.tv_sec;
159: ret.tv_usec = (int)now.tv_usec;
160: return ret;
161: }
162:
163: #else
164:
165: struct curltime Curl_now(void)
166: {
167: /*
168: ** time() returns the value of time in seconds since the Epoch.
169: */
170: struct curltime now;
171: now.tv_sec = time(NULL);
172: now.tv_usec = 0;
173: return now;
174: }
175:
176: #endif
177:
178: /*
179: * Returns: time difference in number of milliseconds. For too large diffs it
180: * returns max value.
181: *
182: * @unittest: 1323
183: */
184: timediff_t Curl_timediff(struct curltime newer, struct curltime older)
185: {
186: timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
187: if(diff >= (TIMEDIFF_T_MAX/1000))
188: return TIMEDIFF_T_MAX;
189: else if(diff <= (TIMEDIFF_T_MIN/1000))
190: return TIMEDIFF_T_MIN;
191: return diff * 1000 + (newer.tv_usec-older.tv_usec)/1000;
192: }
193:
194: /*
195: * Returns: time difference in number of microseconds. For too large diffs it
196: * returns max value.
197: */
198: timediff_t Curl_timediff_us(struct curltime newer, struct curltime older)
199: {
200: timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
201: if(diff >= (TIMEDIFF_T_MAX/1000000))
202: return TIMEDIFF_T_MAX;
203: else if(diff <= (TIMEDIFF_T_MIN/1000000))
204: return TIMEDIFF_T_MIN;
205: return diff * 1000000 + newer.tv_usec-older.tv_usec;
206: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>