1 | /*************************************************************************** |
2 | * _ _ ____ _ |
3 | * Project ___| | | | _ \| | |
4 | * / __| | | | |_) | | |
5 | * | (__| |_| | _ <| |___ |
6 | * \___|\___/|_| \_\_____| |
7 | * |
8 | * Copyright (C) 1998 - 2019, 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 | #include "tool_setup.h" |
23 | |
24 | #include "tool_util.h" |
25 | |
26 | #include "memdebug.h" /* keep this as LAST include */ |
27 | |
28 | #if defined(WIN32) && !defined(MSDOS) |
29 | |
30 | struct timeval tvnow(void) |
31 | { |
32 | /* |
33 | ** GetTickCount() is available on _all_ Windows versions from W95 up |
34 | ** to nowadays. Returns milliseconds elapsed since last system boot, |
35 | ** increases monotonically and wraps once 49.7 days have elapsed. |
36 | ** |
37 | ** GetTickCount64() is available on Windows version from Windows Vista |
38 | ** and Windows Server 2008 up to nowadays. The resolution of the |
39 | ** function is limited to the resolution of the system timer, which |
40 | ** is typically in the range of 10 milliseconds to 16 milliseconds. |
41 | */ |
42 | struct timeval now; |
43 | #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) && \ |
44 | (!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR)) |
45 | ULONGLONG milliseconds = GetTickCount64(); |
46 | #else |
47 | DWORD milliseconds = GetTickCount(); |
48 | #endif |
49 | now.tv_sec = (long)(milliseconds / 1000); |
50 | now.tv_usec = (long)((milliseconds % 1000) * 1000); |
51 | return now; |
52 | } |
53 | |
54 | #elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) |
55 | |
56 | struct timeval tvnow(void) |
57 | { |
58 | /* |
59 | ** clock_gettime() is granted to be increased monotonically when the |
60 | ** monotonic clock is queried. Time starting point is unspecified, it |
61 | ** could be the system start-up time, the Epoch, or something else, |
62 | ** in any case the time starting point does not change once that the |
63 | ** system has started up. |
64 | */ |
65 | struct timeval now; |
66 | struct timespec tsnow; |
67 | if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) { |
68 | now.tv_sec = tsnow.tv_sec; |
69 | now.tv_usec = tsnow.tv_nsec / 1000; |
70 | } |
71 | /* |
72 | ** Even when the configure process has truly detected monotonic clock |
73 | ** availability, it might happen that it is not actually available at |
74 | ** run-time. When this occurs simply fallback to other time source. |
75 | */ |
76 | #ifdef HAVE_GETTIMEOFDAY |
77 | else |
78 | (void)gettimeofday(&now, NULL); |
79 | #else |
80 | else { |
81 | now.tv_sec = (long)time(NULL); |
82 | now.tv_usec = 0; |
83 | } |
84 | #endif |
85 | return now; |
86 | } |
87 | |
88 | #elif defined(HAVE_GETTIMEOFDAY) |
89 | |
90 | struct timeval tvnow(void) |
91 | { |
92 | /* |
93 | ** gettimeofday() is not granted to be increased monotonically, due to |
94 | ** clock drifting and external source time synchronization it can jump |
95 | ** forward or backward in time. |
96 | */ |
97 | struct timeval now; |
98 | (void)gettimeofday(&now, NULL); |
99 | return now; |
100 | } |
101 | |
102 | #else |
103 | |
104 | struct timeval tvnow(void) |
105 | { |
106 | /* |
107 | ** time() returns the value of time in seconds since the Epoch. |
108 | */ |
109 | struct timeval now; |
110 | now.tv_sec = (long)time(NULL); |
111 | now.tv_usec = 0; |
112 | return now; |
113 | } |
114 | |
115 | #endif |
116 | |
117 | /* |
118 | * Make sure that the first argument is the more recent time, as otherwise |
119 | * we'll get a weird negative time-diff back... |
120 | * |
121 | * Returns: the time difference in number of milliseconds. |
122 | */ |
123 | long tvdiff(struct timeval newer, struct timeval older) |
124 | { |
125 | return (long)(newer.tv_sec-older.tv_sec)*1000+ |
126 | (long)(newer.tv_usec-older.tv_usec)/1000; |
127 | } |
128 | |