Update to 7.40.1
[platform/upstream/curl.git] / lib / timeval.c
index 155aa79..769eb3c 100644 (file)
-/*****************************************************************************
- *                                  _   _ ____  _     
- *  Project                     ___| | | |  _ \| |    
- *                             / __| | | | |_) | |    
- *                            | (__| |_| |  _ <| |___ 
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- *  The contents of this file are subject to the Mozilla Public License
- *  Version 1.0 (the "License"); you may not use this file except in
- *  compliance with the License. You may obtain a copy of the License at
- *  http://www.mozilla.org/MPL/
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
- *  Software distributed under the License is distributed on an "AS IS"
- *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- *  License for the specific language governing rights and limitations
- *  under the License.
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://curl.haxx.se/docs/copyright.html.
  *
- *  The Original Code is Curl.
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
  *
- *  The Initial Developer of the Original Code is Daniel Stenberg.
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
  *
- *  Portions created by the Initial Developer are Copyright (C) 1998.
- *  All Rights Reserved.
- *
- * ------------------------------------------------------------
- * Main author:
- * - Daniel Stenberg <daniel@haxx.se>
- *
- *     http://curl.haxx.se
- *
- * $Source$
- * $Revision$
- * $Date$
- * $Author$
- * $State$
- * $Locker$
- *
- * ------------------------------------------------------------
- ****************************************************************************/
+ ***************************************************************************/
 
-#ifdef WIN32
-#include <windows.h>
-#endif
 #include "timeval.h"
 
-#ifndef HAVE_GETTIMEOFDAY
+#if defined(WIN32) && !defined(MSDOS)
 
-#ifdef WIN32
-int
-gettimeofday (struct timeval *tp, void *nothing)
+struct timeval curlx_tvnow(void)
 {
- 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;
- return 1;
-}
-#define HAVE_GETTIMEOFDAY
-#endif
+  /*
+  ** 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
+  ULONGLONG milliseconds = GetTickCount64();
+  now.tv_sec = (long) (milliseconds / 1000);
+  now.tv_usec = (long) (milliseconds % 1000) * 1000;
 #endif
 
-struct timeval tvnow ()
+  return now;
+}
+
+#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
+
+struct timeval curlx_tvnow(void)
 {
- struct timeval now;
+  /*
+  ** 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
- gettimeofday (&now, NULL);
+  else
+    (void)gettimeofday(&now, NULL);
 #else
- now.tv_sec = (long) time(NULL);
- now.tv_usec = 0;
+  else {
+    now.tv_sec = (long)time(NULL);
+    now.tv_usec = 0;
+  }
 #endif
- return now;
 return now;
 }
 
-double tvdiff (struct timeval t1, struct timeval t2)
+#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...
+ *
+ * Returns: the time difference in number of milliseconds.
+ */
+long curlx_tvdiff(struct timeval newer, struct timeval older)
+{
+  return (newer.tv_sec-older.tv_sec)*1000+
+    (newer.tv_usec-older.tv_usec)/1000;
+}
+
+/*
+ * Same as curlx_tvdiff but with full usec resolution.
+ *
+ * Returns: the time difference in seconds with subsecond resolution.
+ */
+double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
 {
- return (double)(t1.tv_sec - t2.tv_sec) + ((t1.tv_usec-t2.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;
 }
 
-long tvlong (struct timeval t1)
+/* return the number of seconds in the given input timeval struct */
+long Curl_tvlong(struct timeval t1)
 {
- return t1.tv_sec;
 return t1.tv_sec;
 }