quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

timeval.c (7325B)


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