Coverage Report

Created: 2024-05-04 12:45

/proc/self/cwd/external/curl/lib/timeval.c
Line
Count
Source (jump to first uncovered line)
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) 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.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
 * SPDX-License-Identifier: curl
22
 *
23
 ***************************************************************************/
24
25
#include "timeval.h"
26
27
#if defined(WIN32) && !defined(MSDOS)
28
29
/* set in win32_init() */
30
extern LARGE_INTEGER Curl_freq;
31
extern bool Curl_isVistaOrGreater;
32
33
/* In case of bug fix this function has a counterpart in tool_util.c */
34
struct curltime Curl_now(void)
35
{
36
  struct curltime now;
37
  if(Curl_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
38
    LARGE_INTEGER count;
39
    QueryPerformanceCounter(&count);
40
    now.tv_sec = (time_t)(count.QuadPart / Curl_freq.QuadPart);
41
    now.tv_usec = (int)((count.QuadPart % Curl_freq.QuadPart) * 1000000 /
42
                        Curl_freq.QuadPart);
43
  }
44
  else {
45
    /* Disable /analyze warning that GetTickCount64 is preferred  */
46
#if defined(_MSC_VER)
47
#pragma warning(push)
48
#pragma warning(disable:28159)
49
#endif
50
    DWORD milliseconds = GetTickCount();
51
#if defined(_MSC_VER)
52
#pragma warning(pop)
53
#endif
54
55
    now.tv_sec = milliseconds / 1000;
56
    now.tv_usec = (milliseconds % 1000) * 1000;
57
  }
58
  return now;
59
}
60
61
#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) ||  \
62
  defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
63
64
struct curltime Curl_now(void)
65
0
{
66
  /*
67
  ** clock_gettime() is granted to be increased monotonically when the
68
  ** monotonic clock is queried. Time starting point is unspecified, it
69
  ** could be the system start-up time, the Epoch, or something else,
70
  ** in any case the time starting point does not change once that the
71
  ** system has started up.
72
  */
73
0
#ifdef HAVE_GETTIMEOFDAY
74
0
  struct timeval now;
75
0
#endif
76
0
  struct curltime cnow;
77
0
  struct timespec tsnow;
78
79
  /*
80
  ** clock_gettime() may be defined by Apple's SDK as weak symbol thus
81
  ** code compiles but fails during run-time if clock_gettime() is
82
  ** called on unsupported OS version.
83
  */
84
#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \
85
        (HAVE_BUILTIN_AVAILABLE == 1)
86
  bool have_clock_gettime = FALSE;
87
  if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *))
88
    have_clock_gettime = TRUE;
89
#endif
90
91
#ifdef HAVE_CLOCK_GETTIME_MONOTONIC_RAW
92
  if(
93
#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) &&    \
94
        (HAVE_BUILTIN_AVAILABLE == 1)
95
    have_clock_gettime &&
96
#endif
97
    (0 == clock_gettime(CLOCK_MONOTONIC_RAW, &tsnow))) {
98
    cnow.tv_sec = tsnow.tv_sec;
99
    cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000);
100
  }
101
  else
102
#endif
103
104
0
  if(
105
#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \
106
        (HAVE_BUILTIN_AVAILABLE == 1)
107
    have_clock_gettime &&
108
#endif
109
0
    (0 == clock_gettime(CLOCK_MONOTONIC, &tsnow))) {
110
0
    cnow.tv_sec = tsnow.tv_sec;
111
0
    cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000);
112
0
  }
113
  /*
114
  ** Even when the configure process has truly detected monotonic clock
115
  ** availability, it might happen that it is not actually available at
116
  ** run-time. When this occurs simply fallback to other time source.
117
  */
118
0
#ifdef HAVE_GETTIMEOFDAY
119
0
  else {
120
0
    (void)gettimeofday(&now, NULL);
121
0
    cnow.tv_sec = now.tv_sec;
122
0
    cnow.tv_usec = (unsigned int)now.tv_usec;
123
0
  }
