]> sjero.net Git - wget/commitdiff
[svn] Use high-resolution timers on Windows.
authorhniksic <devnull@localhost>
Sun, 20 Mar 2005 10:41:46 +0000 (02:41 -0800)
committerhniksic <devnull@localhost>
Sun, 20 Mar 2005 10:41:46 +0000 (02:41 -0800)
src/ChangeLog
src/cookies.c
src/gen-md5.c
src/host.c
src/mswindows.c
src/mswindows.h
src/utils.c
src/utils.h

index 2e996aa0a6995be0e09617ee7a7d35ab26843be9..a2411375539fe11be0b9f15dec7ae24394a04696 100644 (file)
@@ -1,3 +1,34 @@
+2005-03-12  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * utils.c (debug_test_md5): Moved to gen-md5.c.
+
+       * mswindows.h: Don't declare inet_ntop, since we don't use it.
+
+       * mswindows.h: For consistency, also wrap closesocket, it being
+       a Winsock call.
+
+       * mswindows.h: Don't declare sleep and usleep; we're defining
+       xsleep now.
+
+       * mswindows.h (mkdir): Don't special-case Borland C, _mkdir
+       works there as well.
+
+       * host.c: Don't include winsock header files; the correct ones
+       are already included by mswindows.h.
+
+       * mswindows.c (xsleep): Round toward the nearest millisecond
+       in an attempt to avoid average short sleeps.
+
+       * utils.c (wtimer_granularity): Report correct values for
+       Windows timers and for high-resolution timers.
+
+       * utils.c (wtimer_initialize_once): New function, called to
+       initialize the timer frequency.
+
+       * utils.c: Replace the use of GetSystemTime with high-resolution
+       counters under Windows.  When high-resolution counters are
+       unavailable, use GetTickCount().
+
 2005-03-15  Hrvoje Niksic  <hniksic@xemacs.org>
 
        * retr.c (fd_read_body): Undo the 2004-11-18 change.  Instead,
index fe9761fde43fa30ff2a1d1f8032e312d7d7dbdc4..d0d9e6101e3c4930b210aee19aaa8a53acad0753 100644 (file)
@@ -898,6 +898,19 @@ cookie_handle_set_cookie (struct cookie_jar *jar,
 /* Support for sending out cookies in HTTP requests, based on
    previously stored cookies.  Entry point is
    `build_cookies_request'.  */
+   
+/* Return a count of how many times CHR occurs in STRING. */
+
+static int
+count_char (const char *string, char chr)
+{
+  const char *p;
+  int count = 0;
+  for (p = string; *p; p++)
+    if (*p == chr)
+      ++count;
+  return count;
+}
 
 /* Find the cookie chains whose domains match HOST and store them to
    DEST.
index 250d1c4f50b3e98eb93631a02ee63e789a05050f..716e4c222f9b72b49d0d4c79879c8569697f2edf 100644 (file)
@@ -116,3 +116,37 @@ gen_md5_finish (gen_md5_context *ctx, unsigned char *result)
   MD5_Final (result, ctx_imp);
 #endif
 }
+
+#if 0
+/* A debugging function for checking whether an MD5 library works. */
+
+#include "gen-md5.h"
+
+char *
+debug_test_md5 (char *buf)
+{
+  unsigned char raw[16];
+  static char res[33];
+  unsigned char *p1;
+  char *p2;
+  int cnt;
+  ALLOCA_MD5_CONTEXT (ctx);
+
+  gen_md5_init (ctx);
+  gen_md5_update ((unsigned char *)buf, strlen (buf), ctx);
+  gen_md5_finish (ctx, raw);
+
+  p1 = raw;
+  p2 = res;
+  cnt = 16;
+  while (cnt--)
+    {
+      *p2++ = XNUM_TO_digit (*p1 >> 4);
+      *p2++ = XNUM_TO_digit (*p1 & 0xf);
+      ++p1;
+    }
+  *p2 = '\0';
+
+  return res;
+}
+#endif
index b550d786d3a05cfbff7cfcf8d1d6daaa77ff315a..272ed4f1629160e454650a93057cb506d6f7757d 100644 (file)
@@ -43,10 +43,7 @@ so, delete this exception statement from your version.  */
 #include <assert.h>
 #include <sys/types.h>
 
-#ifdef WINDOWS
-# include <winsock.h>
-# define SET_H_ERRNO(err) WSASetLastError (err)
-#else
+#ifndef WINDOWS
 # include <sys/socket.h>
 # include <netinet/in.h>
 # ifndef __BEOS__
@@ -54,6 +51,8 @@ so, delete this exception statement from your version.  */
 # endif
 # include <netdb.h>
 # define SET_H_ERRNO(err) ((void)(h_errno = (err)))
+#else  /* WINDOWS */
+# define SET_H_ERRNO(err) WSASetLastError (err)
 #endif /* WINDOWS */
 
 #ifndef NO_ADDRESS
index 15518a008a810589479053af1c726ddc1aaaa817..a16b4b81fbc217cf05b13142316694b312e9eb8a 100644 (file)
@@ -84,7 +84,7 @@ xsleep (double seconds)
     }
   usleep (seconds * 1000000L);
 #else  /* not HAVE_USLEEP */
