Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) 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 struct timeval curlx_tvnow(void)
     28 {
     29   /*
     30   ** GetTickCount() is available on _all_ Windows versions from W95 up
     31   ** to nowadays. Returns milliseconds elapsed since last system boot,
     32   ** increases monotonically and wraps once 49.7 days have elapsed.
     33   */
     34   struct timeval now;
     35 #if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
     36     (_WIN32_WINNT < _WIN32_WINNT_VISTA)
     37   DWORD milliseconds = GetTickCount();
     38   now.tv_sec = milliseconds / 1000;
     39   now.tv_usec = (milliseconds % 1000) * 1000;
     40 #else
     41   ULONGLONG milliseconds = GetTickCount64();
     42   now.tv_sec = (long) (milliseconds / 1000);
     43   now.tv_usec = (long) (milliseconds % 1000) * 1000;
     44 #endif
     45 
     46   return now;
     47 }
     48 
     49 #elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
     50 
     51 struct timeval curlx_tvnow(void)
     52 {
     53   /*
     54   ** clock_gettime() is granted to be increased monotonically when the
     55   ** monotonic clock is queried. Time starting point is unspecified, it
     56   ** could be the system start-up time, the Epoch, or something else,
     57   ** in any case the time starting point does not change once that the
     58   ** system has started up.
     59   */
     60   struct timeval now;
     61   struct timespec tsnow;
     62   if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
     63     now.tv_sec = tsnow.tv_sec;
     64     now.tv_usec = tsnow.tv_nsec / 1000;
     65   }
     66   /*
     67   ** Even when the configure process has truly detected monotonic clock
     68   ** availability, it might happen that it is not actually available at
     69   ** run-time. When this occurs simply fallback to other time source.
     70   */
     71 #ifdef HAVE_GETTIMEOFDAY
     72   else
     73     (void)gettimeofday(&now, NULL);
     74 #else
     75   else {
     76     now.tv_sec = (long)time(NULL);
     77     now.tv_usec = 0;
     78   }
     79 #endif
     80   return now;
     81 }
     82 
     83 #elif defined(HAVE_GETTIMEOFDAY)
     84 
     85 struct timeval curlx_tvnow(void)
     86 {
     87   /*
     88   ** gettimeofday() is not granted to be increased monotonically, due to
     89   ** clock drifting and external source time synchronization it can jump
     90   ** forward or backward in time.
     91   */
     92   struct timeval now;
     93   (void)gettimeofday(&now, NULL);
     94   return now;
     95 }
     96 
     97 #else
     98 
     99 struct timeval curlx_tvnow(void)
    100 {
    101   /*
    102   ** time() returns the value of time in seconds since the Epoch.
    103   */
    104   struct timeval now;
    105   now.tv_sec = (long)time(NULL);
    106   now.tv_usec = 0;
    107   return now;
    108 }
    109 
    110 #endif
    111 
    112 /*
    113  * Make sure that the first argument is the more recent time, as otherwise
    114  * we'll get a weird negative time-diff back...
    115  *
    116  * Returns: the time difference in number of milliseconds. For large diffs it
    117  * returns 0x7fffffff on 32bit time_t systems.
    118  */
    119 long curlx_tvdiff(struct timeval newer, struct timeval older)
    120 {
    121 #if SIZEOF_TIME_T < 8
    122   /* for 32bit time_t systems, add a precaution to avoid overflow for really
    123      big time differences */
    124   time_t diff = newer.tv_sec-older.tv_sec;
    125   if(diff >= (0x7fffffff/1000))
    126     return 0x7fffffff;
    127 #endif
    128   return (newer.tv_sec-older.tv_sec)*1000+
    129     (long)(newer.tv_usec-older.tv_usec)/1000;
    130 }
    131 
    132 /*
    133  * Same as curlx_tvdiff but with full usec resolution.
    134  *
    135  * Returns: the time difference in seconds with subsecond resolution.
    136  */
    137 double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
    138 {
    139   if(newer.tv_sec != older.tv_sec)
    140     return (double)(newer.tv_sec-older.tv_sec)+
    141       (double)(newer.tv_usec-older.tv_usec)/1000000.0;
    142   else
    143     return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
    144 }
    145 
    146 /* return the number of seconds in the given input timeval struct */
    147 long Curl_tvlong(struct timeval t1)
    148 {
    149   return t1.tv_sec;
    150 }
    151