124
#else
125
  else {
126
    cnow.tv_sec = time(NULL);
127
    cnow.tv_usec = 0;
128
  }
129
#endif
130
0
  return cnow;
131
0
}
132
133
#elif defined(HAVE_MACH_ABSOLUTE_TIME)
134
135
#include <stdint.h>
136
#include <mach/mach_time.h>
137
138
struct curltime Curl_now(void)
139
{
140
  /*
141
  ** Monotonic timer on Mac OS is provided by mach_absolute_time(), which
142
  ** returns time in Mach "absolute time units," which are platform-dependent.
143
  ** To convert to nanoseconds, one must use conversion factors specified by
144
  ** mach_timebase_info().
145
  */
146
  static mach_timebase_info_data_t timebase;
147
  struct curltime cnow;
148
  uint64_t usecs;
149
150
  if(0 == timebase.denom)
151
    (void) mach_timebase_info(&timebase);
152
153
  usecs = mach_absolute_time();
154
  usecs *= timebase.numer;
155
  usecs /= timebase.denom;
156
  usecs /= 1000;
157
158
  cnow.tv_sec = usecs / 1000000;
159
  cnow.tv_usec = (int)(usecs % 1000000);
160
161
  return cnow;
162
}
163
164
#elif defined(HAVE_GETTIMEOFDAY)
165
166
struct curltime Curl_now(void)
167
{
168
  /*
169
  ** gettimeofday() is not granted to be increased monotonically, due to
170
  ** clock drifting and external source time synchronization it can jump
171
  ** forward or backward in time.
172
  */
173
  struct timeval now;
174
  struct curltime ret;
175
  (void)gettimeofday(&now, NULL);
176
  ret.tv_sec = now.tv_sec;
177
  ret.tv_usec = (int)now.tv_usec;
178
  return ret;
179
}
180
181
#else
182
183
struct curltime Curl_now(void)
184
{
185
  /*
186
  ** time() returns the value of time in seconds since the Epoch.
187
  */
188
  struct curltime now;
189
  now.tv_sec = time(NULL);
190
  now.tv_usec = 0;
191
  return now;
192
}
193
194
#endif
195
196
/*
197
 * Returns: time difference in number of milliseconds. For too large diffs it
198
 * returns max value.
199
 *
200
 * @unittest: 1323
201
 */
202
timediff_t Curl_timediff(struct curltime newer, struct curltime older)
203
0
{
204
0
  timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
205
0
  if(diff >= (TIMEDIFF_T_MAX/1000))
206
0
    return TIMEDIFF_T_MAX;
207
0
  else if(diff <= (TIMEDIFF_T_MIN/1000))
208
0
    return TIMEDIFF_T_MIN;
209
0
  return diff * 1000 + (newer.tv_usec-older.tv_usec)/1000;
210
0
}
211
212
/*
213
 * Returns: time difference in number of milliseconds, rounded up.
214
 * For too large diffs it returns max value.
215
 */
216
timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older)
217
0
{
218
0
  timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
219
0
  if(diff >= (TIMEDIFF_T_MAX/1000))
220
0
    return TIMEDIFF_T_MAX;
221
0
  else if(diff <= (TIMEDIFF_T_MIN/1000))
222
0
    return TIMEDIFF_T_MIN;
223
0
  return diff * 1000 + (newer.tv_usec - older.tv_usec + 999)/1000;
224
0
}
225
226
/*
227
 * Returns: time difference in number of microseconds. For too large diffs it
228
 * returns max value.
229
 */
230
timediff_t Curl_timediff_us(struct curltime newer, struct curltime older)
231
0
{
232
0
  timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
233
0
  if(diff >= (TIMEDIFF_T_MAX/1000000))
234
0
    return TIMEDIFF_T_MAX;
235
0
  else if(diff <= (TIMEDIFF_T_MIN/1000000))
236
0
    return TIMEDIFF_T_MIN;
237
0
  return diff * 1000000 + newer.tv_usec-older.tv_usec;
238
0
}