1275970Scy/*
2275970Scy * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
3275970Scy *
4275970Scy * Redistribution and use in source and binary forms, with or without
5275970Scy * modification, are permitted provided that the following conditions
6275970Scy * are met:
7275970Scy * 1. Redistributions of source code must retain the above copyright
8275970Scy *    notice, this list of conditions and the following disclaimer.
9275970Scy * 2. Redistributions in binary form must reproduce the above copyright
10275970Scy *    notice, this list of conditions and the following disclaimer in the
11275970Scy *    documentation and/or other materials provided with the distribution.
12275970Scy * 3. The name of the author may not be used to endorse or promote products
13275970Scy *    derived from this software without specific prior written permission.
14275970Scy *
15275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25275970Scy */
26275970Scy
27275970Scy#include "event2/event-config.h"
28275970Scy#include "evconfig-private.h"
29275970Scy
30275970Scy#ifdef _WIN32
31275970Scy#include <winsock2.h>
32275970Scy#define WIN32_LEAN_AND_MEAN
33275970Scy#include <windows.h>
34275970Scy#undef WIN32_LEAN_AND_MEAN
35275970Scy#endif
36275970Scy
37275970Scy#include <sys/types.h>
38275970Scy#ifdef EVENT__HAVE_STDLIB_H
39275970Scy#include <stdlib.h>
40275970Scy#endif
41275970Scy#include <errno.h>
42275970Scy#include <limits.h>
43275970Scy#ifndef EVENT__HAVE_GETTIMEOFDAY
44275970Scy#include <sys/timeb.h>
45275970Scy#endif
46275970Scy#if !defined(EVENT__HAVE_NANOSLEEP) && !defined(EVENT_HAVE_USLEEP) && \
47275970Scy	!defined(_WIN32)
48275970Scy#include <sys/select.h>
49275970Scy#endif
50275970Scy#include <time.h>
51275970Scy#include <sys/stat.h>
52275970Scy#include <string.h>
53275970Scy
54275970Scy#include "event2/util.h"
55275970Scy#include "util-internal.h"
56275970Scy#include "log-internal.h"
57285612Sdelphij#include "mm-internal.h"
58275970Scy
59275970Scy#ifndef EVENT__HAVE_GETTIMEOFDAY
60275970Scy/* No gettimeofday; this must be windows. */
61275970Scyint
62275970Scyevutil_gettimeofday(struct timeval *tv, struct timezone *tz)
63275970Scy{
64275970Scy#ifdef _MSC_VER
65275970Scy#define U64_LITERAL(n) n##ui64
66275970Scy#else
67275970Scy#define U64_LITERAL(n) n##llu
68275970Scy#endif
69275970Scy
70275970Scy	/* Conversion logic taken from Tor, which in turn took it
71275970Scy	 * from Perl.  GetSystemTimeAsFileTime returns its value as
72275970Scy	 * an unaligned (!) 64-bit value containing the number of
73275970Scy	 * 100-nanosecond intervals since 1 January 1601 UTC. */
74275970Scy#define EPOCH_BIAS U64_LITERAL(116444736000000000)
75275970Scy#define UNITS_PER_SEC U64_LITERAL(10000000)
76275970Scy#define USEC_PER_SEC U64_LITERAL(1000000)
77275970Scy#define UNITS_PER_USEC U64_LITERAL(10)
78275970Scy	union {
79275970Scy		FILETIME ft_ft;
80275970Scy		ev_uint64_t ft_64;
81275970Scy	} ft;
82275970Scy
83275970Scy	if (tv == NULL)
84275970Scy		return -1;
85275970Scy
86275970Scy	GetSystemTimeAsFileTime(&ft.ft_ft);
87275970Scy
88275970Scy	if (EVUTIL_UNLIKELY(ft.ft_64 < EPOCH_BIAS)) {
89275970Scy		/* Time before the unix epoch. */
90275970Scy		return -1;
91275970Scy	}
92275970Scy	ft.ft_64 -= EPOCH_BIAS;
93275970Scy	tv->tv_sec = (long) (ft.ft_64 / UNITS_PER_SEC);
94275970Scy	tv->tv_usec = (long) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
95275970Scy	return 0;
96275970Scy}
97275970Scy#endif
98275970Scy
99275970Scy#define MAX_SECONDS_IN_MSEC_LONG \
100275970Scy	(((LONG_MAX) - 999) / 1000)
101275970Scy
102275970Scylong
103275970Scyevutil_tv_to_msec_(const struct timeval *tv)
104275970Scy{
105275970Scy	if (tv->tv_usec > 1000000 || tv->tv_sec > MAX_SECONDS_IN_MSEC_LONG)
106275970Scy		return -1;
107275970Scy
108275970Scy	return (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000);
109275970Scy}
110275970Scy
111275970Scy/*
112275970Scy  Replacement for usleep on platforms that don't have one.  Not guaranteed to
113275970Scy  be any more finegrained than 1 msec.
114275970Scy */
115275970Scyvoid
116275970Scyevutil_usleep_(const struct timeval *tv)
117275970Scy{
118275970Scy	if (!tv)
119275970Scy		return;
120275970Scy#if defined(_WIN32)
121275970Scy	{
122275970Scy		long msec = evutil_tv_to_msec_(tv);
123275970Scy		Sleep((DWORD)msec);
124275970Scy	}
125275970Scy#elif defined(EVENT__HAVE_NANOSLEEP)
126275970Scy	{
127275970Scy		struct timespec ts;
128275970Scy		ts.tv_sec = tv->tv_sec;
129275970Scy		ts.tv_nsec = tv->tv_usec*1000;
130275970Scy		nanosleep(&ts, NULL);
131275970Scy	}
132275970Scy#elif defined(EVENT__HAVE_USLEEP)
133275970Scy	/* Some systems don't like to usleep more than 999999 usec */
134275970Scy	sleep(tv->tv_sec);
135275970Scy	usleep(tv->tv_usec);
136275970Scy#else
137275970Scy	select(0, NULL, NULL, NULL, tv);
138275970Scy#endif
139275970Scy}
140275970Scy
141275970Scy/*
142275970Scy   This function assumes it's called repeatedly with a
143275970Scy   not-actually-so-monotonic time source whose outputs are in 'tv'. It
144275970Scy   implements a trivial ratcheting mechanism so that the values never go
145275970Scy   backwards.
146275970Scy */
147275970Scystatic void
148275970Scyadjust_monotonic_time(struct evutil_monotonic_timer *base,
149275970Scy    struct timeval *tv)
150275970Scy{
151275970Scy	evutil_timeradd(tv, &base->adjust_monotonic_clock, tv);
152275970Scy
153275970Scy	if (evutil_timercmp(tv, &base->last_time, <)) {
154275970Scy		/* Guess it wasn't monotonic after all. */
155275970Scy		struct timeval adjust;
156275970Scy		evutil_timersub(&base->last_time, tv, &adjust);
157275970Scy		evutil_timeradd(&adjust, &base->adjust_monotonic_clock,
158275970Scy		    &base->adjust_monotonic_clock);
159275970Scy		*tv = base->last_time;
160275970Scy	}
161275970Scy	base->last_time = *tv;
162275970Scy}
163275970Scy
164285612Sdelphij/*
165285612Sdelphij   Allocate a new struct evutil_monotonic_timer
166285612Sdelphij */
167285612Sdelphijstruct evutil_monotonic_timer *
168285612Sdelphijevutil_monotonic_timer_new(void)
169285612Sdelphij{
170285612Sdelphij  struct evutil_monotonic_timer *p = NULL;
171285612Sdelphij
172285612Sdelphij  p = mm_malloc(sizeof(*p));
173285612Sdelphij  if (!p) goto done;
174285612Sdelphij
175285612Sdelphij  memset(p, 0, sizeof(*p));
176285612Sdelphij
177285612Sdelphij done:
178285612Sdelphij  return p;
179285612Sdelphij}
180285612Sdelphij
181285612Sdelphij/*
182285612Sdelphij   Free a struct evutil_monotonic_timer
183285612Sdelphij */
184285612Sdelphijvoid
185285612Sdelphijevutil_monotonic_timer_free(struct evutil_monotonic_timer *timer)
186285612Sdelphij{
187285612Sdelphij  if (timer) {
188285612Sdelphij    mm_free(timer);
189285612Sdelphij  }
190285612Sdelphij}
191285612Sdelphij
192285612Sdelphij/*
193285612Sdelphij   Set up a struct evutil_monotonic_timer for initial use
194285612Sdelphij */
195285612Sdelphijint
196285612Sdelphijevutil_configure_monotonic_time(struct evutil_monotonic_timer *timer,
197285612Sdelphij                                int flags)
198285612Sdelphij{
199285612Sdelphij  return evutil_configure_monotonic_time_(timer, flags);
200285612Sdelphij}
201285612Sdelphij
202285612Sdelphij/*
203285612Sdelphij   Query the current monotonic time
204285612Sdelphij */
205285612Sdelphijint
206285612Sdelphijevutil_gettime_monotonic(struct evutil_monotonic_timer *timer,
207285612Sdelphij                         struct timeval *tp)
208285612Sdelphij{
209285612Sdelphij  return evutil_gettime_monotonic_(timer, tp);
210285612Sdelphij}
211285612Sdelphij
212285612Sdelphij
213275970Scy#if defined(HAVE_POSIX_MONOTONIC)
214275970Scy/* =====
215275970Scy   The POSIX clock_gettime() interface provides a few ways to get at a
216275970Scy   monotonic clock.  CLOCK_MONOTONIC is most widely supported.  Linux also
217275970Scy   provides a CLOCK_MONOTONIC_COARSE with accuracy of about 1-4 msec.
218275970Scy
219275970Scy   On all platforms I'm aware of, CLOCK_MONOTONIC really is monotonic.
220275970Scy   Platforms don't agree about whether it should jump on a sleep/resume.
221275970Scy */
222275970Scy
223275970Scyint
224275970Scyevutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
225275970Scy    int flags)
226275970Scy{
227275970Scy	/* CLOCK_MONOTONIC exists on FreeBSD, Linux, and Solaris.  You need to
228275970Scy	 * check for it at runtime, because some older kernel versions won't
229275970Scy	 * have it working. */
230275970Scy#ifdef CLOCK_MONOTONIC_COARSE
231275970Scy	const int precise = flags & EV_MONOT_PRECISE;
232275970Scy#endif
233275970Scy	const int fallback = flags & EV_MONOT_FALLBACK;
234275970Scy	struct timespec	ts;
235275970Scy
236275970Scy#ifdef CLOCK_MONOTONIC_COARSE
237275970Scy	if (CLOCK_MONOTONIC_COARSE < 0) {
238275970Scy		/* Technically speaking, nothing keeps CLOCK_* from being
239275970Scy		 * negative (as far as I know). This check and the one below
240275970Scy		 * make sure that it's safe for us to use -1 as an "unset"
241275970Scy		 * value. */
242275970Scy		event_errx(1,"I didn't expect CLOCK_MONOTONIC_COARSE to be < 0");
243275970Scy	}
244275970Scy	if (! precise && ! fallback) {
245275970Scy		if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) {
246275970Scy			base->monotonic_clock = CLOCK_MONOTONIC_COARSE;
247275970Scy			return 0;
248275970Scy		}
249275970Scy	}
250275970Scy#endif
251275970Scy	if (!fallback && clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
252275970Scy		base->monotonic_clock = CLOCK_MONOTONIC;
253275970Scy		return 0;
254275970Scy	}
255275970Scy
256275970Scy	if (CLOCK_MONOTONIC < 0) {
257275970Scy		event_errx(1,"I didn't expect CLOCK_MONOTONIC to be < 0");
258275970Scy	}
259275970Scy
260275970Scy	base->monotonic_clock = -1;
261275970Scy	return 0;
262275970Scy}
263275970Scy
264275970Scyint
265275970Scyevutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
266275970Scy    struct timeval *tp)
267275970Scy{
268275970Scy	struct timespec ts;
269275970Scy
270275970Scy	if (base->monotonic_clock < 0) {
271275970Scy		if (evutil_gettimeofday(tp, NULL) < 0)
272275970Scy			return -1;
273275970Scy		adjust_monotonic_time(base, tp);
274275970Scy		return 0;
275275970Scy	}
276275970Scy
277275970Scy	if (clock_gettime(base->monotonic_clock, &ts) == -1)
278275970Scy		return -1;
279275970Scy	tp->tv_sec = ts.tv_sec;
280275970Scy	tp->tv_usec = ts.tv_nsec / 1000;
281275970Scy
282275970Scy	return 0;
283275970Scy}
284275970Scy#endif
285275970Scy
286275970Scy#if defined(HAVE_MACH_MONOTONIC)
287275970Scy/* ======
288275970Scy   Apple is a little late to the POSIX party.  And why not?  Instead of
289275970Scy   clock_gettime(), they provide mach_absolute_time().  Its units are not
290275970Scy   fixed; we need to use mach_timebase_info() to get the right functions to
291275970Scy   convert its units into nanoseconds.
292275970Scy
293275970Scy   To all appearances, mach_absolute_time() seems to be honest-to-goodness
294275970Scy   monotonic.  Whether it stops during sleep or not is unspecified in
295275970Scy   principle, and dependent on CPU architecture in practice.
296275970Scy */
297275970Scy
298275970Scyint
299275970Scyevutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
300275970Scy    int flags)
301275970Scy{
302275970Scy	const int fallback = flags & EV_MONOT_FALLBACK;
303275970Scy	struct mach_timebase_info mi;
304275970Scy	memset(base, 0, sizeof(*base));
305275970Scy	/* OSX has mach_absolute_time() */
306275970Scy	if (!fallback &&
307275970Scy	    mach_timebase_info(&mi) == 0 &&
308275970Scy	    mach_absolute_time() != 0) {
309275970Scy		/* mach_timebase_info tells us how to convert
310275970Scy		 * mach_absolute_time() into nanoseconds, but we
311275970Scy		 * want to use microseconds instead. */
312275970Scy		mi.denom *= 1000;
313275970Scy		memcpy(&base->mach_timebase_units, &mi, sizeof(mi));
314275970Scy	} else {
315275970Scy		base->mach_timebase_units.numer = 0;
316275970Scy	}
317275970Scy	return 0;
318275970Scy}
319275970Scy
320275970Scyint
321275970Scyevutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
322275970Scy    struct timeval *tp)
323275970Scy{
324275970Scy	ev_uint64_t abstime, usec;
325275970Scy	if (base->mach_timebase_units.numer == 0) {
326275970Scy		if (evutil_gettimeofday(tp, NULL) < 0)
327275970Scy			return -1;
328275970Scy		adjust_monotonic_time(base, tp);
329275970Scy		return 0;
330275970Scy	}
331275970Scy
332275970Scy	abstime = mach_absolute_time();
333275970Scy	usec = (abstime * base->mach_timebase_units.numer)
334275970Scy	    / (base->mach_timebase_units.denom);
335275970Scy	tp->tv_sec = usec / 1000000;
336275970Scy	tp->tv_usec = usec % 1000000;
337275970Scy
338275970Scy	return 0;
339275970Scy}
340275970Scy#endif
341275970Scy
342275970Scy#if defined(HAVE_WIN32_MONOTONIC)
343275970Scy/* =====
344275970Scy   Turn we now to Windows.  Want monontonic time on Windows?
345275970Scy
346275970Scy   Windows has QueryPerformanceCounter(), which gives time most high-
347275970Scy   resolution time.  It's a pity it's not so monotonic in practice; it's
348275970Scy   also got some fun bugs, especially: with older Windowses, under
349275970Scy   virtualizations, with funny hardware, on multiprocessor systems, and so
350275970Scy   on.  PEP418 [1] has a nice roundup of the issues here.
351275970Scy
352275970Scy   There's GetTickCount64() on Vista and later, which gives a number of 1-msec
353275970Scy   ticks since startup.  The accuracy here might be as bad as 10-20 msec, I
354275970Scy   hear.  There's an undocumented function (NtSetTimerResolution) that
355275970Scy   allegedly increases the accuracy. Good luck!
356275970Scy
357275970Scy   There's also GetTickCount(), which is only 32 bits, but seems to be
358275970Scy   supported on pre-Vista versions of Windows.  Apparently, you can coax
359275970Scy   another 14 bits out of it, giving you 2231 years before rollover.
360275970Scy
361275970Scy   The less said about timeGetTime() the better.
362275970Scy
363275970Scy   "We don't care.  We don't have to.  We're the Phone Company."
364275970Scy            -- Lily Tomlin, SNL
365275970Scy
366275970Scy   Our strategy, if precise timers are turned off, is to just use the best
367275970Scy   GetTickCount equivalent available.  If we've been asked for precise timing,
368275970Scy   then we mostly[2] assume that GetTickCount is monotonic, and correct
369275970Scy   GetPerformanceCounter to approximate it.
370275970Scy
371275970Scy   [1] http://www.python.org/dev/peps/pep-0418
372275970Scy   [2] Of course, we feed the Windows stuff into adjust_monotonic_time()
373275970Scy       anyway, just in case it isn't.
374275970Scy
375275970Scy */
376275970Scy/*
377275970Scy    Parts of our logic in the win32 timer code here are closely based on
378275970Scy    BitTorrent's libUTP library.  That code is subject to the following
379275970Scy    license:
380275970Scy
381275970Scy      Copyright (c) 2010 BitTorrent, Inc.
382275970Scy
383275970Scy      Permission is hereby granted, free of charge, to any person obtaining a
384275970Scy      copy of this software and associated documentation files (the
385275970Scy      "Software"), to deal in the Software without restriction, including
386275970Scy      without limitation the rights to use, copy, modify, merge, publish,
387275970Scy      distribute, sublicense, and/or sell copies of the Software, and to
388275970Scy      permit persons to whom the Software is furnished to do so, subject to
389275970Scy      the following conditions:
390275970Scy
391275970Scy      The above copyright notice and this permission notice shall be included
392275970Scy      in all copies or substantial portions of the Software.
393275970Scy
394275970Scy      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
395275970Scy      OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
396275970Scy      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
397275970Scy      NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
398275970Scy      LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
399275970Scy      OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
400275970Scy      WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
401275970Scy*/
402275970Scy
403275970Scystatic ev_uint64_t
404275970Scyevutil_GetTickCount_(struct evutil_monotonic_timer *base)
405275970Scy{
406275970Scy	if (base->GetTickCount64_fn) {
407275970Scy		/* Let's just use GetTickCount64 if we can. */
408275970Scy		return base->GetTickCount64_fn();
409275970Scy	} else if (base->GetTickCount_fn) {
410275970Scy		/* Greg Hazel assures me that this works, that BitTorrent has
411275970Scy		 * done it for years, and this it won't turn around and
412275970Scy		 * bite us.  He says they found it on some game programmers'
413275970Scy		 * forum some time around 2007.
414275970Scy		 */
415275970Scy		ev_uint64_t v = base->GetTickCount_fn();
416275970Scy		return (DWORD)v | ((v >> 18) & 0xFFFFFFFF00000000);
417275970Scy	} else {
418275970Scy		/* Here's the fallback implementation. We have to use
419275970Scy		 * GetTickCount() with its given signature, so we only get
420275970Scy		 * 32 bits worth of milliseconds, which will roll ove every
421275970Scy		 * 49 days or so.  */
422275970Scy		DWORD ticks = GetTickCount();
423275970Scy		if (ticks < base->last_tick_count) {
424275970Scy			base->adjust_tick_count += ((ev_uint64_t)1) << 32;
425275970Scy		}
426275970Scy		base->last_tick_count = ticks;
427275970Scy		return ticks + base->adjust_tick_count;
428275970Scy	}
429275970Scy}
430275970Scy
431275970Scyint
432275970Scyevutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
433275970Scy    int flags)
434275970Scy{
435275970Scy	const int precise = flags & EV_MONOT_PRECISE;
436275970Scy	const int fallback = flags & EV_MONOT_FALLBACK;
437275970Scy	HANDLE h;
438275970Scy	memset(base, 0, sizeof(*base));
439275970Scy
440275970Scy	h = evutil_load_windows_system_library_(TEXT("kernel32.dll"));
441275970Scy	if (h != NULL && !fallback) {
442275970Scy		base->GetTickCount64_fn = (ev_GetTickCount_func)GetProcAddress(h, "GetTickCount64");
443275970Scy		base->GetTickCount_fn = (ev_GetTickCount_func)GetProcAddress(h, "GetTickCount");
444275970Scy	}
445275970Scy
446275970Scy	base->first_tick = base->last_tick_count = evutil_GetTickCount_(base);
447275970Scy	if (precise && !fallback) {
448275970Scy		LARGE_INTEGER freq;
449275970Scy		if (QueryPerformanceFrequency(&freq)) {
450275970Scy			LARGE_INTEGER counter;
451275970Scy			QueryPerformanceCounter(&counter);
452275970Scy			base->first_counter = counter.QuadPart;
453275970Scy			base->usec_per_count = 1.0e6 / freq.QuadPart;
454275970Scy			base->use_performance_counter = 1;
455275970Scy		}
456275970Scy	}
457275970Scy
458275970Scy	return 0;
459275970Scy}
460275970Scy
461275970Scystatic inline ev_int64_t
462275970Scyabs64(ev_int64_t i)
463275970Scy{
464275970Scy	return i < 0 ? -i : i;
465275970Scy}
466275970Scy
467275970Scy
468275970Scyint
469275970Scyevutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
470275970Scy    struct timeval *tp)
471275970Scy{
472275970Scy	ev_uint64_t ticks = evutil_GetTickCount_(base);
473275970Scy	if (base->use_performance_counter) {
474275970Scy		/* Here's a trick we took from BitTorrent's libutp, at Greg
475275970Scy		 * Hazel's recommendation.  We use QueryPerformanceCounter for
476275970Scy		 * our high-resolution timer, but use GetTickCount*() to keep
477275970Scy		 * it sane, and adjust_monotonic_time() to keep it monotonic.
478275970Scy		 */
479275970Scy		LARGE_INTEGER counter;
480275970Scy		ev_int64_t counter_elapsed, counter_usec_elapsed, ticks_elapsed;
481275970Scy		QueryPerformanceCounter(&counter);
482275970Scy		counter_elapsed = (ev_int64_t)
483275970Scy		    (counter.QuadPart - base->first_counter);
484275970Scy		ticks_elapsed = ticks - base->first_tick;
485275970Scy		/* TODO: This may upset VC6. If you need this to work with
486275970Scy		 * VC6, please supply an appropriate patch. */
487275970Scy		counter_usec_elapsed = (ev_int64_t)
488275970Scy		    (counter_elapsed * base->usec_per_count);
489275970Scy
490275970Scy		if (abs64(ticks_elapsed*1000 - counter_usec_elapsed) > 1000000) {
491275970Scy			/* It appears that the QueryPerformanceCounter()
492275970Scy			 * result is more than 1 second away from
493275970Scy			 * GetTickCount() result. Let's adjust it to be as
494275970Scy			 * accurate as we can; adjust_monotnonic_time() below
495275970Scy			 * will keep it monotonic. */
496275970Scy			counter_usec_elapsed = ticks_elapsed * 1000;
497275970Scy			base->first_counter = (ev_uint64_t) (counter.QuadPart - counter_usec_elapsed / base->usec_per_count);
498275970Scy		}
499275970Scy		tp->tv_sec = (time_t) (counter_usec_elapsed / 1000000);
500275970Scy		tp->tv_usec = counter_usec_elapsed % 1000000;
501275970Scy
502275970Scy	} else {
503275970Scy		/* We're just using GetTickCount(). */
504275970Scy		tp->tv_sec = (time_t) (ticks / 1000);
505275970Scy		tp->tv_usec = (ticks % 1000) * 1000;
506275970Scy	}
507275970Scy	adjust_monotonic_time(base, tp);
508275970Scy
509275970Scy	return 0;
510275970Scy}
511275970Scy#endif
512275970Scy
513275970Scy#if defined(HAVE_FALLBACK_MONOTONIC)
514275970Scy/* =====
515275970Scy   And if none of the other options work, let's just use gettimeofday(), and
516275970Scy   ratchet it forward so that it acts like a monotonic timer, whether it
517275970Scy   wants to or not.
518275970Scy */
519275970Scy
520275970Scyint
521275970Scyevutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
522275970Scy    int precise)
523275970Scy{
524275970Scy	memset(base, 0, sizeof(*base));
525275970Scy	return 0;
526275970Scy}
527275970Scy
528275970Scyint
529275970Scyevutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
530275970Scy    struct timeval *tp)
531275970Scy{
532275970Scy	if (evutil_gettimeofday(tp, NULL) < 0)
533275970Scy		return -1;
534275970Scy	adjust_monotonic_time(base, tp);
535275970Scy	return 0;
536275970Scy
537275970Scy}
538275970Scy#endif
539