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