Revert "Update to 7.44.0"
[platform/upstream/curl.git] / lib / timeval.c
index 11f3d7a..769eb3c 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  * KIND, either express or implied.
  *
- * $Id$
  ***************************************************************************/
 
 #include "timeval.h"
 
-#ifndef HAVE_GETTIMEOFDAY
+#if defined(WIN32) && !defined(MSDOS)
 
-#ifdef WIN32
-#include <mmsystem.h>
-
-static int gettimeofday(struct timeval *tp, void *nothing)
+struct timeval curlx_tvnow(void)
 {
-#ifdef WITHOUT_MM_LIB
-  SYSTEMTIME st;
-  time_t tt;
-  struct tm tmtm;
-  /* mktime converts local to UTC */
-  GetLocalTime (&st);
-  tmtm.tm_sec = st.wSecond;
-  tmtm.tm_min = st.wMinute;
-  tmtm.tm_hour = st.wHour;
-  tmtm.tm_mday = st.wDay;
-  tmtm.tm_mon = st.wMonth - 1;
-  tmtm.tm_year = st.wYear - 1900;
-  tmtm.tm_isdst = -1;
-  tt = mktime (&tmtm);
-  tp->tv_sec = tt;
-  tp->tv_usec = st.wMilliseconds * 1000;
+  /*
+  ** GetTickCount() is available on _all_ Windows versions from W95 up
+  ** to nowadays. Returns milliseconds elapsed since last system boot,
+  ** increases monotonically and wraps once 49.7 days have elapsed.
+  */
+  struct timeval now;
+#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
+    (_WIN32_WINNT < _WIN32_WINNT_VISTA)
+  DWORD milliseconds = GetTickCount();
+  now.tv_sec = milliseconds / 1000;
+  now.tv_usec = (milliseconds % 1000) * 1000;
 #else
-  /**
-   ** The earlier time calculations using GetLocalTime
-   ** had a time resolution of 10ms.The timeGetTime, part
-   ** of multimedia apis offer a better time resolution
-   ** of 1ms.Need to link against winmm.lib for this
-   **/
-  unsigned long Ticks = 0;
-  unsigned long Sec =0;
-  unsigned long Usec = 0;
-  Ticks = timeGetTime();
+  ULONGLONG milliseconds = GetTickCount64();
+  now.tv_sec = (long) (milliseconds / 1000);
+  now.tv_usec = (long) (milliseconds % 1000) * 1000;
+#endif
 
-  Sec = Ticks/1000;
-  Usec = (Ticks - (Sec*1000))*1000;
-  tp->tv_sec = Sec;
-  tp->tv_usec = Usec;
-#endif /* WITHOUT_MM_LIB */
-  (void)nothing;
-  return 0;
+  return now;
 }
-#else /* WIN32 */
-/* non-win32 version of Curl_gettimeofday() */
-static int gettimeofday(struct timeval *tp, void *nothing)
+
+#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
+
+struct timeval curlx_tvnow(void)
 {
-  (void)nothing; /* we don't support specific time-zones */
-  tp->tv_sec = (long)time(NULL);
-  tp->tv_usec = 0;
-  return 0;
+  /*
+  ** clock_gettime() is granted to be increased monotonically when the
+  ** monotonic clock is queried. Time starting point is unspecified, it
+  ** could be the system start-up time, the Epoch, or something else,
+  ** in any case the time starting point does not change once that the
+  ** system has started up.
+  */
+  struct timeval now;
+  struct timespec tsnow;
+  if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) {
+    now.tv_sec = tsnow.tv_sec;
+    now.tv_usec = tsnow.tv_nsec / 1000;
+  }
+  /*
+  ** Even when the configure process has truly detected monotonic clock
+  ** availability, it might happen that it is not actually available at
+  ** run-time. When this occurs simply fallback to other time source.
+  */
+#ifdef HAVE_GETTIMEOFDAY
+  else
+    (void)gettimeofday(&now, NULL);
+#else
+  else {
+    now.tv_sec = (long)time(NULL);
+    now.tv_usec = 0;
+  }
+#endif
+  return now;
 }
-#endif /* WIN32 */
-#endif /* HAVE_GETTIMEOFDAY */
 
-/* Return the current time in a timeval struct */
+#elif defined(HAVE_GETTIMEOFDAY)
+
 struct timeval curlx_tvnow(void)
 {
+  /*
+  ** gettimeofday() is not granted to be increased monotonically, due to
+  ** clock drifting and external source time synchronization it can jump
+  ** forward or backward in time.
+  */
   struct timeval now;
   (void)gettimeofday(&now, NULL);
   return now;
 }
 
+#else
+
+struct timeval curlx_tvnow(void)
+{
+  /*
+  ** time() returns the value of time in seconds since the Epoch.
+  */
+  struct timeval now;
+  now.tv_sec = (long)time(NULL);
+  now.tv_usec = 0;
+  return now;
+}
+
+#endif
+
 /*
  * Make sure that the first argument is the more recent time, as otherwise
  * we'll get a weird negative time-diff back...
@@ -105,8 +128,11 @@ long curlx_tvdiff(struct timeval newer, struct timeval older)
  */
 double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
 {
-  return (double)(newer.tv_sec-older.tv_sec)+
-    (double)(newer.tv_usec-older.tv_usec)/1000000.0;
+  if(newer.tv_sec != older.tv_sec)
+    return (double)(newer.tv_sec-older.tv_sec)+
+      (double)(newer.tv_usec-older.tv_usec)/1000000.0;
+  else
+    return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
 }
 
 /* return the number of seconds in the given input timeval struct */