-  SleepEx (seconds * 1000, FALSE);
+  SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
 #endif /* not HAVE_USLEEP */
 }
 
@@ -589,12 +589,9 @@ set_sleep_mode (void)
 void
 ws_startup (void)
 {
-  WORD requested;
   WSADATA data;
-  int err;
-
-  requested = MAKEWORD (1, 1);
-  err = WSAStartup (requested, &data);
+  WORD requested = MAKEWORD (1, 1);
+  int err = WSAStartup (requested, &data);
   if (err != 0)
     {
       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
@@ -741,16 +738,16 @@ run_with_timeout (double seconds, void (*fun) (void *), void *arg)
   return rc;
 }
 \f
-/* Wget expects network calls such as bind, connect, etc., to set errno.
-   To achieve that, we place Winsock calls in wrapper functions that, in
-   case of error, sets errno to the value of GetLastError().  In addition,
-   we provide a wrapper around strerror, which recognizes Winsock errors
-   and prints the appropriate error message. */
+/* Wget expects network calls such as connect, recv, send, etc., to set
+   errno on failure.  To achieve that, Winsock calls are wrapped with code
+   that, in case of error, sets errno to the value of WSAGetLastError().
+   In addition, we provide a wrapper around strerror, which recognizes
+   Winsock errors and prints the appropriate error message. */
 
 /* Define a macro that creates a function definition that wraps FUN into
    a function that sets errno the way the rest of the code expects. */
 
-#define WRAP(fun, decl, call) int wrap_##fun decl {    \
+#define WRAP(fun, decl, call) int wrapped_##fun decl { \
   int retval = fun call;                               \
   if (retval < 0)                                      \
     errno = WSAGetLastError ();                                \
@@ -768,6 +765,7 @@ WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
 WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
 WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
                   (s, level, opt, val, len))
+WRAP (closesocket, (int s), (s))
 
 /* Return the text of the error message for Winsock error WSERR. */
 
index 8691d94cc4566edaba9e0d8d80c182d5bb288820..6750934b2c6b1221246180a7f051da743daf1a83 100644 (file)
@@ -124,38 +124,36 @@ __int64 str_to_int64 (const char *, char **, int);
 #include <direct.h>
 
 /* Windows compilers accept only one arg to mkdir.  */
-#ifndef __BORLANDC__
-# define mkdir(a, b) _mkdir(a)
-#else  /* __BORLANDC__ */
-# define mkdir(a, b) mkdir(a)
-#endif /* __BORLANDC__ */
+#define mkdir(a, b) _mkdir(a)
 
 #ifndef INHIBIT_WRAP
 
 /* Winsock functions don't set errno, so we provide wrappers
    that do. */
 
