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