mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Use high-resolution timers on Windows.
This commit is contained in:
parent
828a50e4f3
commit
6da4142b3b
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
152
src/utils.c
152
src/utils.c
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
/* 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);
|
||||
|
@ -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 *));
|
||||
|
Loading…
Reference in New Issue
Block a user