-#define socket wrap_socket
-#define bind wrap_bind
-#define connect wrap_connect
-#define recv wrap_recv
-#define send wrap_send
-#define select wrap_select
-#define getsockname wrap_getsockname
-#define getpeername wrap_getpeername
-#define setsockopt wrap_setsockopt
+#define socket wrapped_socket
+#define bind wrapped_bind
+#define connect wrapped_connect
+#define recv wrapped_recv
+#define send wrapped_send
+#define select wrapped_select
+#define getsockname wrapped_getsockname
+#define getpeername wrapped_getpeername
+#define setsockopt wrapped_setsockopt
+#define closesocket wrapped_closesocket
 
 #endif /* not INHIBIT_WRAP */
 
-int wrap_socket (int, int, int);
-int wrap_bind (int, struct sockaddr *, int);
-int wrap_connect (int, const struct sockaddr *, int);
-int wrap_recv (int, void *, int, int);
-int wrap_send (int, const void *, int, int);
-int wrap_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *);
-int wrap_getsockname (int, struct sockaddr *, int *);
-int wrap_getpeername (int, struct sockaddr *, int *);
-int wrap_setsockopt (int, int, int, const void *, int);
+int wrapped_socket (int, int, int);
+int wrapped_bind (int, struct sockaddr *, int);
+int wrapped_connect (int, const struct sockaddr *, int);
+int wrapped_recv (int, void *, int, int);
+int wrapped_send (int, const void *, int, int);
+int wrapped_select (int, fd_set *, fd_set *, fd_set *, const struct timeval *);
+int wrapped_getsockname (int, struct sockaddr *, int *);
+int wrapped_getpeername (int, struct sockaddr *, int *);
+int wrapped_setsockopt (int, int, int, const void *, int);
+int wrapped_closesocket (int);
 
 /* Finally, provide a private version of strerror that does the
    right thing with Winsock errors. */
@@ -204,13 +202,6 @@ const char *windows_strerror (int);
 
 /* Public functions.  */
 
-#ifndef HAVE_SLEEP
-unsigned int sleep (unsigned);
-#endif
-#ifndef HAVE_USLEEP
-int usleep (unsigned long);
-#endif
-
 void ws_startup (void);
 void ws_changetitle (const char *);
 void ws_percenttitle (double);
@@ -219,11 +210,8 @@ void windows_main (int *, char **, char **);
 
 /* Things needed for IPv6; missing in <ws2tcpip.h>.  */
 #ifdef ENABLE_IPV6
-# ifndef HAVE_NTOP
-  extern const char *inet_ntop (int af, const void *src, char *dst, size_t size);
-# endif
-# ifndef HAVE_PTON
-  extern int inet_pton (int af, const char *src, void *dst);
+# ifndef HAVE_INET_NTOP
+extern const char *inet_ntop (int af, const void *src, char *dst, size_t size);
 # endif
 #endif /* ENABLE_IPV6 */
 
index e5098be38a5cbc4780d0381068adb873973b27eb..2319947a5ffb18675d7f8b044b8d8c98ff0b95d9 100644 (file)
@@ -1,5 +1,5 @@
 /* Various utility functions.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2005 Free Software Foundation, Inc.
 
 This file is part of GNU Wget.
 
@@ -120,19 +120,6 @@ xstrdup_lower (const char *s)
   return copy;
 }
 
-/* Return a count of how many times CHR occurs in STRING. */
-
-int
-count_char (const char *string, char chr)
-{
-  const char *p;
-  int count = 0;
-  for (p = string; *p; p++)
-    if (*p == chr)
-      ++count;
-  return count;
-}
-
 /* Copy the string formed by two pointers (one on the beginning, other
    on the char after the last char) to a new, malloc-ed location.
    0-terminate it.  */
