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