]> sjero.net Git - wget/blobdiff - src/ptimer.c
NEWS: cite --start-pos
[wget] / src / ptimer.c
index 472e74ba395064e4b659161f3c0e295944886e1a..c53b5e7215cd08c6d4ed62763e01bd9325d504eb 100644 (file)
@@ -1,11 +1,12 @@
 /* Portable timers.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+   Foundation, Inc.
 
 This file is part of GNU Wget.
 
 GNU Wget is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.
 
 GNU Wget is distributed in the hope that it will be useful,
@@ -14,18 +15,18 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Wget; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-In addition, as a special exception, the Free Software Foundation
-gives permission to link the code of its release of Wget with the
-OpenSSL project's "OpenSSL" library (or with modified versions of it
-that use the same license as the "OpenSSL" library), and distribute
-the linked executables.  You must obey the GNU General Public License
-in all respects for all of the code used other than "OpenSSL".  If you
-modify this file, you may extend this exception to your version of the
-file, but you are not obligated to do so.  If you do not wish to do
-so, delete this exception statement from your version.  */
+along with Wget.  If not, see <http://www.gnu.org/licenses/>.
+
+Additional permission under GNU GPL version 3 section 7
+
+If you modify this program, or any covered work, by linking or
+combining it with the OpenSSL project's OpenSSL library (or a
+modified version of that library), containing parts covered by the
+terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
+grants you additional permission to convey the resulting work.
+Corresponding Source for a non-source form of such a combination
+shall include the source code for the parts of OpenSSL used as well
+as that of the covered work.  */
 
 /* This file implements "portable timers" (ptimers), objects that
    measure elapsed time using the primitives most appropriate for the
@@ -34,66 +35,55 @@ so, delete this exception statement from your version.  */
      ptimer_new     -- creates a timer.
      ptimer_reset   -- resets the timer's elapsed time to zero.
      ptimer_measure -- measure and return the time elapsed since
-                      creation or last reset.
+                       creation or last reset.
      ptimer_read    -- reads the last measured elapsed value.
      ptimer_destroy -- destroy the timer.
      ptimer_granularity -- returns the approximate granularity of the timers.
 
-   Timers measure time in milliseconds, but the timings they return
-   are floating point numbers, so they can carry as much precision as
-   the underlying system timer supports.  For example, to measure the
-   time it takes to run a loop, you can use something like:
+   Timers measure time in seconds, returning the timings as floating
+   point numbers, so they can carry as much precision as the
+   underlying system timer supports.  For example, to measure the time
+   it takes to run a loop, you can use something like:
 
      ptimer *tmr = ptimer_new ();
      while (...)
        ... loop ...
-     double msecs = ptimer_measure ();
-     printf ("The loop took %.2f ms\n", msecs);  */
+     double secs = ptimer_measure ();
+     printf ("The loop took %.2fs\n", secs);  */
 
-#include <config.h>
+#include "wget.h"
 
 #include <stdio.h>
 #include <stdlib.h>
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else  /* not HAVE_STRING_H */
-# include <strings.h>
-#endif /* not HAVE_STRING_H */
-#include <sys/types.h>
+#include <string.h>
 #include <errno.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+
+/* Cygwin currently (as of 2005-04-08, Cygwin 1.5.14) lacks clock_getres,
+   but still defines _POSIX_TIMERS!  Because of that we simply use the
+   Windows timers under Cygwin.  */
+#ifdef __CYGWIN__
+# include <windows.h>
 #endif
-#include <assert.h>
 
-#include "wget.h"
+#include "utils.h"
 #include "ptimer.h"
 
-#ifndef errno
-extern int errno;
-#endif
-
-/* Depending on the OS and availability of gettimeofday(), one and
-   only one of PTIMER_POSIX, PTIMER_GETTIMEOFDAY, PTIMER_WINDOWS, or
-   PTIMER_TIME will be defined.  */
+/* Depending on the OS, one and only one of PTIMER_POSIX,
+   PTIMER_GETTIMEOFDAY, or PTIMER_WINDOWS will be defined.  */
 
 #undef PTIMER_POSIX
 #undef PTIMER_GETTIMEOFDAY
-#undef PTIMER_TIME
 #undef PTIMER_WINDOWS
 
-#ifdef WINDOWS
-# define PTIMER_WINDOWS                /* use Windows timers */
+#if defined(WINDOWS) || defined(__CYGWIN__)
+# define PTIMER_WINDOWS         /* use Windows timers */
+#elif _POSIX_TIMERS - 0 > 0
+# define PTIMER_POSIX           /* use POSIX timers (clock_gettime) */
 #else
-# if _POSIX_TIMERS > 0
-#  define PTIMER_POSIX         /* use POSIX timers (clock_gettime) */
-# else
-#  ifdef HAVE_GETTIMEOFDAY
-#   define PTIMER_GETTIMEOFDAY /* use gettimeofday */
-#  else
-#   define PTIMER_TIME
-#  endif
-# endif
+# define PTIMER_GETTIMEOFDAY    /* use gettimeofday */
 #endif
 
 #ifdef PTIMER_POSIX
