xref: /netbsd-src/external/bsd/ntp/dist/sntp/libevent/evutil_time.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1 /*	$NetBSD: evutil_time.c,v 1.7 2024/08/18 20:47:21 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "event2/event-config.h"
30 #include "evconfig-private.h"
31 
32 #ifdef _WIN32
33 #include <winsock2.h>
34 #define WIN32_LEAN_AND_MEAN
35 #include <windows.h>
36 #undef WIN32_LEAN_AND_MEAN
37 #endif
38 
39 #include <sys/types.h>
40 #ifdef EVENT__HAVE_STDLIB_H
41 #include <stdlib.h>
42 #endif
43 #include <errno.h>
44 #include <limits.h>
45 #ifndef EVENT__HAVE_GETTIMEOFDAY
46 #include <sys/timeb.h>
47 #endif
48 #if !defined(EVENT__HAVE_NANOSLEEP) && !defined(EVENT__HAVE_USLEEP) && \
49 	!defined(_WIN32)
50 #include <sys/select.h>
51 #endif
52 #include <time.h>
53 #include <sys/stat.h>
54 #include <string.h>
55 
56 /** evutil_usleep_() */
57 #if defined(_WIN32)
58 #elif defined(EVENT__HAVE_NANOSLEEP)
59 #elif defined(EVENT__HAVE_USLEEP)
60 #include <unistd.h>
61 #endif
62 
63 #include "event2/util.h"
64 #include "util-internal.h"
65 #include "log-internal.h"
66 #include "mm-internal.h"
67 
68 #ifndef EVENT__HAVE_GETTIMEOFDAY
69 /* No gettimeofday; this must be windows. */
70 
71 typedef void (WINAPI *GetSystemTimePreciseAsFileTime_fn_t) (LPFILETIME);
72 
73 int
74 evutil_gettimeofday(struct timeval *tv, struct timezone *tz)
75 {
76 #ifdef _MSC_VER
77 #define U64_LITERAL(n) n##ui64
78 #else
79 #define U64_LITERAL(n) n##llu
80 #endif
81 
82 	/* Conversion logic taken from Tor, which in turn took it
83 	 * from Perl.  GetSystemTimeAsFileTime returns its value as
84 	 * an unaligned (!) 64-bit value containing the number of
85 	 * 100-nanosecond intervals since 1 January 1601 UTC. */
86 #define EPOCH_BIAS U64_LITERAL(116444736000000000)
87 #define UNITS_PER_SEC U64_LITERAL(10000000)
88 #define USEC_PER_SEC U64_LITERAL(1000000)
89 #define UNITS_PER_USEC U64_LITERAL(10)
90 	union {
91 		FILETIME ft_ft;
92 		ev_uint64_t ft_64;
93 	} ft;
94 
95 	if (tv == NULL)
96 		return -1;
97 
98 	static GetSystemTimePreciseAsFileTime_fn_t GetSystemTimePreciseAsFileTime_fn = NULL;
99 	static int check_precise = 1;
100 
101 	if (EVUTIL_UNLIKELY(check_precise)) {
102 		HMODULE h = evutil_load_windows_system_library_(TEXT("kernel32.dll"));
103 		if (h != NULL)
104 			GetSystemTimePreciseAsFileTime_fn =
105 				(GetSystemTimePreciseAsFileTime_fn_t)
106 					GetProcAddress(h, "GetSystemTimePreciseAsFileTime");
107 		check_precise = 0;
108 	}
109 
110 	if (GetSystemTimePreciseAsFileTime_fn != NULL)
111 		GetSystemTimePreciseAsFileTime_fn(&ft.ft_ft);
112 	else
113 		GetSystemTimeAsFileTime(&ft.ft_ft);
114 
115 	if (EVUTIL_UNLIKELY(ft.ft_64 < EPOCH_BIAS)) {
116 		/* Time before the unix epoch. */
117 		return -1;
118 	}
119 	ft.ft_64 -= EPOCH_BIAS;
120 	tv->tv_sec = (long) (ft.ft_64 / UNITS_PER_SEC);
121 	tv->tv_usec = (long) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC);
122 	return 0;
123 }
124 #endif
125 
126 #define MAX_SECONDS_IN_MSEC_LONG \
127 	(((LONG_MAX) - 999) / 1000)
128 
129 long
130 evutil_tv_to_msec_(const struct timeval *tv)
131 {
132 	if (tv->tv_usec > 1000000 || tv->tv_sec > MAX_SECONDS_IN_MSEC_LONG)
133 		return -1;
134 
135 	return (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000);
136 }
137 
138 /*
139   Replacement for usleep on platforms that don't have one.  Not guaranteed to
140   be any more finegrained than 1 msec.
141  */
142 void
143 evutil_usleep_(const struct timeval *tv)
144 {
145 	if (!tv)
146 		return;
147 #if defined(_WIN32)
148 	{
149 		__int64 usec;
150 		LARGE_INTEGER li;
151 		HANDLE timer;
152 
153 		usec = tv->tv_sec * 1000000LL + tv->tv_usec;
154 		if (!usec)
155 			return;
156 
157 		li.QuadPart = -10LL * usec;
158 		timer = CreateWaitableTimer(NULL, TRUE, NULL);
159 		if (!timer)
160 			return;
161 
162 		SetWaitableTimer(timer, &li, 0, NULL, NULL, 0);
163 		WaitForSingleObject(timer, INFINITE);
164 		CloseHandle(timer);
165 	}
166 #elif defined(EVENT__HAVE_NANOSLEEP)
167 	{
168 		struct timespec ts;
169 		ts.tv_sec = tv->tv_sec;
170 		ts.tv_nsec = tv->tv_usec*1000;
171 		nanosleep(&ts, NULL);
172 	}
173 #elif defined(EVENT__HAVE_USLEEP)
174 	/* Some systems don't like to usleep more than 999999 usec */
175 	sleep(tv->tv_sec);
176 	usleep(tv->tv_usec);
177 #else
178 	{
179 		struct timeval tv2 = *tv;
180 		select(0, NULL, NULL, NULL, &tv2);
181 	}
182 #endif
183 }
184 
185 int
186 evutil_date_rfc1123(char *date, const size_t datelen, const struct tm *tm)
187 {
188 	static const char *DAYS[] =
189 		{ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
190 	static const char *MONTHS[] =
191 		{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
192 
193 	time_t t = time(NULL);
194 
195 #if defined(EVENT__HAVE__GMTIME64_S) || !defined(_WIN32)
196 	struct tm sys;
197 #endif
198 
199 	/* If `tm` is null, set system's current time. */
200 	if (tm == NULL) {
201 #if !defined(_WIN32)
202 		gmtime_r(&t, &sys);
203 		tm = &sys;
204 		/** detect _gmtime64()/_gmtime64_s() */
205 #elif defined(EVENT__HAVE__GMTIME64_S)
206 		errno_t err;
207 		err = _gmtime64_s(&sys, &t);
208 		if (err) {
209 			event_errx(1, "Invalid argument to _gmtime64_s");
210 		} else {
211 			tm = &sys;
212 		}
213 #elif defined(EVENT__HAVE__GMTIME64)
214 		tm = _gmtime64(&t);
215 #else
216 		tm = gmtime(&t);
217 #endif
218 	}
219 
220 	return evutil_snprintf(
221 		date, datelen, "%s, %02d %s %4d %02d:%02d:%02d GMT",
222 		DAYS[tm->tm_wday], tm->tm_mday, MONTHS[tm->tm_mon],
223 		1900 + tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec);
224 }
225 
226 /*
227    This function assumes it's called repeatedly with a
228    not-actually-so-monotonic time source whose outputs are in 'tv'. It
229    implements a trivial ratcheting mechanism so that the values never go
230    backwards.
231  */
232 static void
233 adjust_monotonic_time(struct evutil_monotonic_timer *base,
234     struct timeval *tv)
235 {
236 	evutil_timeradd(tv, &base->adjust_monotonic_clock, tv);
237 
238 	if (evutil_timercmp(tv, &base->last_time, <)) {
239 		/* Guess it wasn't monotonic after all. */
240 		struct timeval adjust;
241 		evutil_timersub(&base->last_time, tv, &adjust);
242 		evutil_timeradd(&adjust, &base->adjust_monotonic_clock,
243 		    &base->adjust_monotonic_clock);
244 		*tv = base->last_time;
245 	}
246 	base->last_time = *tv;
247 }
248 
249 /*
250    Allocate a new struct evutil_monotonic_timer
251  */
252 struct evutil_monotonic_timer *
253 evutil_monotonic_timer_new(void)
254 {
255   struct evutil_monotonic_timer *p = NULL;
256 
257   p = mm_malloc(sizeof(*p));
258   if (!p) goto done;
259 
260   memset(p, 0, sizeof(*p));
261 
262  done:
263   return p;
264 }
265 
266 /*
267    Free a struct evutil_monotonic_timer
268  */
269 void
270 evutil_monotonic_timer_free(struct evutil_monotonic_timer *timer)
271 {
272   if (timer) {
273     mm_free(timer);
274   }
275 }
276 
277 /*
278    Set up a struct evutil_monotonic_timer for initial use
279  */
280 int
281 evutil_configure_monotonic_time(struct evutil_monotonic_timer *timer,
282                                 int flags)
283 {
284   return evutil_configure_monotonic_time_(timer, flags);
285 }
286 
287 /*
288    Query the current monotonic time
289  */
290 int
291 evutil_gettime_monotonic(struct evutil_monotonic_timer *timer,
292                          struct timeval *tp)
293 {
294   return evutil_gettime_monotonic_(timer, tp);
295 }
296 
297 
298 #if defined(HAVE_POSIX_MONOTONIC)
299 /* =====
300    The POSIX clock_gettime() interface provides a few ways to get at a
301    monotonic clock.  CLOCK_MONOTONIC is most widely supported.  Linux also
302    provides a CLOCK_MONOTONIC_COARSE with accuracy of about 1-4 msec.
303 
304    On all platforms I'm aware of, CLOCK_MONOTONIC really is monotonic.
305    Platforms don't agree about whether it should jump on a sleep/resume.
306  */
307 
308 int
309 evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
310     int flags)
311 {
312 	/* CLOCK_MONOTONIC exists on FreeBSD, Linux, and Solaris.  You need to
313 	 * check for it at runtime, because some older kernel versions won't
314 	 * have it working. */
315 #ifdef CLOCK_MONOTONIC_COARSE
316 	const int precise = flags & EV_MONOT_PRECISE;
317 #endif
318 	const int fallback = flags & EV_MONOT_FALLBACK;
319 	struct timespec	ts;
320 
321 #ifdef CLOCK_MONOTONIC_COARSE
322 	if (CLOCK_MONOTONIC_COARSE < 0) {
323 		/* Technically speaking, nothing keeps CLOCK_* from being
324 		 * negative (as far as I know). This check and the one below
325 		 * make sure that it's safe for us to use -1 as an "unset"
326 		 * value. */
327 		event_errx(1,"I didn't expect CLOCK_MONOTONIC_COARSE to be < 0");
328 	}
329 	if (! precise && ! fallback) {
330 		if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) {
331 			base->monotonic_clock = CLOCK_MONOTONIC_COARSE;
332 			return 0;
333 		}
334 	}
335 #endif
336 	if (!fallback && clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
337 		base->monotonic_clock = CLOCK_MONOTONIC;
338 		return 0;
339 	}
340 
341 	if (CLOCK_MONOTONIC < 0) {
342 		event_errx(1,"I didn't expect CLOCK_MONOTONIC to be < 0");
343 	}
344 
345 	base->monotonic_clock = -1;
346 	return 0;
347 }
348 
349 int
350 evutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
351     struct timeval *tp)
352 {
353 	struct timespec ts;
354 
355 	if (base->monotonic_clock < 0) {
356 		if (evutil_gettimeofday(tp, NULL) < 0)
357 			return -1;
358 		adjust_monotonic_time(base, tp);
359 		return 0;
360 	}
361 
362 	if (clock_gettime(base->monotonic_clock, &ts) == -1)
363 		return -1;
364 	tp->tv_sec = ts.tv_sec;
365 	tp->tv_usec = ts.tv_nsec / 1000;
366 
367 	return 0;
368 }
369 #endif
370 
371 #if defined(HAVE_MACH_MONOTONIC)
372 /* ======
373    Apple is a little late to the POSIX party.  And why not?  Instead of
374    clock_gettime(), they provide mach_absolute_time().  Its units are not
375    fixed; we need to use mach_timebase_info() to get the right functions to
376    convert its units into nanoseconds.
377 
378    To all appearances, mach_absolute_time() seems to be honest-to-goodness
379    monotonic.  Whether it stops during sleep or not is unspecified in
380    principle, and dependent on CPU architecture in practice.
381  */
382 
383 int
384 evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
385     int flags)
386 {
387 	const int fallback = flags & EV_MONOT_FALLBACK;
388 	struct mach_timebase_info mi;
389 	memset(base, 0, sizeof(*base));
390 	/* OSX has mach_absolute_time() */
391 	if (!fallback &&
392 	    mach_timebase_info(&mi) == 0 &&
393 	    mach_absolute_time() != 0) {
394 		/* mach_timebase_info tells us how to convert
395 		 * mach_absolute_time() into nanoseconds, but we
396 		 * want to use microseconds instead. */
397 		mi.denom *= 1000;
398 		memcpy(&base->mach_timebase_units, &mi, sizeof(mi));
399 	} else {
400 		base->mach_timebase_units.numer = 0;
401 	}
402 	return 0;
403 }
404 
405 int
406 evutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
407     struct timeval *tp)
408 {
409 	ev_uint64_t abstime, usec;
410 	if (base->mach_timebase_units.numer == 0) {
411 		if (evutil_gettimeofday(tp, NULL) < 0)
412 			return -1;
413 		adjust_monotonic_time(base, tp);
414 		return 0;
415 	}
416 
417 	abstime = mach_absolute_time();
418 	usec = (abstime * base->mach_timebase_units.numer)
419 	    / (base->mach_timebase_units.denom);
420 	tp->tv_sec = usec / 1000000;
421 	tp->tv_usec = usec % 1000000;
422 
423 	return 0;
424 }
425 #endif
426 
427 #if defined(HAVE_WIN32_MONOTONIC)
428 /* =====
429    Turn we now to Windows.  Want monontonic time on Windows?
430 
431    Windows has QueryPerformanceCounter(), which gives time most high-
432    resolution time.  It's a pity it's not so monotonic in practice; it's
433    also got some fun bugs, especially: with older Windowses, under
434    virtualizations, with funny hardware, on multiprocessor systems, and so
435    on.  PEP418 [1] has a nice roundup of the issues here.
436 
437    There's GetTickCount64() on Vista and later, which gives a number of 1-msec
438    ticks since startup.  The accuracy here might be as bad as 10-20 msec, I
439    hear.  There's an undocumented function (NtSetTimerResolution) that
440    allegedly increases the accuracy. Good luck!
441 
442    There's also GetTickCount(), which is only 32 bits, but seems to be
443    supported on pre-Vista versions of Windows.  Apparently, you can coax
444    another 14 bits out of it, giving you 2231 years before rollover.
445 
446    The less said about timeGetTime() the better.
447 
448    "We don't care.  We don't have to.  We're the Phone Company."
449             -- Lily Tomlin, SNL
450 
451    Our strategy, if precise timers are turned off, is to just use the best
452    GetTickCount equivalent available.  If we've been asked for precise timing,
453    then we mostly[2] assume that GetTickCount is monotonic, and correct
454    GetPerformanceCounter to approximate it.
455 
456    [1] http://www.python.org/dev/peps/pep-0418
457    [2] Of course, we feed the Windows stuff into adjust_monotonic_time()
458        anyway, just in case it isn't.
459 
460  */
461 /*
462     Parts of our logic in the win32 timer code here are closely based on
463     BitTorrent's libUTP library.  That code is subject to the following
464     license:
465 
466       Copyright (c) 2010 BitTorrent, Inc.
467 
468       Permission is hereby granted, free of charge, to any person obtaining a
469       copy of this software and associated documentation files (the
470       "Software"), to deal in the Software without restriction, including
471       without limitation the rights to use, copy, modify, merge, publish,
472       distribute, sublicense, and/or sell copies of the Software, and to
473       permit persons to whom the Software is furnished to do so, subject to
474       the following conditions:
475 
476       The above copyright notice and this permission notice shall be included
477       in all copies or substantial portions of the Software.
478 
479       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
480       OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
481       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
482       NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
483       LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
484       OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
485       WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
486 */
487 
488 static ev_uint64_t
489 evutil_GetTickCount_(struct evutil_monotonic_timer *base)
490 {
491 	if (base->GetTickCount64_fn) {
492 		/* Let's just use GetTickCount64 if we can. */
493 		return base->GetTickCount64_fn();
494 	} else if (base->GetTickCount_fn) {
495 		/* Greg Hazel assures me that this works, that BitTorrent has
496 		 * done it for years, and this it won't turn around and
497 		 * bite us.  He says they found it on some game programmers'
498 		 * forum some time around 2007.
499 		 */
500 		ev_uint64_t v = base->GetTickCount_fn();
501 		return (DWORD)v | ((v >> 18) & 0xFFFFFFFF00000000);
502 	} else {
503 		/* Here's the fallback implementation. We have to use
504 		 * GetTickCount() with its given signature, so we only get
505 		 * 32 bits worth of milliseconds, which will roll ove every
506 		 * 49 days or so.  */
507 		DWORD ticks = GetTickCount();
508 		if (ticks < base->last_tick_count) {
509 			base->adjust_tick_count += ((ev_uint64_t)1) << 32;
510 		}
511 		base->last_tick_count = ticks;
512 		return ticks + base->adjust_tick_count;
513 	}
514 }
515 
516 int
517 evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
518     int flags)
519 {
520 	const int precise = flags & EV_MONOT_PRECISE;
521 	const int fallback = flags & EV_MONOT_FALLBACK;
522 	HANDLE h;
523 	memset(base, 0, sizeof(*base));
524 
525 	h = evutil_load_windows_system_library_(TEXT("kernel32.dll"));
526 	if (h != NULL && !fallback) {
527 		base->GetTickCount64_fn = (ev_GetTickCount_func)GetProcAddress(h, "GetTickCount64");
528 		base->GetTickCount_fn = (ev_GetTickCount_func)GetProcAddress(h, "GetTickCount");
529 	}
530 
531 	base->first_tick = base->last_tick_count = evutil_GetTickCount_(base);
532 	if (precise && !fallback) {
533 		LARGE_INTEGER freq;
534 		if (QueryPerformanceFrequency(&freq)) {
535 			LARGE_INTEGER counter;
536 			QueryPerformanceCounter(&counter);
537 			base->first_counter = counter.QuadPart;
538 			base->usec_per_count = 1.0e6 / freq.QuadPart;
539 			base->use_performance_counter = 1;
540 		}
541 	}
542 
543 	return 0;
544 }
545 
546 static inline ev_int64_t
547 abs64(ev_int64_t i)
548 {
549 	return i < 0 ? -i : i;
550 }
551 
552 
553 int
554 evutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
555     struct timeval *tp)
556 {
557 	ev_uint64_t ticks = evutil_GetTickCount_(base);
558 	if (base->use_performance_counter) {
559 		/* Here's a trick we took from BitTorrent's libutp, at Greg
560 		 * Hazel's recommendation.  We use QueryPerformanceCounter for
561 		 * our high-resolution timer, but use GetTickCount*() to keep
562 		 * it sane, and adjust_monotonic_time() to keep it monotonic.
563 		 */
564 		LARGE_INTEGER counter;
565 		ev_int64_t counter_elapsed, counter_usec_elapsed, ticks_elapsed;
566 		QueryPerformanceCounter(&counter);
567 		counter_elapsed = (ev_int64_t)
568 		    (counter.QuadPart - base->first_counter);
569 		ticks_elapsed = ticks - base->first_tick;
570 		/* TODO: This may upset VC6. If you need this to work with
571 		 * VC6, please supply an appropriate patch. */
572 		counter_usec_elapsed = (ev_int64_t)
573 		    (counter_elapsed * base->usec_per_count);
574 
575 		if (abs64(ticks_elapsed*1000 - counter_usec_elapsed) > 1000000) {
576 			/* It appears that the QueryPerformanceCounter()
577 			 * result is more than 1 second away from
578 			 * GetTickCount() result. Let's adjust it to be as
579 			 * accurate as we can; adjust_monotnonic_time() below
580 			 * will keep it monotonic. */
581 			counter_usec_elapsed = ticks_elapsed * 1000;
582 			base->first_counter = (ev_uint64_t) (counter.QuadPart - counter_usec_elapsed / base->usec_per_count);
583 		}
584 		tp->tv_sec = (time_t) (counter_usec_elapsed / 1000000);
585 		tp->tv_usec = counter_usec_elapsed % 1000000;
586 
587 	} else {
588 		/* We're just using GetTickCount(). */
589 		tp->tv_sec = (time_t) (ticks / 1000);
590 		tp->tv_usec = (ticks % 1000) * 1000;
591 	}
592 	adjust_monotonic_time(base, tp);
593 
594 	return 0;
595 }
596 #endif
597 
598 #if defined(HAVE_FALLBACK_MONOTONIC)
599 /* =====
600    And if none of the other options work, let's just use gettimeofday(), and
601    ratchet it forward so that it acts like a monotonic timer, whether it
602    wants to or not.
603  */
604 
605 int
606 evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
607     int precise)
608 {
609 	memset(base, 0, sizeof(*base));
610 	return 0;
611 }
612 
613 int
614 evutil_gettime_monotonic_(struct evutil_monotonic_timer *base,
615     struct timeval *tp)
616 {
617 	if (evutil_gettimeofday(tp, NULL) < 0)
618 		return -1;
619 	adjust_monotonic_time(base, tp);
620 	return 0;
621 
622 }
623 #endif
624