@@ -1564,11 +1551,7 @@ number_to_static_string (wgint number)
    only one of the above constants will be defined.  Virtually all
    modern Unix systems will define TIMER_GETTIMEOFDAY; Windows will
    use TIMER_WINDOWS.  TIMER_TIME is a catch-all method for
-   non-Windows systems without gettimeofday.
-
-   #### Perhaps we should also support ftime(), which exists on old
-   BSD 4.2-influenced systems?  (It also existed under MS DOS Borland
-   C, if memory serves me.)  */
+   non-Windows systems without gettimeofday.  */
 
 #ifdef WINDOWS
 # define TIMER_WINDOWS
@@ -1589,7 +1572,10 @@ typedef time_t wget_sys_time;
 #endif
 
 #ifdef TIMER_WINDOWS
-typedef ULARGE_INTEGER wget_sys_time;
+typedef union {
+  DWORD lores;          /* In case GetTickCount is used */
+  LARGE_INTEGER hires;  /* In case high-resolution timer is used */
+} wget_sys_time;
 #endif
 
 struct wget_timer {
@@ -1609,6 +1595,39 @@ struct wget_timer {
   double elapsed_pre_start;
 };
 
+#ifdef TIMER_WINDOWS
+
+/* Whether high-resolution timers are used.  Set by wtimer_initialize_once
+   the first time wtimer_allocate is called. */
+static int using_hires_timers;
+
+/* Frequency of high-resolution timers -- number of updates per
+   millisecond.  Calculated the first time wtimer_allocate is called
+   provided that high-resolution timers are available. */
+static double hires_millisec_freq;
+
+/* The first time a timer is created, determine whether to use
+   high-resolution timers. */
+
+static void
+wtimer_initialize_once (void)
+{
+  static int init_done;
+  if (!init_done)
+    {
+      LARGE_INTEGER freq;
+      init_done = 1;
+      freq.QuadPart = 0;
+      QueryPerformanceFrequency (&freq);
+      if (freq.QuadPart != 0)
+        {
+          using_hires_timers = 1;
+          hires_millisec_freq = (double) freq.QuadPart / 1000.0;
+        }
+     }
+}
+#endif /* TIMER_WINDOWS */
+
 /* Allocate a timer.  Calling wtimer_read on the timer will return
    zero.  It is not legal to call wtimer_update with a freshly
    allocated timer -- use wtimer_reset first.  */
@@ -1618,6 +1637,11 @@ wtimer_allocate (void)
 {
   struct wget_timer *wt = xnew (struct wget_timer);
   xzero (*wt);
+
+#ifdef TIMER_WINDOWS
+  wtimer_initialize_once ();
+#endif
+
   return wt;
 }
 
@@ -1654,32 +1678,24 @@ wtimer_sys_set (wget_sys_time *wst)
 #endif
 
 #ifdef TIMER_WINDOWS
-  /* We use GetSystemTime to get the elapsed time.  MSDN warns that
-     system clock adjustments can skew the output of GetSystemTime
-     when used as a timer and gives preference to GetTickCount and
-     high-resolution timers.  But GetTickCount can overflow, and hires
-     timers are typically used for profiling, not for regular time
-     measurement.  Since we handle clock skew anyway, we just use
-     GetSystemTime.  */
-  FILETIME ft;
-  SYSTEMTIME st;
-  GetSystemTime (&st);
-
-  /* As recommended by MSDN, we convert SYSTEMTIME to FILETIME, copy
-     FILETIME to ULARGE_INTEGER, and use regular 64-bit integer
-     arithmetic on that.  */
-  SystemTimeToFileTime (&st, &ft);
-  wst->HighPart = ft.dwHighDateTime;
-  wst->LowPart  = ft.dwLowDateTime;
+  if (using_hires_timers)
+    {
+      QueryPerformanceCounter (&wst->hires);
+    }
+  else
+    {
+      /* Where hires counters are not available, use GetTickCount rather
+         GetSystemTime, because it is unaffected by clock skew and simpler
+         to use.  Note that overflows don't affect us because we never use
+         absolute values of the ticker, only the differences.  */
+      wst->lores = GetTickCount ();
+    }
 #endif
 }
 
 /* Reset timer WT.  This establishes the starting point from which
    wtimer_elapsed() will return the number of elapsed milliseconds.
-   It is allowed to reset a previously used timer.
-
-   If a non-zero value is used as START, the timer's values will be
-   offset by START.  */
+   It is allowed to reset a previously used timer.  */
 
 void
 wtimer_reset (struct wget_timer *wt)
