113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci#include "timeval.h" 2613498266Sopenharmony_ci 2713498266Sopenharmony_ci#if defined(_WIN32) 2813498266Sopenharmony_ci 2913498266Sopenharmony_ci#include <curl/curl.h> 3013498266Sopenharmony_ci#include "system_win32.h" 3113498266Sopenharmony_ci 3213498266Sopenharmony_ci/* In case of bug fix this function has a counterpart in tool_util.c */ 3313498266Sopenharmony_cistruct curltime Curl_now(void) 3413498266Sopenharmony_ci{ 3513498266Sopenharmony_ci struct curltime now; 3613498266Sopenharmony_ci if(Curl_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */ 3713498266Sopenharmony_ci LARGE_INTEGER count; 3813498266Sopenharmony_ci QueryPerformanceCounter(&count); 3913498266Sopenharmony_ci now.tv_sec = (time_t)(count.QuadPart / Curl_freq.QuadPart); 4013498266Sopenharmony_ci now.tv_usec = (int)((count.QuadPart % Curl_freq.QuadPart) * 1000000 / 4113498266Sopenharmony_ci Curl_freq.QuadPart); 4213498266Sopenharmony_ci } 4313498266Sopenharmony_ci else { 4413498266Sopenharmony_ci /* Disable /analyze warning that GetTickCount64 is preferred */ 4513498266Sopenharmony_ci#if defined(_MSC_VER) 4613498266Sopenharmony_ci#pragma warning(push) 4713498266Sopenharmony_ci#pragma warning(disable:28159) 4813498266Sopenharmony_ci#endif 4913498266Sopenharmony_ci DWORD milliseconds = GetTickCount(); 5013498266Sopenharmony_ci#if defined(_MSC_VER) 5113498266Sopenharmony_ci#pragma warning(pop) 5213498266Sopenharmony_ci#endif 5313498266Sopenharmony_ci 5413498266Sopenharmony_ci now.tv_sec = milliseconds / 1000; 5513498266Sopenharmony_ci now.tv_usec = (milliseconds % 1000) * 1000; 5613498266Sopenharmony_ci } 5713498266Sopenharmony_ci return now; 5813498266Sopenharmony_ci} 5913498266Sopenharmony_ci 6013498266Sopenharmony_ci#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) || \ 6113498266Sopenharmony_ci defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW) 6213498266Sopenharmony_ci 6313498266Sopenharmony_cistruct curltime Curl_now(void) 6413498266Sopenharmony_ci{ 6513498266Sopenharmony_ci /* 6613498266Sopenharmony_ci ** clock_gettime() is granted to be increased monotonically when the 6713498266Sopenharmony_ci ** monotonic clock is queried. Time starting point is unspecified, it 6813498266Sopenharmony_ci ** could be the system start-up time, the Epoch, or something else, 6913498266Sopenharmony_ci ** in any case the time starting point does not change once that the 7013498266Sopenharmony_ci ** system has started up. 7113498266Sopenharmony_ci */ 7213498266Sopenharmony_ci#ifdef HAVE_GETTIMEOFDAY 7313498266Sopenharmony_ci struct timeval now; 7413498266Sopenharmony_ci#endif 7513498266Sopenharmony_ci struct curltime cnow; 7613498266Sopenharmony_ci struct timespec tsnow; 7713498266Sopenharmony_ci 7813498266Sopenharmony_ci /* 7913498266Sopenharmony_ci ** clock_gettime() may be defined by Apple's SDK as weak symbol thus 8013498266Sopenharmony_ci ** code compiles but fails during run-time if clock_gettime() is 8113498266Sopenharmony_ci ** called on unsupported OS version. 8213498266Sopenharmony_ci */ 8313498266Sopenharmony_ci#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ 8413498266Sopenharmony_ci (HAVE_BUILTIN_AVAILABLE == 1) 8513498266Sopenharmony_ci bool have_clock_gettime = FALSE; 8613498266Sopenharmony_ci if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) 8713498266Sopenharmony_ci have_clock_gettime = TRUE; 8813498266Sopenharmony_ci#endif 8913498266Sopenharmony_ci 9013498266Sopenharmony_ci#ifdef HAVE_CLOCK_GETTIME_MONOTONIC_RAW 9113498266Sopenharmony_ci if( 9213498266Sopenharmony_ci#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ 9313498266Sopenharmony_ci (HAVE_BUILTIN_AVAILABLE == 1) 9413498266Sopenharmony_ci have_clock_gettime && 9513498266Sopenharmony_ci#endif 9613498266Sopenharmony_ci (0 == clock_gettime(CLOCK_MONOTONIC_RAW, &tsnow))) { 9713498266Sopenharmony_ci cnow.tv_sec = tsnow.tv_sec; 9813498266Sopenharmony_ci cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000); 9913498266Sopenharmony_ci } 10013498266Sopenharmony_ci else 10113498266Sopenharmony_ci#endif 10213498266Sopenharmony_ci 10313498266Sopenharmony_ci if( 10413498266Sopenharmony_ci#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ 10513498266Sopenharmony_ci (HAVE_BUILTIN_AVAILABLE == 1) 10613498266Sopenharmony_ci have_clock_gettime && 10713498266Sopenharmony_ci#endif 10813498266Sopenharmony_ci (0 == clock_gettime(CLOCK_MONOTONIC, &tsnow))) { 10913498266Sopenharmony_ci cnow.tv_sec = tsnow.tv_sec; 11013498266Sopenharmony_ci cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000); 11113498266Sopenharmony_ci } 11213498266Sopenharmony_ci /* 11313498266Sopenharmony_ci ** Even when the configure process has truly detected monotonic clock 11413498266Sopenharmony_ci ** availability, it might happen that it is not actually available at 11513498266Sopenharmony_ci ** run-time. When this occurs simply fallback to other time source. 11613498266Sopenharmony_ci */ 11713498266Sopenharmony_ci#ifdef HAVE_GETTIMEOFDAY 11813498266Sopenharmony_ci else { 11913498266Sopenharmony_ci (void)gettimeofday(&now, NULL); 12013498266Sopenharmony_ci cnow.tv_sec = now.tv_sec; 12113498266Sopenharmony_ci cnow.tv_usec = (unsigned int)now.tv_usec; 12213498266Sopenharmony_ci } 12313498266Sopenharmony_ci#else 12413498266Sopenharmony_ci else { 12513498266Sopenharmony_ci cnow.tv_sec = time(NULL); 12613498266Sopenharmony_ci cnow.tv_usec = 0; 12713498266Sopenharmony_ci } 12813498266Sopenharmony_ci#endif 12913498266Sopenharmony_ci return cnow; 13013498266Sopenharmony_ci} 13113498266Sopenharmony_ci 13213498266Sopenharmony_ci#elif defined(HAVE_MACH_ABSOLUTE_TIME) 13313498266Sopenharmony_ci 13413498266Sopenharmony_ci#include <stdint.h> 13513498266Sopenharmony_ci#include <mach/mach_time.h> 13613498266Sopenharmony_ci 13713498266Sopenharmony_cistruct curltime Curl_now(void) 13813498266Sopenharmony_ci{ 13913498266Sopenharmony_ci /* 14013498266Sopenharmony_ci ** Monotonic timer on Mac OS is provided by mach_absolute_time(), which 14113498266Sopenharmony_ci ** returns time in Mach "absolute time units," which are platform-dependent. 14213498266Sopenharmony_ci ** To convert to nanoseconds, one must use conversion factors specified by 14313498266Sopenharmony_ci ** mach_timebase_info(). 14413498266Sopenharmony_ci */ 14513498266Sopenharmony_ci static mach_timebase_info_data_t timebase; 14613498266Sopenharmony_ci struct curltime cnow; 14713498266Sopenharmony_ci uint64_t usecs; 14813498266Sopenharmony_ci 14913498266Sopenharmony_ci if(0 == timebase.denom) 15013498266Sopenharmony_ci (void) mach_timebase_info(&timebase); 15113498266Sopenharmony_ci 15213498266Sopenharmony_ci usecs = mach_absolute_time(); 15313498266Sopenharmony_ci usecs *= timebase.numer; 15413498266Sopenharmony_ci usecs /= timebase.denom; 15513498266Sopenharmony_ci usecs /= 1000; 15613498266Sopenharmony_ci 15713498266Sopenharmony_ci cnow.tv_sec = usecs / 1000000; 15813498266Sopenharmony_ci cnow.tv_usec = (int)(usecs % 1000000); 15913498266Sopenharmony_ci 16013498266Sopenharmony_ci return cnow; 16113498266Sopenharmony_ci} 16213498266Sopenharmony_ci 16313498266Sopenharmony_ci#elif defined(HAVE_GETTIMEOFDAY) 16413498266Sopenharmony_ci 16513498266Sopenharmony_cistruct curltime Curl_now(void) 16613498266Sopenharmony_ci{ 16713498266Sopenharmony_ci /* 16813498266Sopenharmony_ci ** gettimeofday() is not granted to be increased monotonically, due to 16913498266Sopenharmony_ci ** clock drifting and external source time synchronization it can jump 17013498266Sopenharmony_ci ** forward or backward in time. 17113498266Sopenharmony_ci */ 17213498266Sopenharmony_ci struct timeval now; 17313498266Sopenharmony_ci struct curltime ret; 17413498266Sopenharmony_ci (void)gettimeofday(&now, NULL); 17513498266Sopenharmony_ci ret.tv_sec = now.tv_sec; 17613498266Sopenharmony_ci ret.tv_usec = (int)now.tv_usec; 17713498266Sopenharmony_ci return ret; 17813498266Sopenharmony_ci} 17913498266Sopenharmony_ci 18013498266Sopenharmony_ci#else 18113498266Sopenharmony_ci 18213498266Sopenharmony_cistruct curltime Curl_now(void) 18313498266Sopenharmony_ci{ 18413498266Sopenharmony_ci /* 18513498266Sopenharmony_ci ** time() returns the value of time in seconds since the Epoch. 18613498266Sopenharmony_ci */ 18713498266Sopenharmony_ci struct curltime now; 18813498266Sopenharmony_ci now.tv_sec = time(NULL); 18913498266Sopenharmony_ci now.tv_usec = 0; 19013498266Sopenharmony_ci return now; 19113498266Sopenharmony_ci} 19213498266Sopenharmony_ci 19313498266Sopenharmony_ci#endif 19413498266Sopenharmony_ci 19513498266Sopenharmony_ci/* 19613498266Sopenharmony_ci * Returns: time difference in number of milliseconds. For too large diffs it 19713498266Sopenharmony_ci * returns max value. 19813498266Sopenharmony_ci * 19913498266Sopenharmony_ci * @unittest: 1323 20013498266Sopenharmony_ci */ 20113498266Sopenharmony_citimediff_t Curl_timediff(struct curltime newer, struct curltime older) 20213498266Sopenharmony_ci{ 20313498266Sopenharmony_ci timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec; 20413498266Sopenharmony_ci if(diff >= (TIMEDIFF_T_MAX/1000)) 20513498266Sopenharmony_ci return TIMEDIFF_T_MAX; 20613498266Sopenharmony_ci else if(diff <= (TIMEDIFF_T_MIN/1000)) 20713498266Sopenharmony_ci return TIMEDIFF_T_MIN; 20813498266Sopenharmony_ci return diff * 1000 + (newer.tv_usec-older.tv_usec)/1000; 20913498266Sopenharmony_ci} 21013498266Sopenharmony_ci 21113498266Sopenharmony_ci/* 21213498266Sopenharmony_ci * Returns: time difference in number of milliseconds, rounded up. 21313498266Sopenharmony_ci * For too large diffs it returns max value. 21413498266Sopenharmony_ci */ 21513498266Sopenharmony_citimediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older) 21613498266Sopenharmony_ci{ 21713498266Sopenharmony_ci timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec; 21813498266Sopenharmony_ci if(diff >= (TIMEDIFF_T_MAX/1000)) 21913498266Sopenharmony_ci return TIMEDIFF_T_MAX; 22013498266Sopenharmony_ci else if(diff <= (TIMEDIFF_T_MIN/1000)) 22113498266Sopenharmony_ci return TIMEDIFF_T_MIN; 22213498266Sopenharmony_ci return diff * 1000 + (newer.tv_usec - older.tv_usec + 999)/1000; 22313498266Sopenharmony_ci} 22413498266Sopenharmony_ci 22513498266Sopenharmony_ci/* 22613498266Sopenharmony_ci * Returns: time difference in number of microseconds. For too large diffs it 22713498266Sopenharmony_ci * returns max value. 22813498266Sopenharmony_ci */ 22913498266Sopenharmony_citimediff_t Curl_timediff_us(struct curltime newer, struct curltime older) 23013498266Sopenharmony_ci{ 23113498266Sopenharmony_ci timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec; 23213498266Sopenharmony_ci if(diff >= (TIMEDIFF_T_MAX/1000000)) 23313498266Sopenharmony_ci return TIMEDIFF_T_MAX; 23413498266Sopenharmony_ci else if(diff <= (TIMEDIFF_T_MIN/1000000)) 23513498266Sopenharmony_ci return TIMEDIFF_T_MIN; 23613498266Sopenharmony_ci return diff * 1000000 + newer.tv_usec-older.tv_usec; 23713498266Sopenharmony_ci} 238