1290001Sglebius/* 2290001Sglebius * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 3290001Sglebius * 4290001Sglebius * Redistribution and use in source and binary forms, with or without 5290001Sglebius * modification, are permitted provided that the following conditions 6290001Sglebius * are met: 7290001Sglebius * 1. Redistributions of source code must retain the above copyright 8290001Sglebius * notice, this list of conditions and the following disclaimer. 9290001Sglebius * 2. Redistributions in binary form must reproduce the above copyright 10290001Sglebius * notice, this list of conditions and the following disclaimer in the 11290001Sglebius * documentation and/or other materials provided with the distribution. 12290001Sglebius * 3. The name of the author may not be used to endorse or promote products 13290001Sglebius * derived from this software without specific prior written permission. 14290001Sglebius * 15290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16290001Sglebius * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17290001Sglebius * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18290001Sglebius * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19290001Sglebius * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20290001Sglebius * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21290001Sglebius * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22290001Sglebius * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23290001Sglebius * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24290001Sglebius * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25290001Sglebius */ 26290001Sglebius 27290001Sglebius#include "event2/event-config.h" 28290001Sglebius#include "evconfig-private.h" 29290001Sglebius 30290001Sglebius#ifdef _WIN32 31290001Sglebius#include <winsock2.h> 32290001Sglebius#define WIN32_LEAN_AND_MEAN 33290001Sglebius#include <windows.h> 34290001Sglebius#undef WIN32_LEAN_AND_MEAN 35290001Sglebius#endif 36290001Sglebius 37290001Sglebius#include <sys/types.h> 38290001Sglebius#ifdef EVENT__HAVE_STDLIB_H 39290001Sglebius#include <stdlib.h> 40290001Sglebius#endif 41290001Sglebius#include <errno.h> 42290001Sglebius#include <limits.h> 43290001Sglebius#ifndef EVENT__HAVE_GETTIMEOFDAY 44290001Sglebius#include <sys/timeb.h> 45290001Sglebius#endif 46290001Sglebius#if !defined(EVENT__HAVE_NANOSLEEP) && !defined(EVENT_HAVE_USLEEP) && \ 47290001Sglebius !defined(_WIN32) 48290001Sglebius#include <sys/select.h> 49290001Sglebius#endif 50290001Sglebius#include <time.h> 51290001Sglebius#include <sys/stat.h> 52290001Sglebius#include <string.h> 53290001Sglebius 54290001Sglebius#include "event2/util.h" 55290001Sglebius#include "util-internal.h" 56290001Sglebius#include "log-internal.h" 57290001Sglebius#include "mm-internal.h" 58290001Sglebius 59290001Sglebius#ifndef EVENT__HAVE_GETTIMEOFDAY 60290001Sglebius/* No gettimeofday; this must be windows. */ 61290001Sglebiusint 62290001Sglebiusevutil_gettimeofday(struct timeval *tv, struct timezone *tz) 63290001Sglebius{ 64290001Sglebius#ifdef _MSC_VER 65290001Sglebius#define U64_LITERAL(n) n##ui64 66290001Sglebius#else 67290001Sglebius#define U64_LITERAL(n) n##llu 68290001Sglebius#endif 69290001Sglebius 70290001Sglebius /* Conversion logic taken from Tor, which in turn took it 71290001Sglebius * from Perl. GetSystemTimeAsFileTime returns its value as 72290001Sglebius * an unaligned (!) 64-bit value containing the number of 73290001Sglebius * 100-nanosecond intervals since 1 January 1601 UTC. */ 74290001Sglebius#define EPOCH_BIAS U64_LITERAL(116444736000000000) 75290001Sglebius#define UNITS_PER_SEC U64_LITERAL(10000000) 76290001Sglebius#define USEC_PER_SEC U64_LITERAL(1000000) 77290001Sglebius#define UNITS_PER_USEC U64_LITERAL(10) 78290001Sglebius union { 79290001Sglebius FILETIME ft_ft; 80290001Sglebius ev_uint64_t ft_64; 81290001Sglebius } ft; 82290001Sglebius 83290001Sglebius if (tv == NULL) 84290001Sglebius return -1; 85290001Sglebius 86290001Sglebius GetSystemTimeAsFileTime(&ft.ft_ft); 87290001Sglebius 88290001Sglebius if (EVUTIL_UNLIKELY(ft.ft_64 < EPOCH_BIAS)) { 89290001Sglebius /* Time before the unix epoch. */ 90290001Sglebius return -1; 91290001Sglebius } 92290001Sglebius ft.ft_64 -= EPOCH_BIAS; 93290001Sglebius tv->tv_sec = (long) (ft.ft_64 / UNITS_PER_SEC); 94290001Sglebius tv->tv_usec = (long) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC); 95290001Sglebius return 0; 96290001Sglebius} 97290001Sglebius#endif 98290001Sglebius 99290001Sglebius#define MAX_SECONDS_IN_MSEC_LONG \ 100290001Sglebius (((LONG_MAX) - 999) / 1000) 101290001Sglebius 102290001Sglebiuslong 103290001Sglebiusevutil_tv_to_msec_(const struct timeval *tv) 104290001Sglebius{ 105290001Sglebius if (tv->tv_usec > 1000000 || tv->tv_sec > MAX_SECONDS_IN_MSEC_LONG) 106290001Sglebius return -1; 107290001Sglebius 108290001Sglebius return (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000); 109290001Sglebius} 110290001Sglebius 111290001Sglebius/* 112290001Sglebius Replacement for usleep on platforms that don't have one. Not guaranteed to 113290001Sglebius be any more finegrained than 1 msec. 114290001Sglebius */ 115290001Sglebiusvoid 116290001Sglebiusevutil_usleep_(const struct timeval *tv) 117290001Sglebius{ 118290001Sglebius if (!tv) 119290001Sglebius return; 120290001Sglebius#if defined(_WIN32) 121290001Sglebius { 122290001Sglebius long msec = evutil_tv_to_msec_(tv); 123290001Sglebius Sleep((DWORD)msec); 124290001Sglebius } 125290001Sglebius#elif defined(EVENT__HAVE_NANOSLEEP) 126290001Sglebius { 127290001Sglebius struct timespec ts; 128290001Sglebius ts.tv_sec = tv->tv_sec; 129290001Sglebius ts.tv_nsec = tv->tv_usec*1000; 130290001Sglebius nanosleep(&ts, NULL); 131290001Sglebius } 132290001Sglebius#elif defined(EVENT__HAVE_USLEEP) 133290001Sglebius /* Some systems don't like to usleep more than 999999 usec */ 134290001Sglebius sleep(tv->tv_sec); 135290001Sglebius usleep(tv->tv_usec); 136290001Sglebius#else 137290001Sglebius select(0, NULL, NULL, NULL, tv); 138290001Sglebius#endif 139290001Sglebius} 140290001Sglebius 141290001Sglebius/* 142290001Sglebius This function assumes it's called repeatedly with a 143290001Sglebius not-actually-so-monotonic time source whose outputs are in 'tv'. It 144290001Sglebius implements a trivial ratcheting mechanism so that the values never go 145290001Sglebius backwards. 146290001Sglebius */ 147290001Sglebiusstatic void 148290001Sglebiusadjust_monotonic_time(struct evutil_monotonic_timer *base, 149290001Sglebius struct timeval *tv) 150290001Sglebius{ 151290001Sglebius evutil_timeradd(tv, &base->adjust_monotonic_clock, tv); 152290001Sglebius 153290001Sglebius if (evutil_timercmp(tv, &base->last_time, <)) { 154290001Sglebius /* Guess it wasn't monotonic after all. */ 155290001Sglebius struct timeval adjust; 156290001Sglebius evutil_timersub(&base->last_time, tv, &adjust); 157290001Sglebius evutil_timeradd(&adjust, &base->adjust_monotonic_clock, 158290001Sglebius &base->adjust_monotonic_clock); 159290001Sglebius *tv = base->last_time; 160290001Sglebius } 161290001Sglebius base->last_time = *tv; 162290001Sglebius} 163290001Sglebius 164290001Sglebius/* 165290001Sglebius Allocate a new struct evutil_monotonic_timer 166290001Sglebius */ 167290001Sglebiusstruct evutil_monotonic_timer * 168290001Sglebiusevutil_monotonic_timer_new(void) 169290001Sglebius{ 170290001Sglebius struct evutil_monotonic_timer *p = NULL; 171290001Sglebius 172290001Sglebius p = mm_malloc(sizeof(*p)); 173290001Sglebius if (!p) goto done; 174290001Sglebius 175290001Sglebius memset(p, 0, sizeof(*p)); 176290001Sglebius 177290001Sglebius done: 178290001Sglebius return p; 179290001Sglebius} 180290001Sglebius 181290001Sglebius/* 182290001Sglebius Free a struct evutil_monotonic_timer 183290001Sglebius */ 184290001Sglebiusvoid 185290001Sglebiusevutil_monotonic_timer_free(struct evutil_monotonic_timer *timer) 186290001Sglebius{ 187290001Sglebius if (timer) { 188290001Sglebius mm_free(timer); 189290001Sglebius } 190290001Sglebius} 191290001Sglebius 192290001Sglebius/* 193290001Sglebius Set up a struct evutil_monotonic_timer for initial use 194290001Sglebius */ 195290001Sglebiusint 196290001Sglebiusevutil_configure_monotonic_time(struct evutil_monotonic_timer *timer, 197290001Sglebius int flags) 198290001Sglebius{ 199290001Sglebius return evutil_configure_monotonic_time_(timer, flags); 200290001Sglebius} 201290001Sglebius 202290001Sglebius/* 203290001Sglebius Query the current monotonic time 204290001Sglebius */ 205290001Sglebiusint 206290001Sglebiusevutil_gettime_monotonic(struct evutil_monotonic_timer *timer, 207290001Sglebius struct timeval *tp) 208290001Sglebius{ 209290001Sglebius return evutil_gettime_monotonic_(timer, tp); 210290001Sglebius} 211290001Sglebius 212290001Sglebius 213290001Sglebius#if defined(HAVE_POSIX_MONOTONIC) 214290001Sglebius/* ===== 215290001Sglebius The POSIX clock_gettime() interface provides a few ways to get at a 216290001Sglebius monotonic clock. CLOCK_MONOTONIC is most widely supported. Linux also 217290001Sglebius provides a CLOCK_MONOTONIC_COARSE with accuracy of about 1-4 msec. 218290001Sglebius 219290001Sglebius On all platforms I'm aware of, CLOCK_MONOTONIC really is monotonic. 220290001Sglebius Platforms don't agree about whether it should jump on a sleep/resume. 221290001Sglebius */ 222290001Sglebius 223290001Sglebiusint 224290001Sglebiusevutil_configure_monotonic_time_(struct evutil_monotonic_timer *base, 225290001Sglebius int flags) 226290001Sglebius{ 227290001Sglebius /* CLOCK_MONOTONIC exists on FreeBSD, Linux, and Solaris. You need to 228290001Sglebius * check for it at runtime, because some older kernel versions won't 229290001Sglebius * have it working. */ 230290001Sglebius#ifdef CLOCK_MONOTONIC_COARSE 231290001Sglebius const int precise = flags & EV_MONOT_PRECISE; 232290001Sglebius#endif 233290001Sglebius const int fallback = flags & EV_MONOT_FALLBACK; 234290001Sglebius struct timespec ts; 235290001Sglebius 236290001Sglebius#ifdef CLOCK_MONOTONIC_COARSE 237290001Sglebius if (CLOCK_MONOTONIC_COARSE < 0) { 238290001Sglebius /* Technically speaking, nothing keeps CLOCK_* from being 239290001Sglebius * negative (as far as I know). This check and the one below 240290001Sglebius * make sure that it's safe for us to use -1 as an "unset" 241290001Sglebius * value. */ 242290001Sglebius event_errx(1,"I didn't expect CLOCK_MONOTONIC_COARSE to be < 0"); 243290001Sglebius } 244290001Sglebius if (! precise && ! fallback) { 245290001Sglebius if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) { 246290001Sglebius base->monotonic_clock = CLOCK_MONOTONIC_COARSE; 247290001Sglebius return 0; 248290001Sglebius } 249290001Sglebius } 250290001Sglebius#endif 251290001Sglebius if (!fallback && clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { 252290001Sglebius base->monotonic_clock = CLOCK_MONOTONIC; 253290001Sglebius return 0; 254290001Sglebius } 255290001Sglebius 256290001Sglebius if (CLOCK_MONOTONIC < 0) { 257290001Sglebius event_errx(1,"I didn't expect CLOCK_MONOTONIC to be < 0"); 258290001Sglebius } 259290001Sglebius 260290001Sglebius base->monotonic_clock = -1; 261290001Sglebius return 0; 262290001Sglebius} 263290001Sglebius 264290001Sglebiusint 265290001Sglebiusevutil_gettime_monotonic_(struct evutil_monotonic_timer *base, 266290001Sglebius struct timeval *tp) 267290001Sglebius{ 268290001Sglebius struct timespec ts; 269290001Sglebius 270290001Sglebius if (base->monotonic_clock < 0) { 271290001Sglebius if (evutil_gettimeofday(tp, NULL) < 0) 272290001Sglebius return -1; 273290001Sglebius adjust_monotonic_time(base, tp); 274290001Sglebius return 0; 275290001Sglebius } 276290001Sglebius 277290001Sglebius if (clock_gettime(base->monotonic_clock, &ts) == -1) 278290001Sglebius return -1; 279290001Sglebius tp->tv_sec = ts.tv_sec; 280290001Sglebius tp->tv_usec = ts.tv_nsec / 1000; 281290001Sglebius 282290001Sglebius return 0; 283290001Sglebius} 284290001Sglebius#endif 285290001Sglebius 286290001Sglebius#if defined(HAVE_MACH_MONOTONIC) 287290001Sglebius/* ====== 288290001Sglebius Apple is a little late to the POSIX party. And why not? Instead of 289290001Sglebius clock_gettime(), they provide mach_absolute_time(). Its units are not 290290001Sglebius fixed; we need to use mach_timebase_info() to get the right functions to 291290001Sglebius convert its units into nanoseconds. 292290001Sglebius 293290001Sglebius To all appearances, mach_absolute_time() seems to be honest-to-goodness 294290001Sglebius monotonic. Whether it stops during sleep or not is unspecified in 295290001Sglebius principle, and dependent on CPU architecture in practice. 296290001Sglebius */ 297290001Sglebius 298290001Sglebiusint 299290001Sglebiusevutil_configure_monotonic_time_(struct evutil_monotonic_timer *base, 300290001Sglebius int flags) 301290001Sglebius{ 302290001Sglebius const int fallback = flags & EV_MONOT_FALLBACK; 303290001Sglebius struct mach_timebase_info mi; 304290001Sglebius memset(base, 0, sizeof(*base)); 305290001Sglebius /* OSX has mach_absolute_time() */ 306290001Sglebius if (!fallback && 307290001Sglebius mach_timebase_info(&mi) == 0 && 308290001Sglebius mach_absolute_time() != 0) { 309290001Sglebius /* mach_timebase_info tells us how to convert 310290001Sglebius * mach_absolute_time() into nanoseconds, but we 311290001Sglebius * want to use microseconds instead. */ 312290001Sglebius mi.denom *= 1000; 313290001Sglebius memcpy(&base->mach_timebase_units, &mi, sizeof(mi)); 314290001Sglebius } else { 315290001Sglebius base->mach_timebase_units.numer = 0; 316290001Sglebius } 317290001Sglebius return 0; 318290001Sglebius} 319290001Sglebius 320290001Sglebiusint 321290001Sglebiusevutil_gettime_monotonic_(struct evutil_monotonic_timer *base, 322290001Sglebius struct timeval *tp) 323290001Sglebius{ 324290001Sglebius ev_uint64_t abstime, usec; 325290001Sglebius if (base->mach_timebase_units.numer == 0) { 326290001Sglebius if (evutil_gettimeofday(tp, NULL) < 0) 327290001Sglebius return -1; 328290001Sglebius adjust_monotonic_time(base, tp); 329290001Sglebius return 0; 330290001Sglebius } 331290001Sglebius 332290001Sglebius abstime = mach_absolute_time(); 333290001Sglebius usec = (abstime * base->mach_timebase_units.numer) 334290001Sglebius / (base->mach_timebase_units.denom); 335290001Sglebius tp->tv_sec = usec / 1000000; 336290001Sglebius tp->tv_usec = usec % 1000000; 337290001Sglebius 338290001Sglebius return 0; 339290001Sglebius} 340290001Sglebius#endif 341290001Sglebius 342290001Sglebius#if defined(HAVE_WIN32_MONOTONIC) 343290001Sglebius/* ===== 344290001Sglebius Turn we now to Windows. Want monontonic time on Windows? 345290001Sglebius 346290001Sglebius Windows has QueryPerformanceCounter(), which gives time most high- 347290001Sglebius resolution time. It's a pity it's not so monotonic in practice; it's 348290001Sglebius also got some fun bugs, especially: with older Windowses, under 349290001Sglebius virtualizations, with funny hardware, on multiprocessor systems, and so 350290001Sglebius on. PEP418 [1] has a nice roundup of the issues here. 351290001Sglebius 352290001Sglebius There's GetTickCount64() on Vista and later, which gives a number of 1-msec 353290001Sglebius ticks since startup. The accuracy here might be as bad as 10-20 msec, I 354290001Sglebius hear. There's an undocumented function (NtSetTimerResolution) that 355290001Sglebius allegedly increases the accuracy. Good luck! 356290001Sglebius 357290001Sglebius There's also GetTickCount(), which is only 32 bits, but seems to be 358290001Sglebius supported on pre-Vista versions of Windows. Apparently, you can coax 359290001Sglebius another 14 bits out of it, giving you 2231 years before rollover. 360290001Sglebius 361290001Sglebius The less said about timeGetTime() the better. 362290001Sglebius 363290001Sglebius "We don't care. We don't have to. We're the Phone Company." 364290001Sglebius -- Lily Tomlin, SNL 365290001Sglebius 366290001Sglebius Our strategy, if precise timers are turned off, is to just use the best 367290001Sglebius GetTickCount equivalent available. If we've been asked for precise timing, 368290001Sglebius then we mostly[2] assume that GetTickCount is monotonic, and correct 369290001Sglebius GetPerformanceCounter to approximate it. 370290001Sglebius 371290001Sglebius [1] http://www.python.org/dev/peps/pep-0418 372290001Sglebius [2] Of course, we feed the Windows stuff into adjust_monotonic_time() 373290001Sglebius anyway, just in case it isn't. 374290001Sglebius 375290001Sglebius */ 376290001Sglebius/* 377290001Sglebius Parts of our logic in the win32 timer code here are closely based on 378290001Sglebius BitTorrent's libUTP library. That code is subject to the following 379290001Sglebius license: 380290001Sglebius 381290001Sglebius Copyright (c) 2010 BitTorrent, Inc. 382290001Sglebius 383290001Sglebius Permission is hereby granted, free of charge, to any person obtaining a 384290001Sglebius copy of this software and associated documentation files (the 385290001Sglebius "Software"), to deal in the Software without restriction, including 386290001Sglebius without limitation the rights to use, copy, modify, merge, publish, 387290001Sglebius distribute, sublicense, and/or sell copies of the Software, and to 388290001Sglebius permit persons to whom the Software is furnished to do so, subject to 389290001Sglebius the following conditions: 390290001Sglebius 391290001Sglebius The above copyright notice and this permission notice shall be included 392290001Sglebius in all copies or substantial portions of the Software. 393290001Sglebius 394290001Sglebius THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 395290001Sglebius OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 396290001Sglebius MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 397290001Sglebius NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 398290001Sglebius LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 399290001Sglebius OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 400290001Sglebius WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 401290001Sglebius*/ 402290001Sglebius 403290001Sglebiusstatic ev_uint64_t 404290001Sglebiusevutil_GetTickCount_(struct evutil_monotonic_timer *base) 405290001Sglebius{ 406290001Sglebius if (base->GetTickCount64_fn) { 407290001Sglebius /* Let's just use GetTickCount64 if we can. */ 408290001Sglebius return base->GetTickCount64_fn(); 409290001Sglebius } else if (base->GetTickCount_fn) { 410290001Sglebius /* Greg Hazel assures me that this works, that BitTorrent has 411290001Sglebius * done it for years, and this it won't turn around and 412290001Sglebius * bite us. He says they found it on some game programmers' 413290001Sglebius * forum some time around 2007. 414290001Sglebius */ 415290001Sglebius ev_uint64_t v = base->GetTickCount_fn(); 416290001Sglebius return (DWORD)v | ((v >> 18) & 0xFFFFFFFF00000000); 417290001Sglebius } else { 418290001Sglebius /* Here's the fallback implementation. We have to use 419290001Sglebius * GetTickCount() with its given signature, so we only get 420290001Sglebius * 32 bits worth of milliseconds, which will roll ove every 421290001Sglebius * 49 days or so. */ 422290001Sglebius DWORD ticks = GetTickCount(); 423290001Sglebius if (ticks < base->last_tick_count) { 424290001Sglebius base->adjust_tick_count += ((ev_uint64_t)1) << 32; 425290001Sglebius } 426290001Sglebius base->last_tick_count = ticks; 427290001Sglebius return ticks + base->adjust_tick_count; 428290001Sglebius } 429290001Sglebius} 430290001Sglebius 431290001Sglebiusint 432290001Sglebiusevutil_configure_monotonic_time_(struct evutil_monotonic_timer *base, 433290001Sglebius int flags) 434290001Sglebius{ 435290001Sglebius const int precise = flags & EV_MONOT_PRECISE; 436290001Sglebius const int fallback = flags & EV_MONOT_FALLBACK; 437290001Sglebius HANDLE h; 438290001Sglebius memset(base, 0, sizeof(*base)); 439290001Sglebius 440290001Sglebius h = evutil_load_windows_system_library_(TEXT("kernel32.dll")); 441290001Sglebius if (h != NULL && !fallback) { 442290001Sglebius base->GetTickCount64_fn = (ev_GetTickCount_func)GetProcAddress(h, "GetTickCount64"); 443290001Sglebius base->GetTickCount_fn = (ev_GetTickCount_func)GetProcAddress(h, "GetTickCount"); 444290001Sglebius } 445290001Sglebius 446290001Sglebius base->first_tick = base->last_tick_count = evutil_GetTickCount_(base); 447290001Sglebius if (precise && !fallback) { 448290001Sglebius LARGE_INTEGER freq; 449290001Sglebius if (QueryPerformanceFrequency(&freq)) { 450290001Sglebius LARGE_INTEGER counter; 451290001Sglebius QueryPerformanceCounter(&counter); 452290001Sglebius base->first_counter = counter.QuadPart; 453290001Sglebius base->usec_per_count = 1.0e6 / freq.QuadPart; 454290001Sglebius base->use_performance_counter = 1; 455290001Sglebius } 456290001Sglebius } 457290001Sglebius 458290001Sglebius return 0; 459290001Sglebius} 460290001Sglebius 461290001Sglebiusstatic inline ev_int64_t 462290001Sglebiusabs64(ev_int64_t i) 463290001Sglebius{ 464290001Sglebius return i < 0 ? -i : i; 465290001Sglebius} 466290001Sglebius 467290001Sglebius 468290001Sglebiusint 469290001Sglebiusevutil_gettime_monotonic_(struct evutil_monotonic_timer *base, 470290001Sglebius struct timeval *tp) 471290001Sglebius{ 472290001Sglebius ev_uint64_t ticks = evutil_GetTickCount_(base); 473290001Sglebius if (base->use_performance_counter) { 474290001Sglebius /* Here's a trick we took from BitTorrent's libutp, at Greg 475290001Sglebius * Hazel's recommendation. We use QueryPerformanceCounter for 476290001Sglebius * our high-resolution timer, but use GetTickCount*() to keep 477290001Sglebius * it sane, and adjust_monotonic_time() to keep it monotonic. 478290001Sglebius */ 479290001Sglebius LARGE_INTEGER counter; 480290001Sglebius ev_int64_t counter_elapsed, counter_usec_elapsed, ticks_elapsed; 481290001Sglebius QueryPerformanceCounter(&counter); 482290001Sglebius counter_elapsed = (ev_int64_t) 483290001Sglebius (counter.QuadPart - base->first_counter); 484290001Sglebius ticks_elapsed = ticks - base->first_tick; 485290001Sglebius /* TODO: This may upset VC6. If you need this to work with 486290001Sglebius * VC6, please supply an appropriate patch. */ 487290001Sglebius counter_usec_elapsed = (ev_int64_t) 488290001Sglebius (counter_elapsed * base->usec_per_count); 489290001Sglebius 490290001Sglebius if (abs64(ticks_elapsed*1000 - counter_usec_elapsed) > 1000000) { 491290001Sglebius /* It appears that the QueryPerformanceCounter() 492290001Sglebius * result is more than 1 second away from 493290001Sglebius * GetTickCount() result. Let's adjust it to be as 494290001Sglebius * accurate as we can; adjust_monotnonic_time() below 495290001Sglebius * will keep it monotonic. */ 496290001Sglebius counter_usec_elapsed = ticks_elapsed * 1000; 497290001Sglebius base->first_counter = (ev_uint64_t) (counter.QuadPart - counter_usec_elapsed / base->usec_per_count); 498290001Sglebius } 499290001Sglebius tp->tv_sec = (time_t) (counter_usec_elapsed / 1000000); 500290001Sglebius tp->tv_usec = counter_usec_elapsed % 1000000; 501290001Sglebius 502290001Sglebius } else { 503290001Sglebius /* We're just using GetTickCount(). */ 504290001Sglebius tp->tv_sec = (time_t) (ticks / 1000); 505290001Sglebius tp->tv_usec = (ticks % 1000) * 1000; 506290001Sglebius } 507290001Sglebius adjust_monotonic_time(base, tp); 508290001Sglebius 509290001Sglebius return 0; 510290001Sglebius} 511290001Sglebius#endif 512290001Sglebius 513290001Sglebius#if defined(HAVE_FALLBACK_MONOTONIC) 514290001Sglebius/* ===== 515290001Sglebius And if none of the other options work, let's just use gettimeofday(), and 516290001Sglebius ratchet it forward so that it acts like a monotonic timer, whether it 517290001Sglebius wants to or not. 518290001Sglebius */ 519290001Sglebius 520290001Sglebiusint 521290001Sglebiusevutil_configure_monotonic_time_(struct evutil_monotonic_timer *base, 522290001Sglebius int precise) 523290001Sglebius{ 524290001Sglebius memset(base, 0, sizeof(*base)); 525290001Sglebius return 0; 526290001Sglebius} 527290001Sglebius 528290001Sglebiusint 529290001Sglebiusevutil_gettime_monotonic_(struct evutil_monotonic_timer *base, 530290001Sglebius struct timeval *tp) 531290001Sglebius{ 532290001Sglebius if (evutil_gettimeofday(tp, NULL) < 0) 533290001Sglebius return -1; 534290001Sglebius adjust_monotonic_time(base, tp); 535290001Sglebius return 0; 536290001Sglebius 537290001Sglebius} 538290001Sglebius#endif 539