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