@@ -115,8 +105,8 @@ typedef struct timespec ptimer_system_time;
    CLOCK_MONOTONIC where available, CLOCK_REALTIME otherwise.  */
 static int posix_clock_id;
 
-/* Resolution of the clock, in milliseconds. */
-static double posix_millisec_resolution;
+/* Resolution of the clock, initialized in posix_init. */
+static double posix_clock_resolution;
 
 /* Decide which clock_id to use.  */
 
@@ -132,7 +122,7 @@ posix_init (void)
     int id;
     int sysconf_name;
   } clocks[] = {
-#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
+#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK - 0 >= 0
     { CLOCK_MONOTONIC, _SC_MONOTONIC_CLOCK },
 #endif
 #ifdef CLOCK_HIGHRES
@@ -140,7 +130,7 @@ posix_init (void)
 #endif
     { CLOCK_REALTIME, NO_SYSCONF_CHECK },
   };
-  int i;
+  size_t i;
 
   /* Determine the clock we can use.  For a clock to be usable, it
      must be confirmed with sysconf (where applicable) and with
@@ -150,27 +140,26 @@ posix_init (void)
     {
       struct timespec r;
       if (clocks[i].sysconf_name != NO_SYSCONF_CHECK)
-       if (sysconf (clocks[i].sysconf_name) < 0)
-         continue;             /* sysconf claims this clock is unavailable */
+        if (sysconf (clocks[i].sysconf_name) < 0)
+          continue;             /* sysconf claims this clock is unavailable */
       if (clock_getres (clocks[i].id, &r) < 0)
-       continue;               /* clock_getres doesn't work for this clock */
+        continue;               /* clock_getres doesn't work for this clock */
       posix_clock_id = clocks[i].id;
-      posix_millisec_resolution = r.tv_sec * 1000.0 + r.tv_nsec / 1000000.0;
-      /* Guard against broken clock_getres returning nonsensical
-        values.  */
-      if (posix_millisec_resolution == 0)
-       posix_millisec_resolution = 1;
+      posix_clock_resolution = (double) r.tv_sec + r.tv_nsec / 1e9;
+      /* Guard against nonsense returned by a broken clock_getres.  */
+      if (posix_clock_resolution == 0)
+        posix_clock_resolution = 1e-3;
       break;
     }
   if (i == countof (clocks))
     {
       /* If no clock was found, it means that clock_getres failed for
-        the realtime clock.  */
+         the realtime clock.  */
       logprintf (LOG_NOTQUIET, _("Cannot get REALTIME clock frequency: %s\n"),
-                strerror (errno));
+                 strerror (errno));
       /* Use CLOCK_REALTIME, but invent a plausible resolution. */
       posix_clock_id = CLOCK_REALTIME;
-      posix_millisec_resolution = 1;
+      posix_clock_resolution = 1e-3;
     }
 }
 
@@ -183,16 +172,16 @@ posix_measure (ptimer_system_time *pst)
 static inline double
 posix_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
 {
-  return ((pst1->tv_sec - pst2->tv_sec) * 1000.0
-         + (pst1->tv_nsec - pst2->tv_nsec) / 1000000.0);
+  return ((pst1->tv_sec - pst2->tv_sec)
+          + (pst1->tv_nsec - pst2->tv_nsec) / 1e9);
 }
 
 static inline double
 posix_resolution (void)
 {
-  return posix_millisec_resolution;
+  return posix_clock_resolution;
 }
-#endif /* PTIMER_POSIX */
+#endif  /* PTIMER_POSIX */
 
 #ifdef PTIMER_GETTIMEOFDAY
 /* Elapsed time measurement using gettimeofday: system time is held in
@@ -216,8 +205,8 @@ gettimeofday_measure (ptimer_system_time *pst)
 static inline double
 gettimeofday_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
 {
-  return ((pst1->tv_sec - pst2->tv_sec) * 1000.0
-         + (pst1->tv_usec - pst2->tv_usec) / 1000.0);
+  return ((pst1->tv_sec - pst2->tv_sec)
+          + (pst1->tv_usec - pst2->tv_usec) / 1e6);
 }
 
 static inline double
@@ -228,40 +217,7 @@ gettimeofday_resolution (void)
      than 1ms.  Assume 100 usecs.  */
   return 0.1;
 }
-#endif /* PTIMER_GETTIMEOFDAY */
-
-#ifdef PTIMER_TIME
-/* Elapsed time measurement using the time(2) call: system time is
-   held in time_t, retrieved using time, and resolution is 1 second.
-
-   This method is a catch-all for non-Windows systems without
-   gettimeofday -- e.g. DOS or really old or non-standard Unix
-   systems.  */
-
-typedef time_t ptimer_system_time;
-
-#define IMPL_measure time_measure
-#define IMPL_diff time_diff
-#define IMPL_resolution time_resolution
-
-static inline void
-time_measure (ptimer_system_time *pst)
-{
-  time (pst);
-}
-
-static inline double
-time_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
-{
-  return 1000.0 * (*pst1 - *pst2);
-}
-
-static inline double
-time_resolution (void)
-{
-  return 1;
-}
-#endif /* PTIMER_TIME */
+#endif  /* PTIMER_GETTIMEOFDAY */
 
 #ifdef PTIMER_WINDOWS
 /* Elapsed time measurement on Windows: where high-resolution timers
@@ -283,12 +239,12 @@ typedef union {
 
 /* Whether high-resolution timers are used.  Set by ptimer_initialize_once
    the first time ptimer_new is called. */
