xref: /libevent-2.1.12/evutil_time.c (revision a8219143)
1c4194854SNick Mathewson /*
2c4194854SNick Mathewson  * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
3c4194854SNick Mathewson  *
4c4194854SNick Mathewson  * Redistribution and use in source and binary forms, with or without
5c4194854SNick Mathewson  * modification, are permitted provided that the following conditions
6c4194854SNick Mathewson  * are met:
7c4194854SNick Mathewson  * 1. Redistributions of source code must retain the above copyright
8c4194854SNick Mathewson  *    notice, this list of conditions and the following disclaimer.
9c4194854SNick Mathewson  * 2. Redistributions in binary form must reproduce the above copyright
10c4194854SNick Mathewson  *    notice, this list of conditions and the following disclaimer in the
11c4194854SNick Mathewson  *    documentation and/or other materials provided with the distribution.
12c4194854SNick Mathewson  * 3. The name of the author may not be used to endorse or promote products
13c4194854SNick Mathewson  *    derived from this software without specific prior written permission.
14c4194854SNick Mathewson  *
15c4194854SNick Mathewson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16c4194854SNick Mathewson  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17c4194854SNick Mathewson  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18c4194854SNick Mathewson  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19c4194854SNick Mathewson  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20c4194854SNick Mathewson  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21c4194854SNick Mathewson  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22c4194854SNick Mathewson  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23c4194854SNick Mathewson  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24c4194854SNick Mathewson  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25c4194854SNick Mathewson  */
26c4194854SNick Mathewson 
27c4194854SNick Mathewson #include "event2/event-config.h"
28c4194854SNick Mathewson #include "evconfig-private.h"
29c4194854SNick Mathewson 
30c4194854SNick Mathewson #ifdef _WIN32
31c4194854SNick Mathewson #include <winsock2.h>
32c4194854SNick Mathewson #define WIN32_LEAN_AND_MEAN
33c4194854SNick Mathewson #include <windows.h>
34c4194854SNick Mathewson #undef WIN32_LEAN_AND_MEAN
35c4194854SNick Mathewson #endif
36c4194854SNick Mathewson 
37c4194854SNick Mathewson #include <sys/types.h>
38c4194854SNick Mathewson #ifdef EVENT__HAVE_STDLIB_H
39c4194854SNick Mathewson #include <stdlib.h>
40c4194854SNick Mathewson #endif
41c4194854SNick Mathewson #include <errno.h>
42c4194854SNick Mathewson #include <limits.h>
43c4194854SNick Mathewson #ifndef EVENT__HAVE_GETTIMEOFDAY
44c4194854SNick Mathewson #include <sys/timeb.h>
45c4194854SNick Mathewson #endif
4685fed75fSAzat Khuzhin #if !defined(EVENT__HAVE_NANOSLEEP) && !defined(EVENT__HAVE_USLEEP) && \
47c4194854SNick Mathewson 	!defined(_WIN32)
48c4194854SNick Mathewson #include <sys/select.h>
49c4194854SNick Mathewson #endif
50c4194854SNick Mathewson #include <time.h>
51c4194854SNick Mathewson #include <sys/stat.h>
52f5e4eb05SNick Mathewson #include <string.h>
53c4194854SNick Mathewson 
543e75194cSAzat Khuzhin /** evutil_usleep_() */
553e75194cSAzat Khuzhin #if defined(_WIN32)
563e75194cSAzat Khuzhin #elif defined(EVENT__HAVE_NANOSLEEP)
573e75194cSAzat Khuzhin #elif defined(EVENT__HAVE_USLEEP)
583e75194cSAzat Khuzhin #include <unistd.h>
593e75194cSAzat Khuzhin #endif
603e75194cSAzat Khuzhin 
61c4194854SNick Mathewson #include "event2/util.h"
62c4194854SNick Mathewson #include "util-internal.h"
63c4194854SNick Mathewson #include "log-internal.h"
64f2645f80SAndrea Shepard #include "mm-internal.h"
65c4194854SNick Mathewson 
66c4194854SNick Mathewson #ifndef EVENT__HAVE_GETTIMEOFDAY
67c4194854SNick Mathewson /* No gettimeofday; this must be windows. */
68*a8219143SNick Grifka 
69*a8219143SNick Grifka typedef void (WINAPI *GetSystemTimePreciseAsFileTime_fn_t) (LPFILETIME);
70*a8219143SNick Grifka 
71c4194854SNick Mathewson int
evutil_gettimeofday(struct timeval * tv,struct timezone * tz)72c4194854SNick Mathewson evutil_gettimeofday(struct timeval *tv, struct timezone *tz)
73c4194854SNick Mathewson {
74c4194854SNick Mathewson #ifdef _MSC_VER
75c4194854SNick Mathewson #define U64_LITERAL(n) n##ui64
76c4194854SNick Mathewson #else
77c4194854SNick Mathewson #define U64_LITERAL(n) n##llu
78c4194854SNick Mathewson #endif
79c4194854SNick Mathewson 
80c4194854SNick Mathewson 	/* Conversion logic taken from Tor, which in turn took it
81c4194854SNick Mathewson 	 * from Perl.  GetSystemTimeAsFileTime returns its value as
82c4194854SNick Mathewson 	 * an unaligned (!) 64-bit value containing the number of
83c4194854SNick Mathewson 	 * 100-nanosecond intervals since 1 January 1601 UTC. */
84c4194854SNick Mathewson #define EPOCH_BIAS U64_LITERAL(116444736000000000)
85c4194854SNick Mathewson #define UNITS_PER_SEC U64_LITERAL(10000000)
86c4194854SNick Mathewson #define USEC_PER_SEC U64_LITERAL(1000000)
87c4194854SNick Mathewson #define UNITS_PER_USEC U64_LITERAL(10)
88c4194854SNick Mathewson 	union {
89c4194854SNick Mathewson 		FILETIME ft_ft;
90c4194854SNick Mathewson 		ev_uint64_t ft_64;
91c4194854SNick Mathewson 	} ft;
92c4194854SNick Mathewson 
93c4194854SNick Mathewson 	if (tv == NULL)
94c4194854SNick Mathewson 		return -1;
95c4194854SNick Mathewson 
96*a8219143SNick Grifka 	static GetSystemTimePreciseAsFileTime_fn_t GetSystemTimePreciseAsFileTime_fn = NULL;
97*a8219143SNick Grifka 	static int check_precise = 1;
98*a8219143SNick Grifka 
99*a8219143SNick Grifka 	if (EVUTIL_UNLIKELY(check_precise)) {
100*a8219143SNick Grifka 		HMODULE h = evutil_load_windows_system_library_(TEXT("kernel32.dll"));
101*a8219143SNick Grifka 		if (h != NULL)
102*a8219143SNick Grifka 			GetSystemTimePreciseAsFileTime_fn =
103*a8219143SNick Grifka 				(GetSystemTimePreciseAsFileTime_fn_t)
104*a8219143SNick Grifka 					GetProcAddress(h, "GetSystemTimePreciseAsFileTime");
105*a8219143SNick Grifka 		check_precise = 0;
106*a8219143SNick Grifka 	}
107*a8219143SNick Grifka 
108*a8219143SNick Grifka 	if (GetSystemTimePreciseAsFileTime_fn != NULL)
109*a8219143SNick Grifka 		GetSystemTimePreciseAsFileTime_fn(&ft.ft_ft);
110*a8219143SNick Grifka 	else
111c4194854SNick Mathewson 		GetSystemTimeAsFileTime(&ft.ft_ft);
112c4194854SNick Mathewson 
113c4194854SNick Mathewson 	if (EVUTIL_UNLIKELY(ft.ft_64 < EPOCH_BIAS)) {
114c4194854SNick Mathewson 		/* Time before the unix epoch. */
115c4194854SNick Mathewson 		return -1;
116c4194854SNick Mathewson 	}
117c4194854SNick Mathewson 	ft.ft_64 -= EPOCH_BIAS;
118c4194854SNick Mathewson 	tv->tv_sec = (long) (ft.ft_64 / UNITS_PER_SEC);
119c4194854SNick Mathewson 	tv->tv_usec = (long) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
120c4194854SNick Mathewson 	return 0;
121c4194854SNick Mathewson }
122c4194854SNick Mathewson #endif
123c4194854SNick Mathewson 
124c4194854SNick Mathewson #define MAX_SECONDS_IN_MSEC_LONG \
125c4194854SNick Mathewson 	(((LONG_MAX) - 999) / 1000)
126c4194854SNick Mathewson 
127c4194854SNick Mathewson long
evutil_tv_to_msec_(const struct timeval * tv)128c4194854SNick Mathewson evutil_tv_to_msec_(const struct timeval *tv)
129c4194854SNick Mathewson {
130c4194854SNick Mathewson 	if (tv->tv_usec > 1000000 || tv->tv_sec > MAX_SECONDS_IN_MSEC_LONG)
131c4194854SNick Mathewson 		return -1;
132c4194854SNick Mathewson 
133c4194854SNick Mathewson 	return (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000);
134c4194854SNick Mathewson }
135c4194854SNick Mathewson 
136630f077cSNick Mathewson /*
137630f077cSNick Mathewson   Replacement for usleep on platforms that don't have one.  Not guaranteed to
138630f077cSNick Mathewson   be any more finegrained than 1 msec.
139630f077cSNick Mathewson  */
140c4194854SNick Mathewson void
evutil_usleep_(const struct timeval * tv)141c4194854SNick Mathewson evutil_usleep_(const struct timeval *tv)
142c4194854SNick Mathewson {
143c4194854SNick Mathewson 	if (!tv)
144c4194854SNick Mathewson 		return;
145c4194854SNick Mathewson #if defined(_WIN32)
146c4194854SNick Mathewson 	{
147d42240d1Syuangongji 		__int64 usec;
148d42240d1Syuangongji 		LARGE_INTEGER li;
149d42240d1Syuangongji 		HANDLE timer;
150d42240d1Syuangongji 
151d42240d1Syuangongji 		usec = tv->tv_sec * 1000000LL + tv->tv_usec;
152d42240d1Syuangongji 		if (!usec)
153d42240d1Syuangongji 			return;
154d42240d1Syuangongji 
155d42240d1Syuangongji 		li.QuadPart = -10LL * usec;
156d42240d1Syuangongji 		timer = CreateWaitableTimer(NULL, TRUE, NULL);
157d42240d1Syuangongji 		if (!timer)
158d42240d1Syuangongji 			return;
159d42240d1Syuangongji 
160d42240d1Syuangongji 		SetWaitableTimer(timer, &li, 0, NULL, NULL, 0);
161d42240d1Syuangongji 		WaitForSingleObject(timer, INFINITE);
162d42240d1Syuangongji 		CloseHandle(timer);
163c4194854SNick Mathewson 	}
164c4194854SNick Mathewson #elif defined(EVENT__HAVE_NANOSLEEP)
165c4194854SNick Mathewson 	{
166c4194854SNick Mathewson 		struct timespec ts;
167c4194854SNick Mathewson 		ts.tv_sec = tv->tv_sec;
168c4194854SNick Mathewson 		ts.tv_nsec = tv->tv_usec*1000;
169c4194854SNick Mathewson 		nanosleep(&ts, NULL);
170c4194854SNick Mathewson 	}
171c4194854SNick Mathewson #elif defined(EVENT__HAVE_USLEEP)
172c4194854SNick Mathewson 	/* Some systems don't like to usleep more than 999999 usec */
173c4194854SNick Mathewson 	sleep(tv->tv_sec);
174c4194854SNick Mathewson 	usleep(tv->tv_usec);
175c4194854SNick Mathewson #else
1768818c86cSPhilip Prindeville 	{
1778818c86cSPhilip Prindeville 		struct timeval tv2 = *tv;
1788818c86cSPhilip Prindeville 		select(0, NULL, NULL, NULL, &tv2);
1798818c86cSPhilip Prindeville 	}
180c4194854SNick Mathewson #endif
181c4194854SNick Mathewson }
182f5e4eb05SNick Mathewson 
183db60ade8SVis Virial int
evutil_date_rfc1123(char * date,const size_t datelen,const struct tm * tm)1844545807dSAzat Khuzhin evutil_date_rfc1123(char *date, const size_t datelen, const struct tm *tm)
1854545807dSAzat Khuzhin {
186db60ade8SVis Virial 	static const char *DAYS[] =
187db60ade8SVis Virial 		{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
188db60ade8SVis Virial 	static const char *MONTHS[] =
189db60ade8SVis Virial 		{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
190db60ade8SVis Virial 
191db60ade8SVis Virial 	time_t t = time(NULL);
192db60ade8SVis Virial 
193f4a6152cSyuangongji #if defined(EVENT__HAVE__GMTIME64_S) || !defined(_WIN32)
1944545807dSAzat Khuzhin 	struct tm sys;
1954545807dSAzat Khuzhin #endif
1964545807dSAzat Khuzhin 
1974545807dSAzat Khuzhin 	/* If `tm` is null, set system's current time. */
1984545807dSAzat Khuzhin 	if (tm == NULL) {
199f4a6152cSyuangongji #if !defined(_WIN32)
2004545807dSAzat Khuzhin 		gmtime_r(&t, &sys);
2014545807dSAzat Khuzhin 		tm = &sys;
202f4a6152cSyuangongji 		/** detect _gmtime64()/_gmtime64_s() */
203f4a6152cSyuangongji #elif defined(EVENT__HAVE__GMTIME64_S)
204f4a6152cSyuangongji 		errno_t err;
205f4a6152cSyuangongji 		err = _gmtime64_s(&sys, &t);
206f4a6152cSyuangongji 		if (err) {
207f4a6152cSyuangongji 			event_errx(1, "Invalid argument to _gmtime64_s");
208f4a6152cSyuangongji 		} else {
209f4a6152cSyuangongji 			tm = &sys;
210f4a6152cSyuangongji 		}
211f4a6152cSyuangongji #elif defined(EVENT__HAVE__GMTIME64)
212f4a6152cSyuangongji 		tm = _gmtime64(&t);
213f4a6152cSyuangongji #else
214f4a6152cSyuangongji 		tm = gmtime(&t);
215db60ade8SVis Virial #endif
216db60ade8SVis Virial 	}
217db60ade8SVis Virial 
218db60ade8SVis Virial 	return evutil_snprintf(
219db60ade8SVis Virial 		date, datelen, "%s, %02d %s %4d %02d:%02d:%02d GMT",
2204545807dSAzat Khuzhin 		DAYS[tm->tm_wday], tm->tm_mday, MONTHS[tm->tm_mon],
2214545807dSAzat Khuzhin 		1900 + tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec);
222db60ade8SVis Virial }
223db60ade8SVis Virial 
224f5e4eb05SNick Mathewson /*
225f5e4eb05SNick Mathewson    This function assumes it's called repeatedly with a
226f5e4eb05SNick Mathewson    not-actually-so-monotonic time source whose outputs are in 'tv'. It
227f5e4eb05SNick Mathewson    implements a trivial ratcheting mechanism so that the values never go
228f5e4eb05SNick Mathewson    backwards.
229f5e4eb05SNick Mathewson  */
230f5e4eb05SNick Mathewson static void
adjust_monotonic_time(struct evutil_monotonic_timer * base,struct timeval * tv)231f5e4eb05SNick Mathewson adjust_monotonic_time(struct evutil_monotonic_timer *base,
232f5e4eb05SNick Mathewson     struct timeval *tv)
233f5e4eb05SNick Mathewson {
234f5e4eb05SNick Mathewson 	evutil_timeradd(tv, &base->adjust_monotonic_clock, tv);
235f5e4eb05SNick Mathewson 
236f5e4eb05SNick Mathewson 	if (evutil_timercmp(tv, &base->last_time, <)) {
237f5e4eb05SNick Mathewson 		/* Guess it wasn't monotonic after all. */
238f5e4eb05SNick Mathewson 		struct timeval adjust;
239f5e4eb05SNick Mathewson 		evutil_timersub(&base->last_time, tv, &adjust);
240f5e4eb05SNick Mathewson 		evutil_timeradd(&adjust, &base->adjust_monotonic_clock,
241f5e4eb05SNick Mathewson 		    &base->adjust_monotonic_clock);
242f5e4eb05SNick Mathewson 		*tv = base->last_time;
243f5e4eb05SNick Mathewson 	}
244f5e4eb05SNick Mathewson 	base->last_time = *tv;
245f5e4eb05SNick Mathewson }
246f5e4eb05SNick Mathewson 
247f2645f80SAndrea Shepard /*
248f2645f80SAndrea Shepard    Allocate a new struct evutil_monotonic_timer
249f2645f80SAndrea Shepard  */
250f2645f80SAndrea Shepard struct evutil_monotonic_timer *
evutil_monotonic_timer_new(void)251f2645f80SAndrea Shepard evutil_monotonic_timer_new(void)
252f2645f80SAndrea Shepard {
253f2645f80SAndrea Shepard   struct evutil_monotonic_timer *p = NULL;
254f2645f80SAndrea Shepard 
255f2645f80SAndrea Shepard   p = mm_malloc(sizeof(*p));
256f2645f80SAndrea Shepard   if (!p) goto done;
257f2645f80SAndrea Shepard 
258f2645f80SAndrea Shepard   memset(p, 0, sizeof(*p));
259f2645f80SAndrea Shepard 
260f2645f80SAndrea Shepard  done:
261f2645f80SAndrea Shepard   return p;
262f2645f80SAndrea Shepard }
263f2645f80SAndrea Shepard 
264f2645f80SAndrea Shepard /*
265f2645f80SAndrea Shepard    Free a struct evutil_monotonic_timer
266f2645f80SAndrea Shepard  */
267f2645f80SAndrea Shepard void
evutil_monotonic_timer_free(struct evutil_monotonic_timer * timer)268f2645f80SAndrea Shepard evutil_monotonic_timer_free(struct evutil_monotonic_timer *timer)
269f2645f80SAndrea Shepard {
270f2645f80SAndrea Shepard   if (timer) {
271f2645f80SAndrea Shepard     mm_free(timer);
272f2645f80SAndrea Shepard   }
273f2645f80SAndrea Shepard }
274f2645f80SAndrea Shepard 
275f2645f80SAndrea Shepard /*
276f2645f80SAndrea Shepard    Set up a struct evutil_monotonic_timer for initial use
277f2645f80SAndrea Shepard  */
278f2645f80SAndrea Shepard int
evutil_configure_monotonic_time(struct evutil_monotonic_timer * timer,int flags)279f2645f80SAndrea Shepard evutil_configure_monotonic_time(struct evutil_monotonic_timer *timer,
280f2645f80SAndrea Shepard                                 int flags)
281f2645f80SAndrea Shepard {
282f2645f80SAndrea Shepard   return evutil_configure_monotonic_time_(timer, flags);
283f2645f80SAndrea Shepard }
284f2645f80SAndrea Shepard 
285f2645f80SAndrea Shepard /*
286f2645f80SAndrea Shepard    Query the current monotonic time
287f2645f80SAndrea Shepard  */
288f2645f80SAndrea Shepard int
evutil_gettime_monotonic(struct evutil_monotonic_timer * timer,struct timeval * tp)289f2645f80SAndrea Shepard evutil_gettime_monotonic(struct evutil_monotonic_timer *timer,
290f2645f80SAndrea Shepard                          struct timeval *tp)
291f2645f80SAndrea Shepard {
292f2645f80SAndrea Shepard   return evutil_gettime_monotonic_(timer, tp);
293f2645f80SAndrea Shepard }
294f2645f80SAndrea Shepard 
295f2645f80SAndrea Shepard 
296f5e4eb05SNick Mathewson #if defined(HAVE_POSIX_MONOTONIC)
297f5e4eb05SNick Mathewson /* =====
298f5e4eb05SNick Mathewson    The POSIX clock_gettime() interface provides a few ways to get at a
299f5e4eb05SNick Mathewson    monotonic clock.  CLOCK_MONOTONIC is most widely supported.  Linux also
300f5e4eb05SNick Mathewson    provides a CLOCK_MONOTONIC_COARSE with accuracy of about 1-4 msec.
301f5e4eb05SNick Mathewson 
302f5e4eb05SNick Mathewson    On all platforms I'm aware of, CLOCK_MONOTONIC really is monotonic.
303f5e4eb05SNick Mathewson    Platforms don't agree about whether it should jump on a sleep/resume.
304f5e4eb05SNick Mathewson  */
305f5e4eb05SNick Mathewson 
306f5e4eb05SNick Mathewson int
evutil_configure_monotonic_time_(struct evutil_monotonic_timer * base,int flags)307f5e4eb05SNick Mathewson evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
308630f077cSNick Mathewson     int flags)
309f5e4eb05SNick Mathewson {
310f5e4eb05SNick Mathewson 	/* CLOCK_MONOTONIC exists on FreeBSD, Linux, and Solaris.  You need to
311f5e4eb05SNick Mathewson 	 * check for it at runtime, because some older kernel versions won't
312f5e4eb05SNick Mathewson 	 * have it working. */
3139be54680SNick Mathewson #ifdef CLOCK_MONOTONIC_COARSE
314630f077cSNick Mathewson 	const int precise = flags & EV_MONOT_PRECISE;
3159be54680SNick Mathewson #endif
316630f077cSNick Mathewson 	const int fallback = flags & EV_MONOT_FALLBACK;
317f5e4eb05SNick Mathewson 	struct timespec	ts;
318630f077cSNick Mathewson 
319f5e4eb05SNick Mathewson #ifdef CLOCK_MONOTONIC_COARSE
320911abf3dSNick Mathewson 	if (CLOCK_MONOTONIC_COARSE < 0) {
321911abf3dSNick Mathewson 		/* Technically speaking, nothing keeps CLOCK_* from being
322911abf3dSNick Mathewson 		 * negative (as far as I know). This check and the one below
323911abf3dSNick Mathewson 		 * make sure that it's safe for us to use -1 as an "unset"
324911abf3dSNick Mathewson 		 * value. */
325911abf3dSNick Mathewson 		event_errx(1,"I didn't expect CLOCK_MONOTONIC_COARSE to be < 0");
326911abf3dSNick Mathewson 	}
327630f077cSNick Mathewson 	if (! precise && ! fallback) {
328f5e4eb05SNick Mathewson 		if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) {
329f5e4eb05SNick Mathewson 			base->monotonic_clock = CLOCK_MONOTONIC_COARSE;
330f5e4eb05SNick Mathewson 			return 0;
331f5e4eb05SNick Mathewson 		}
332f5e4eb05SNick Mathewson 	}
333f5e4eb05SNick Mathewson #endif
334630f077cSNick Mathewson 	if (!fallback && clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
335f5e4eb05SNick Mathewson 		base->monotonic_clock = CLOCK_MONOTONIC;
336f5e4eb05SNick Mathewson 		return 0;
337f5e4eb05SNick Mathewson 	}
338f5e4eb05SNick Mathewson 
339911abf3dSNick Mathewson 	if (CLOCK_MONOTONIC < 0) {
340911abf3dSNick Mathewson 		event_errx(1,"I didn't expect CLOCK_MONOTONIC to be < 0");
341911abf3dSNick Mathewson 	}
342f5e4eb05SNick Mathewson 
343f5e4eb05SNick Mathewson 	base->monotonic_clock = -1;
344f5e4eb05SNick Mathewson 	return 0;
345f5e4eb05SNick Mathewson }
346f5e4eb05SNick Mathewson 
347f5e4eb05SNick Mathewson int
evutil_gettime_monotonic_(struct evutil_monotonic_timer * base,struct timeval * tp)348f5e4eb05SNick Mathewson evutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
349f5e4eb05SNick Mathewson     struct timeval *tp)
350f5e4eb05SNick Mathewson {
351f5e4eb05SNick Mathewson 	struct timespec ts;
352f5e4eb05SNick Mathewson 
353f5e4eb05SNick Mathewson 	if (base->monotonic_clock < 0) {
354f5e4eb05SNick Mathewson 		if (evutil_gettimeofday(tp, NULL) < 0)
355f5e4eb05SNick Mathewson 			return -1;
356f5e4eb05SNick Mathewson 		adjust_monotonic_time(base, tp);
357f5e4eb05SNick Mathewson 		return 0;
358f5e4eb05SNick Mathewson 	}
359f5e4eb05SNick Mathewson 
360f5e4eb05SNick Mathewson 	if (clock_gettime(base->monotonic_clock, &ts) == -1)
361f5e4eb05SNick Mathewson 		return -1;
362f5e4eb05SNick Mathewson 	tp->tv_sec = ts.tv_sec;
363f5e4eb05SNick Mathewson 	tp->tv_usec = ts.tv_nsec / 1000;
364f5e4eb05SNick Mathewson 
365f5e4eb05SNick Mathewson 	return 0;
366f5e4eb05SNick Mathewson }
367f5e4eb05SNick Mathewson #endif
368f5e4eb05SNick Mathewson 
369f5e4eb05SNick Mathewson #if defined(HAVE_MACH_MONOTONIC)
370f5e4eb05SNick Mathewson /* ======
371f5e4eb05SNick Mathewson    Apple is a little late to the POSIX party.  And why not?  Instead of
372f5e4eb05SNick Mathewson    clock_gettime(), they provide mach_absolute_time().  Its units are not
373f5e4eb05SNick Mathewson    fixed; we need to use mach_timebase_info() to get the right functions to
374f5e4eb05SNick Mathewson    convert its units into nanoseconds.
375f5e4eb05SNick Mathewson 
376f5e4eb05SNick Mathewson    To all appearances, mach_absolute_time() seems to be honest-to-goodness
377f5e4eb05SNick Mathewson    monotonic.  Whether it stops during sleep or not is unspecified in
378f5e4eb05SNick Mathewson    principle, and dependent on CPU architecture in practice.
379f5e4eb05SNick Mathewson  */
380f5e4eb05SNick Mathewson 
381f5e4eb05SNick Mathewson int
evutil_configure_monotonic_time_(struct evutil_monotonic_timer * base,int flags)382f5e4eb05SNick Mathewson evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
383630f077cSNick Mathewson     int flags)
384f5e4eb05SNick Mathewson {
385630f077cSNick Mathewson 	const int fallback = flags & EV_MONOT_FALLBACK;
386f5e4eb05SNick Mathewson 	struct mach_timebase_info mi;
387f5e4eb05SNick Mathewson 	memset(base, 0, sizeof(*base));
388f5e4eb05SNick Mathewson 	/* OSX has mach_absolute_time() */
389630f077cSNick Mathewson 	if (!fallback &&
390630f077cSNick Mathewson 	    mach_timebase_info(&mi) == 0 &&
391630f077cSNick Mathewson 	    mach_absolute_time() != 0) {
392f5e4eb05SNick Mathewson 		/* mach_timebase_info tells us how to convert
393f5e4eb05SNick Mathewson 		 * mach_absolute_time() into nanoseconds, but we
394f5e4eb05SNick Mathewson 		 * want to use microseconds instead. */
395f5e4eb05SNick Mathewson 		mi.denom *= 1000;
396f5e4eb05SNick Mathewson 		memcpy(&base->mach_timebase_units, &mi, sizeof(mi));
397f5e4eb05SNick Mathewson 	} else {
398f5e4eb05SNick Mathewson 		base->mach_timebase_units.numer = 0;
399f5e4eb05SNick Mathewson 	}
400f5e4eb05SNick Mathewson 	return 0;
401f5e4eb05SNick Mathewson }
402f5e4eb05SNick Mathewson 
403f5e4eb05SNick Mathewson int
evutil_gettime_monotonic_(struct evutil_monotonic_timer * base,struct timeval * tp)404f5e4eb05SNick Mathewson evutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
405f5e4eb05SNick Mathewson     struct timeval *tp)
406f5e4eb05SNick Mathewson {
407f5e4eb05SNick Mathewson 	ev_uint64_t abstime, usec;
408f5e4eb05SNick Mathewson 	if (base->mach_timebase_units.numer == 0) {
409f5e4eb05SNick Mathewson 		if (evutil_gettimeofday(tp, NULL) < 0)
410f5e4eb05SNick Mathewson 			return -1;
411f5e4eb05SNick Mathewson 		adjust_monotonic_time(base, tp);
412f5e4eb05SNick Mathewson 		return 0;
413f5e4eb05SNick Mathewson 	}
414f5e4eb05SNick Mathewson 
415f5e4eb05SNick Mathewson 	abstime = mach_absolute_time();
416f5e4eb05SNick Mathewson 	usec = (abstime * base->mach_timebase_units.numer)
417f5e4eb05SNick Mathewson 	    / (base->mach_timebase_units.denom);
418f5e4eb05SNick Mathewson 	tp->tv_sec = usec / 1000000;
419f5e4eb05SNick Mathewson 	tp->tv_usec = usec % 1000000;
420f5e4eb05SNick Mathewson 
421f5e4eb05SNick Mathewson 	return 0;
422f5e4eb05SNick Mathewson }
423f5e4eb05SNick Mathewson #endif
424f5e4eb05SNick Mathewson 
425f5e4eb05SNick Mathewson #if defined(HAVE_WIN32_MONOTONIC)
426f5e4eb05SNick Mathewson /* =====
427f5e4eb05SNick Mathewson    Turn we now to Windows.  Want monontonic time on Windows?
428f5e4eb05SNick Mathewson 
429f5e4eb05SNick Mathewson    Windows has QueryPerformanceCounter(), which gives time most high-
430f5e4eb05SNick Mathewson    resolution time.  It's a pity it's not so monotonic in practice; it's
4312c470452SNick Mathewson    also got some fun bugs, especially: with older Windowses, under
432f5e4eb05SNick Mathewson    virtualizations, with funny hardware, on multiprocessor systems, and so
4332c470452SNick Mathewson    on.  PEP418 [1] has a nice roundup of the issues here.
434f5e4eb05SNick Mathewson 
4352c470452SNick Mathewson    There's GetTickCount64() on Vista and later, which gives a number of 1-msec
4362c470452SNick Mathewson    ticks since startup.  The accuracy here might be as bad as 10-20 msec, I
4372c470452SNick Mathewson    hear.  There's an undocumented function (NtSetTimerResolution) that
4382c470452SNick Mathewson    allegedly increases the accuracy. Good luck!
439f5e4eb05SNick Mathewson 
440f5e4eb05SNick Mathewson    There's also GetTickCount(), which is only 32 bits, but seems to be
4412c470452SNick Mathewson    supported on pre-Vista versions of Windows.  Apparently, you can coax
4422c470452SNick Mathewson    another 14 bits out of it, giving you 2231 years before rollover.
443f5e4eb05SNick Mathewson 
444f5e4eb05SNick Mathewson    The less said about timeGetTime() the better.
445f5e4eb05SNick Mathewson 
446f5e4eb05SNick Mathewson    "We don't care.  We don't have to.  We're the Phone Company."
447f5e4eb05SNick Mathewson             -- Lily Tomlin, SNL
448f5e4eb05SNick Mathewson 
4492c470452SNick Mathewson    Our strategy, if precise timers are turned off, is to just use the best
4502c470452SNick Mathewson    GetTickCount equivalent available.  If we've been asked for precise timing,
4512c470452SNick Mathewson    then we mostly[2] assume that GetTickCount is monotonic, and correct
4522c470452SNick Mathewson    GetPerformanceCounter to approximate it.
453f5e4eb05SNick Mathewson 
454f5e4eb05SNick Mathewson    [1] http://www.python.org/dev/peps/pep-0418
4552c470452SNick Mathewson    [2] Of course, we feed the Windows stuff into adjust_monotonic_time()
4562c470452SNick Mathewson        anyway, just in case it isn't.
4572c470452SNick Mathewson 
458f5e4eb05SNick Mathewson  */
4592c470452SNick Mathewson /*
4602c470452SNick Mathewson     Parts of our logic in the win32 timer code here are closely based on
4612c470452SNick Mathewson     BitTorrent's libUTP library.  That code is subject to the following
4622c470452SNick Mathewson     license:
4632c470452SNick Mathewson 
4642c470452SNick Mathewson       Copyright (c) 2010 BitTorrent, Inc.
4652c470452SNick Mathewson 
4662c470452SNick Mathewson       Permission is hereby granted, free of charge, to any person obtaining a
4672c470452SNick Mathewson       copy of this software and associated documentation files (the
4682c470452SNick Mathewson       "Software"), to deal in the Software without restriction, including
4692c470452SNick Mathewson       without limitation the rights to use, copy, modify, merge, publish,
4702c470452SNick Mathewson       distribute, sublicense, and/or sell copies of the Software, and to
4712c470452SNick Mathewson       permit persons to whom the Software is furnished to do so, subject to
4722c470452SNick Mathewson       the following conditions:
4732c470452SNick Mathewson 
4742c470452SNick Mathewson       The above copyright notice and this permission notice shall be included
4752c470452SNick Mathewson       in all copies or substantial portions of the Software.
4762c470452SNick Mathewson 
4772c470452SNick Mathewson       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
4782c470452SNick Mathewson       OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
4792c470452SNick Mathewson       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
4802c470452SNick Mathewson       NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
4812c470452SNick Mathewson       LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
4822c470452SNick Mathewson       OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
4832c470452SNick Mathewson       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4842c470452SNick Mathewson */
4852c470452SNick Mathewson 
4862c470452SNick Mathewson static ev_uint64_t
evutil_GetTickCount_(struct evutil_monotonic_timer * base)4872c470452SNick Mathewson evutil_GetTickCount_(struct evutil_monotonic_timer *base)
4882c470452SNick Mathewson {
4892c470452SNick Mathewson 	if (base->GetTickCount64_fn) {
4902c470452SNick Mathewson 		/* Let's just use GetTickCount64 if we can. */
4912c470452SNick Mathewson 		return base->GetTickCount64_fn();
4922c470452SNick Mathewson 	} else if (base->GetTickCount_fn) {
4932c470452SNick Mathewson 		/* Greg Hazel assures me that this works, that BitTorrent has
4942c470452SNick Mathewson 		 * done it for years, and this it won't turn around and
4952c470452SNick Mathewson 		 * bite us.  He says they found it on some game programmers'
4962c470452SNick Mathewson 		 * forum some time around 2007.
4972c470452SNick Mathewson 		 */
4982c470452SNick Mathewson 		ev_uint64_t v = base->GetTickCount_fn();
4992c470452SNick Mathewson 		return (DWORD)v | ((v >> 18) & 0xFFFFFFFF00000000);
5002c470452SNick Mathewson 	} else {
5012c470452SNick Mathewson 		/* Here's the fallback implementation. We have to use
5022c470452SNick Mathewson 		 * GetTickCount() with its given signature, so we only get
5032c470452SNick Mathewson 		 * 32 bits worth of milliseconds, which will roll ove every
5042c470452SNick Mathewson 		 * 49 days or so.  */
5052c470452SNick Mathewson 		DWORD ticks = GetTickCount();
5062c470452SNick Mathewson 		if (ticks < base->last_tick_count) {
5072c470452SNick Mathewson 			base->adjust_tick_count += ((ev_uint64_t)1) << 32;
5082c470452SNick Mathewson 		}
5092c470452SNick Mathewson 		base->last_tick_count = ticks;
5102c470452SNick Mathewson 		return ticks + base->adjust_tick_count;
5112c470452SNick Mathewson 	}
5122c470452SNick Mathewson }
5132c470452SNick Mathewson 
514f5e4eb05SNick Mathewson int
evutil_configure_monotonic_time_(struct evutil_monotonic_timer * base,int flags)515f5e4eb05SNick Mathewson evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
516630f077cSNick Mathewson     int flags)
517f5e4eb05SNick Mathewson {
518630f077cSNick Mathewson 	const int precise = flags & EV_MONOT_PRECISE;
519630f077cSNick Mathewson 	const int fallback = flags & EV_MONOT_FALLBACK;
5202c470452SNick Mathewson 	HANDLE h;
521f5e4eb05SNick Mathewson 	memset(base, 0, sizeof(*base));
5222c470452SNick Mathewson 
5232c470452SNick Mathewson 	h = evutil_load_windows_system_library_(TEXT("kernel32.dll"));
524630f077cSNick Mathewson 	if (h != NULL && !fallback) {
5252c470452SNick Mathewson 		base->GetTickCount64_fn = (ev_GetTickCount_func)GetProcAddress(h, "GetTickCount64");
5262c470452SNick Mathewson 		base->GetTickCount_fn = (ev_GetTickCount_func)GetProcAddress(h, "GetTickCount");
5272c470452SNick Mathewson 	}
5282c470452SNick Mathewson 
5292c470452SNick Mathewson 	base->first_tick = base->last_tick_count = evutil_GetTickCount_(base);
530630f077cSNick Mathewson 	if (precise && !fallback) {
5312c470452SNick Mathewson 		LARGE_INTEGER freq;
5322c470452SNick Mathewson 		if (QueryPerformanceFrequency(&freq)) {
5332c470452SNick Mathewson 			LARGE_INTEGER counter;
5342c470452SNick Mathewson 			QueryPerformanceCounter(&counter);
5352c470452SNick Mathewson 			base->first_counter = counter.QuadPart;
5362c470452SNick Mathewson 			base->usec_per_count = 1.0e6 / freq.QuadPart;
5372c470452SNick Mathewson 			base->use_performance_counter = 1;
5382c470452SNick Mathewson 		}
5392c470452SNick Mathewson 	}
540f5e4eb05SNick Mathewson 
541f5e4eb05SNick Mathewson 	return 0;
542f5e4eb05SNick Mathewson }
543f5e4eb05SNick Mathewson 
5442c470452SNick Mathewson static inline ev_int64_t
abs64(ev_int64_t i)5452c470452SNick Mathewson abs64(ev_int64_t i)
5462c470452SNick Mathewson {
5472c470452SNick Mathewson 	return i < 0 ? -i : i;
5482c470452SNick Mathewson }
5492c470452SNick Mathewson 
5502c470452SNick Mathewson 
551f5e4eb05SNick Mathewson int
evutil_gettime_monotonic_(struct evutil_monotonic_timer * base,struct timeval * tp)552f5e4eb05SNick Mathewson evutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
553f5e4eb05SNick Mathewson     struct timeval *tp)
554f5e4eb05SNick Mathewson {
5552c470452SNick Mathewson 	ev_uint64_t ticks = evutil_GetTickCount_(base);
5562c470452SNick Mathewson 	if (base->use_performance_counter) {
5572c470452SNick Mathewson 		/* Here's a trick we took from BitTorrent's libutp, at Greg
5582c470452SNick Mathewson 		 * Hazel's recommendation.  We use QueryPerformanceCounter for
5592c470452SNick Mathewson 		 * our high-resolution timer, but use GetTickCount*() to keep
5602c470452SNick Mathewson 		 * it sane, and adjust_monotonic_time() to keep it monotonic.
5612c470452SNick Mathewson 		 */
5622c470452SNick Mathewson 		LARGE_INTEGER counter;
5632c470452SNick Mathewson 		ev_int64_t counter_elapsed, counter_usec_elapsed, ticks_elapsed;
5642c470452SNick Mathewson 		QueryPerformanceCounter(&counter);
5652c470452SNick Mathewson 		counter_elapsed = (ev_int64_t)
5662c470452SNick Mathewson 		    (counter.QuadPart - base->first_counter);
5672c470452SNick Mathewson 		ticks_elapsed = ticks - base->first_tick;
5682c470452SNick Mathewson 		/* TODO: This may upset VC6. If you need this to work with
5692c470452SNick Mathewson 		 * VC6, please supply an appropriate patch. */
5702c470452SNick Mathewson 		counter_usec_elapsed = (ev_int64_t)
5712c470452SNick Mathewson 		    (counter_elapsed * base->usec_per_count);
5722c470452SNick Mathewson 
5732c470452SNick Mathewson 		if (abs64(ticks_elapsed*1000 - counter_usec_elapsed) > 1000000) {
5742c470452SNick Mathewson 			/* It appears that the QueryPerformanceCounter()
5752c470452SNick Mathewson 			 * result is more than 1 second away from
5762c470452SNick Mathewson 			 * GetTickCount() result. Let's adjust it to be as
5772c470452SNick Mathewson 			 * accurate as we can; adjust_monotnonic_time() below
5782c470452SNick Mathewson 			 * will keep it monotonic. */
5792c470452SNick Mathewson 			counter_usec_elapsed = ticks_elapsed * 1000;
58085a40040SNick Mathewson 			base->first_counter = (ev_uint64_t) (counter.QuadPart - counter_usec_elapsed / base->usec_per_count);
581f5e4eb05SNick Mathewson 		}
58285a40040SNick Mathewson 		tp->tv_sec = (time_t) (counter_usec_elapsed / 1000000);
5832c470452SNick Mathewson 		tp->tv_usec = counter_usec_elapsed % 1000000;
5842c470452SNick Mathewson 
5852c470452SNick Mathewson 	} else {
5862c470452SNick Mathewson 		/* We're just using GetTickCount(). */
58785a40040SNick Mathewson 		tp->tv_sec = (time_t) (ticks / 1000);
588f5e4eb05SNick Mathewson 		tp->tv_usec = (ticks % 1000) * 1000;
5892c470452SNick Mathewson 	}
590f5e4eb05SNick Mathewson 	adjust_monotonic_time(base, tp);
591f5e4eb05SNick Mathewson 
592f5e4eb05SNick Mathewson 	return 0;
593f5e4eb05SNick Mathewson }
594f5e4eb05SNick Mathewson #endif
595f5e4eb05SNick Mathewson 
596f5e4eb05SNick Mathewson #if defined(HAVE_FALLBACK_MONOTONIC)
597f5e4eb05SNick Mathewson /* =====
598f5e4eb05SNick Mathewson    And if none of the other options work, let's just use gettimeofday(), and
599f5e4eb05SNick Mathewson    ratchet it forward so that it acts like a monotonic timer, whether it
600f5e4eb05SNick Mathewson    wants to or not.
601f5e4eb05SNick Mathewson  */
602f5e4eb05SNick Mathewson 
603f5e4eb05SNick Mathewson int
evutil_configure_monotonic_time_(struct evutil_monotonic_timer * base,int precise)604f5e4eb05SNick Mathewson evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
605f5e4eb05SNick Mathewson     int precise)
606f5e4eb05SNick Mathewson {
607f5e4eb05SNick Mathewson 	memset(base, 0, sizeof(*base));
608f5e4eb05SNick Mathewson 	return 0;
609f5e4eb05SNick Mathewson }
610f5e4eb05SNick Mathewson 
611f5e4eb05SNick Mathewson int
evutil_gettime_monotonic_(struct evutil_monotonic_timer * base,struct timeval * tp)612f5e4eb05SNick Mathewson evutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
613f5e4eb05SNick Mathewson     struct timeval *tp)
614f5e4eb05SNick Mathewson {
615f5e4eb05SNick Mathewson 	if (evutil_gettimeofday(tp, NULL) < 0)
616f5e4eb05SNick Mathewson 		return -1;
617f5e4eb05SNick Mathewson 	adjust_monotonic_time(base, tp);
618f5e4eb05SNick Mathewson 	return 0;
619f5e4eb05SNick Mathewson 
620f5e4eb05SNick Mathewson }
621f5e4eb05SNick Mathewson #endif
622