@@ -1704,10 +1720,10 @@ wtimer_sys_diff (wget_sys_time *wst1, wget_sys_time *wst2)
 #endif
 
 #ifdef WINDOWS
-  /* VC++ 6 doesn't support direct cast of uint64 to double.  To work
-     around this, we subtract, then convert to signed, then finally to
-     double.  */
-  return (double)(signed __int64)(wst1->QuadPart - wst2->QuadPart) / 10000;
+  if (using_hires_timers)
+    return (wst1->hires.QuadPart - wst2->hires.QuadPart) / hires_millisec_freq;
+  else
+    return wst1->lores - wst2->lores;
 #endif
 }
 
@@ -1789,9 +1805,10 @@ wtimer_granularity (void)
 #endif
 
 #ifdef TIMER_WINDOWS
-  /* According to MSDN, GetSystemTime returns a broken-down time
-     structure the smallest member of which are milliseconds.  */
-  return 1;
+  if (using_hires_timers)
+    return 1.0 / hires_millisec_freq;
+  else
+    return 10;  /* according to MSDN */
 #endif
 }
 \f
@@ -1964,40 +1981,6 @@ random_float (void)
   int rnd3 = random_number (1000);
   return rnd1 / 1000.0 + rnd2 / 1000000.0 + rnd3 / 1000000000.0;
 }
-
-#if 0
-/* A debugging function for checking whether an MD5 library works. */
-
-#include "gen-md5.h"
-
-char *
-debug_test_md5 (char *buf)
-{
-  unsigned char raw[16];
-  static char res[33];
-  unsigned char *p1;
-  char *p2;
-  int cnt;
-  ALLOCA_MD5_CONTEXT (ctx);
-
-  gen_md5_init (ctx);
-  gen_md5_update ((unsigned char *)buf, strlen (buf), ctx);
-  gen_md5_finish (ctx, raw);
-
-  p1 = raw;
-  p2 = res;
-  cnt = 16;
-  while (cnt--)
-    {
-      *p2++ = XNUM_TO_digit (*p1 >> 4);
-      *p2++ = XNUM_TO_digit (*p1 & 0xf);
-      ++p1;
-    }
-  *p2 = '\0';
-
-  return res;
-}
-#endif
 \f
 /* Implementation of run_with_timeout, a generic timeout-forcing
    routine for systems with Unix-like signal handling.  */
@@ -2168,8 +2151,9 @@ xsleep (double seconds)
 #ifdef HAVE_NANOSLEEP
   /* nanosleep is the preferred interface because it offers high
      accuracy and, more importantly, because it allows us to reliably
-     restart after having been interrupted by a signal such as
-     SIGWINCH.  */
+     restart receiving a signal such as SIGWINCH.  (There was an
+     actual Debian bug report about --limit-rate malfunctioning while
+     the terminal was being resized.)  */
   struct timespec sleep, remaining;
   sleep.tv_sec = (long) seconds;
   sleep.tv_nsec = 1000000000L * (seconds - (long) seconds);
index d6a118d2b292406f794c9cba1ce7fef90d136d26..1b3da62831c1cadf095599164ab85cdf7ef9eadc 100644 (file)
@@ -61,7 +61,6 @@ void print_malloc_debug_stats ();
 #endif
 
 char *xstrdup_lower PARAMS ((const char *));
-int count_char PARAMS ((const char *, char));
 
 char *strdupdelim PARAMS ((const char *, const char *));
 char **sepstring PARAMS ((const char *));