-static int windows_hires_timers;
+static bool windows_hires_timers;
 
 /* Frequency of high-resolution timers -- number of updates per
-   millisecond.  Calculated the first time ptimer_new is called
-   provided that high-resolution timers are available. */
-static double windows_hires_msfreq;
+   second.  Calculated the first time ptimer_new is called provided
+   that high-resolution timers are available. */
+static double windows_hires_freq;
 
 static void
 windows_init (void)
@@ -298,8 +254,8 @@ windows_init (void)
   QueryPerformanceFrequency (&freq);
   if (freq.QuadPart != 0)
     {
-      windows_hires_timers = 1;
-      windows_hires_msfreq = (double) freq.QuadPart / 1000.0;
+      windows_hires_timers = true;
+      windows_hires_freq = (double) freq.QuadPart;
     }
 }
 
@@ -321,7 +277,7 @@ static inline double
 windows_diff (ptimer_system_time *pst1, ptimer_system_time *pst2)
 {
   if (windows_hires_timers)
-    return (pst1->hires.QuadPart - pst2->hires.QuadPart) / windows_hires_msfreq;
+    return (pst1->hires.QuadPart - pst2->hires.QuadPart) / windows_hires_freq;
   else
     return pst1->lores - pst2->lores;
 }
@@ -330,11 +286,11 @@ static double
 windows_resolution (void)
 {
   if (windows_hires_timers)
-    return 1.0 / windows_hires_msfreq;
+    return 1.0 / windows_hires_freq;
   else
-    return 10;                 /* according to MSDN */
+    return 10;                  /* according to MSDN */
 }
-#endif /* PTIMER_WINDOWS */
+#endif  /* PTIMER_WINDOWS */
 \f
 /* The code below this point is independent of timer implementation. */
 
@@ -343,8 +299,7 @@ struct ptimer {
      time, yields elapsed time. */
   ptimer_system_time start;
 
-  /* The most recent elapsed time, calculated by ptimer_measure().
-     Measured in milliseconds.  */
+  /* The most recent elapsed time, calculated by ptimer_measure().  */
   double elapsed_last;
 
   /* Approximately, the time elapsed between the true start of the
@@ -360,10 +315,10 @@ ptimer_new (void)
 {
   struct ptimer *pt = xnew0 (struct ptimer);
 #ifdef IMPL_init
-  static int init_done;
+  static bool init_done;
   if (!init_done)
     {
-      init_done = 1;
+      init_done = true;
       IMPL_init ();
     }
 #endif
@@ -381,8 +336,8 @@ ptimer_destroy (struct ptimer *pt)
 }
 
 /* Reset timer PT.  This establishes the starting point from which
-   ptimer_read() will return the number of elapsed milliseconds.
-   It is allowed to reset a previously used timer.  */
+   ptimer_measure() will return the elapsed time in seconds.  It is
+   allowed to reset a previously used timer.  */
 
 void
 ptimer_reset (struct ptimer *pt)
@@ -393,13 +348,10 @@ ptimer_reset (struct ptimer *pt)
   pt->elapsed_pre_start = 0;
 }
 
-/* Measure the elapsed time since timer creation/reset and return it
-   to the caller.  The value remains stored for further reads by
-   ptimer_read.
-
-   This function causes the timer to call gettimeofday (or time(),
-   etc.) to update its idea of current time.  To get the elapsed
-   interval in milliseconds, use ptimer_read.
+/* Measure the elapsed time since timer creation/reset.  This causes
+   the timer to internally call clock_gettime (or gettimeofday, etc.)
+   to update its idea of current time.  The time is returned, but is
+   also stored for later access through ptimer_read().
 
    This function handles clock skew, i.e. time that moves backwards is
    ignored.  */
@@ -440,8 +392,9 @@ ptimer_measure (struct ptimer *pt)
   return elapsed;
 }
 
-/* Return the elapsed time in milliseconds between the last call to
-   ptimer_reset and the last call to ptimer_update.  */
+/* Return the most recent elapsed time measured with ptimer_measure.
+   If ptimer_measure has not yet been called since the timer was
+   created or reset, this returns 0.  */
 
 double
 ptimer_read (const struct ptimer *pt)
@@ -450,8 +403,8 @@ ptimer_read (const struct ptimer *pt)
 }
 
 /* Return the assessed resolution of the timer implementation, in
-   milliseconds.  This is used by code that tries to substitute a
-   better value for timers that have returned zero.  */
+   seconds.  This is used by code that tries to substitute a better
+   value for timers that have returned zero.  */
 
 double
 ptimer_resolution (void)