1/* Portable timers. 2 Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, 3 Inc. 4 5This file is part of GNU Wget. 6 7GNU Wget is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3 of the License, or 10(at your option) any later version. 11 12GNU Wget is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with Wget. If not, see <http://www.gnu.org/licenses/>. 19 20Additional permission under GNU GPL version 3 section 7 21 22If you modify this program, or any covered work, by linking or 23combining it with the OpenSSL project's OpenSSL library (or a 24modified version of that library), containing parts covered by the 25terms of the OpenSSL or SSLeay licenses, the Free Software Foundation 26grants you additional permission to convey the resulting work. 27Corresponding Source for a non-source form of such a combination 28shall include the source code for the parts of OpenSSL used as well 29as that of the covered work. */ 30 31/* This file implements "portable timers" (ptimers), objects that 32 measure elapsed time using the primitives most appropriate for the 33 underlying operating system. The entry points are: 34 35 ptimer_new -- creates a timer. 36 ptimer_reset -- resets the timer's elapsed time to zero. 37 ptimer_measure -- measure and return the time elapsed since 38 creation or last reset. 39 ptimer_read -- reads the last measured elapsed value. 40 ptimer_destroy -- destroy the timer. 41 ptimer_granularity -- returns the approximate granularity of the timers. 42 43 Timers measure time in seconds, returning the timings as floating 44 point numbers, so they can carry as much precision as the 45 underlying system timer supports. For example, to measure the time 46 it takes to run a loop, you can use something like: 47 48 ptimer *tmr = ptimer_new (); 49 while (...) 50 ... loop ... 51 double secs = ptimer_measure (); 52 printf ("The loop took %.2fs\n", secs); */ 53 54#include "wget.h" 55 56#include <stdio.h> 57#include <stdlib.h> 58#include <string.h> 59#include <errno.h> 60#ifdef HAVE_UNISTD_H 61# include <unistd.h> 62#endif 63#include <time.h> 64#ifdef HAVE_SYS_TIME_H 65# include <sys/time.h> 66#endif 67 68/* Cygwin currently (as of 2005-04-08, Cygwin 1.5.14) lacks clock_getres, 69 but still defines _POSIX_TIMERS! Because of that we simply use the 70 Windows timers under Cygwin. */ 71#ifdef __CYGWIN__ 72# include <windows.h> 73#endif 74 75#include "utils.h" 76#include "ptimer.h" 77 78/* Depending on the OS, one and only one of PTIMER_POSIX, 79 PTIMER_GETTIMEOFDAY, or PTIMER_WINDOWS will be defined. */ 80 81#undef PTIMER_POSIX 82#undef PTIMER_GETTIMEOFDAY 83#undef PTIMER_WINDOWS 84 85#if defined(WINDOWS) || defined(__CYGWIN__) 86# define PTIMER_WINDOWS /* use Windows timers */ 87#elif _POSIX_TIMERS - 0 > 0 88# define PTIMER_POSIX /* use POSIX timers (clock_gettime) */ 89#else 90# define PTIMER_GETTIMEOFDAY /* use gettimeofday */ 91#endif 92 93#ifdef PTIMER_POSIX 94/* Elapsed time measurement using POSIX timers: system time is held in 95 struct timespec, time is retrieved using clock_gettime, and 96 resolution using clock_getres. 97 98 This method is used on Unix systems that implement POSIX 99 timers. */ 100 101typedef struct timespec ptimer_system_time; 102 103#define IMPL_init posix_init 104#define IMPL_measure posix_measure 105#define IMPL_diff posix_diff 106#define IMPL_resolution posix_resolution 107 108/* clock_id to use for POSIX clocks. This tries to use 109 CLOCK_MONOTONIC where available, CLOCK_REALTIME otherwise. */ 110static int posix_clock_id; 111 112/* Resolution of the clock, initialized in posix_init. */ 113static double posix_clock_resolution; 114 115/* Decide which clock_id to use. */ 116 117static void 118posix_init (void) 119{ 120 /* List of clocks we want to support: some systems support monotonic 121 clocks, Solaris has "high resolution" clock (sometimes 122 unavailable except to superuser), and all should support the 123 real-time clock. */ 124#define NO_SYSCONF_CHECK -1 125 static const struct { 126 int id; 127 int sysconf_name; 128 } clocks[] = { 129#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK - 0 >= 0 130 { CLOCK_MONOTONIC, _SC_MONOTONIC_CLOCK }, 131#endif 132#ifdef CLOCK_HIGHRES 133 { CLOCK_HIGHRES, NO_SYSCONF_CHECK }, 134#endif 135 { CLOCK_REALTIME, NO_SYSCONF_CHECK }, 136 }; 137 size_t i; 138 139 /* Determine the clock we can use. For a clock to be usable, it 140 must be confirmed with sysconf (where applicable) and with 141 clock_getres. If no clock is found, CLOCK_REALTIME is used. */ 142 143 for (i = 0; i < countof (clocks); i++) 144 { 145 struct timespec r; 146 if (clocks[i].sysconf_name != NO_SYSCONF_CHECK) 147 if (sysconf (clocks[i].sysconf_name) < 0) 148 continue; /* sysconf claims this clock is unavailable */ 149 if (clock_getres (clocks[i].id, &r) < 0) 150 continue; /* clock_getres doesn't work for this clock */ 151 posix_clock_id = clocks[i].id; 152 posix_clock_resolution = (double) r.tv_sec + r.tv_nsec / 1e9; 153 /* Guard against nonsense returned by a broken clock_getres. */ 154 if (posix_clock_resolution == 0) 155 posix_clock_resolution = 1e-3; 156 break; 157 } 158 if (i == countof (clocks)) 159 { 160 /* If no clock was found, it means that clock_getres failed for 161 the realtime clock. */ 162 logprintf (LOG_NOTQUIET, _("Cannot get REALTIME clock frequency: %s\n"), 163 strerror (errno)); 164 /* Use CLOCK_REALTIME, but invent a plausible resolution. */ 165 posix_clock_id = CLOCK_REALTIME; 166 posix_clock_resolution = 1e-3; 167 } 168} 169 170static inline void 171posix_measure (ptimer_system_time *pst) 172{ 173 clock_gettime (posix_clock_id, pst); 174} 175 176static inline double 177posix_diff (ptimer_system_time *pst1, ptimer_system_time *pst2) 178{ 179 return ((pst1->tv_sec - pst2->tv_sec) 180 + (pst1->tv_nsec - pst2->tv_nsec) / 1e9); 181} 182 183static inline double 184posix_resolution (void) 185{ 186 return posix_clock_resolution; 187} 188#endif /* PTIMER_POSIX */ 189 190#ifdef PTIMER_GETTIMEOFDAY 191/* Elapsed time measurement using gettimeofday: system time is held in 192 struct timeval, retrieved using gettimeofday, and resolution is 193 unknown. 194 195 This method is used Unix systems without POSIX timers. */ 196 197typedef struct timeval ptimer_system_time; 198 199#define IMPL_measure gettimeofday_measure 200#define IMPL_diff gettimeofday_diff 201#define IMPL_resolution gettimeofday_resolution 202 203static inline void 204gettimeofday_measure (ptimer_system_time *pst) 205{ 206 gettimeofday (pst, NULL); 207} 208 209static inline double 210gettimeofday_diff (ptimer_system_time *pst1, ptimer_system_time *pst2) 211{ 212 return ((pst1->tv_sec - pst2->tv_sec) 213 + (pst1->tv_usec - pst2->tv_usec) / 1e6); 214} 215 216static inline double 217gettimeofday_resolution (void) 218{ 219 /* Granularity of gettimeofday varies wildly between architectures. 220 However, it appears that on modern machines it tends to be better 221 than 1ms. Assume 100 usecs. */ 222 return 0.1; 223} 224#endif /* PTIMER_GETTIMEOFDAY */ 225 226#ifdef PTIMER_WINDOWS 227/* Elapsed time measurement on Windows: where high-resolution timers 228 are available, time is stored in a LARGE_INTEGER and retrieved 229 using QueryPerformanceCounter. Otherwise, it is stored in a DWORD 230 and retrieved using GetTickCount. 231 232 This method is used on Windows. */ 233 234typedef union { 235 DWORD lores; /* In case GetTickCount is used */ 236 LARGE_INTEGER hires; /* In case high-resolution timer is used */ 237} ptimer_system_time; 238 239#define IMPL_init windows_init 240#define IMPL_measure windows_measure 241#define IMPL_diff windows_diff 242#define IMPL_resolution windows_resolution 243 244/* Whether high-resolution timers are used. Set by ptimer_initialize_once 245 the first time ptimer_new is called. */ 246static bool windows_hires_timers; 247 248/* Frequency of high-resolution timers -- number of updates per 249 second. Calculated the first time ptimer_new is called provided 250 that high-resolution timers are available. */ 251static double windows_hires_freq; 252 253static void 254windows_init (void) 255{ 256 LARGE_INTEGER freq; 257 freq.QuadPart = 0; 258 QueryPerformanceFrequency (&freq); 259 if (freq.QuadPart != 0) 260 { 261 windows_hires_timers = true; 262 windows_hires_freq = (double) freq.QuadPart; 263 } 264} 265 266static inline void 267windows_measure (ptimer_system_time *pst) 268{ 269 if (windows_hires_timers) 270 QueryPerformanceCounter (&pst->hires); 271 else 272 /* Where hires counters are not available, use GetTickCount rather 273 GetSystemTime, because it is unaffected by clock skew and 274 simpler to use. Note that overflows don't affect us because we 275 never use absolute values of the ticker, only the 276 differences. */ 277 pst->lores = GetTickCount (); 278} 279 280static inline double 281windows_diff (ptimer_system_time *pst1, ptimer_system_time *pst2) 282{ 283 if (windows_hires_timers) 284 return (pst1->hires.QuadPart - pst2->hires.QuadPart) / windows_hires_freq; 285 else 286 return pst1->lores - pst2->lores; 287} 288 289static double 290windows_resolution (void) 291{ 292 if (windows_hires_timers) 293 return 1.0 / windows_hires_freq; 294 else 295 return 10; /* according to MSDN */ 296} 297#endif /* PTIMER_WINDOWS */ 298 299/* The code below this point is independent of timer implementation. */ 300 301struct ptimer { 302 /* The starting point in time which, subtracted from the current 303 time, yields elapsed time. */ 304 ptimer_system_time start; 305 306 /* The most recent elapsed time, calculated by ptimer_measure(). */ 307 double elapsed_last; 308 309 /* Approximately, the time elapsed between the true start of the 310 measurement and the time represented by START. This is used for 311 adjustment when clock skew is detected. */ 312 double elapsed_pre_start; 313}; 314 315/* Allocate a new timer and reset it. Return the new timer. */ 316 317struct ptimer * 318ptimer_new (void) 319{ 320 struct ptimer *pt = xnew0 (struct ptimer); 321#ifdef IMPL_init 322 static bool init_done; 323 if (!init_done) 324 { 325 init_done = true; 326 IMPL_init (); 327 } 328#endif 329 ptimer_reset (pt); 330 return pt; 331} 332 333/* Free the resources associated with the timer. Its further use is 334 prohibited. */ 335 336void 337ptimer_destroy (struct ptimer *pt) 338{ 339 xfree (pt); 340} 341 342/* Reset timer PT. This establishes the starting point from which 343 ptimer_measure() will return the elapsed time in seconds. It is 344 allowed to reset a previously used timer. */ 345 346void 347ptimer_reset (struct ptimer *pt) 348{ 349 /* Set the start time to the current time. */ 350 IMPL_measure (&pt->start); 351 pt->elapsed_last = 0; 352 pt->elapsed_pre_start = 0; 353} 354 355/* Measure the elapsed time since timer creation/reset. This causes 356 the timer to internally call clock_gettime (or gettimeofday, etc.) 357 to update its idea of current time. The time is returned, but is 358 also stored for later access through ptimer_read(). 359 360 This function handles clock skew, i.e. time that moves backwards is 361 ignored. */ 362 363double 364ptimer_measure (struct ptimer *pt) 365{ 366 ptimer_system_time now; 367 double elapsed; 368 369 IMPL_measure (&now); 370 elapsed = pt->elapsed_pre_start + IMPL_diff (&now, &pt->start); 371 372 /* Ideally we'd just return the difference between NOW and 373 pt->start. However, the system timer can be set back, and we 374 could return a value smaller than when we were last called, even 375 a negative value. Both of these would confuse the callers, which 376 expect us to return monotonically nondecreasing values. 377 378 Therefore: if ELAPSED is smaller than its previous known value, 379 we reset pt->start to the current time and effectively start 380 measuring from this point. But since we don't want the elapsed 381 value to start from zero, we set elapsed_pre_start to the last 382 elapsed time and increment all future calculations by that 383 amount. 384 385 This cannot happen with Windows and POSIX monotonic/highres 386 timers, but the check is not expensive. */ 387 388 if (elapsed < pt->elapsed_last) 389 { 390 pt->start = now; 391 pt->elapsed_pre_start = pt->elapsed_last; 392 elapsed = pt->elapsed_last; 393 } 394 395 pt->elapsed_last = elapsed; 396 return elapsed; 397} 398 399/* Return the most recent elapsed time measured with ptimer_measure. 400 If ptimer_measure has not yet been called since the timer was 401 created or reset, this returns 0. */ 402 403double 404ptimer_read (const struct ptimer *pt) 405{ 406 return pt->elapsed_last; 407} 408 409/* Return the assessed resolution of the timer implementation, in 410 seconds. This is used by code that tries to substitute a better 411 value for timers that have returned zero. */ 412 413double 414ptimer_resolution (void) 415{ 416 return IMPL_resolution (); 417} 418