| /* |
| * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "event2/event-config.h" |
| #include "evconfig-private.h" |
| |
| #ifdef _WIN32 |
| #include <winsock2.h> |
| #define WIN32_LEAN_AND_MEAN |
| #include <windows.h> |
| #undef WIN32_LEAN_AND_MEAN |
| #endif |
| |
| #include <sys/types.h> |
| #ifdef EVENT__HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| #include <errno.h> |
| #include <limits.h> |
| #ifndef EVENT__HAVE_GETTIMEOFDAY |
| #include <sys/timeb.h> |
| #endif |
| #if !defined(EVENT__HAVE_NANOSLEEP) && !defined(EVENT__HAVE_USLEEP) && \ |
| !defined(_WIN32) |
| #include <sys/select.h> |
| #endif |
| #include <time.h> |
| #include <sys/stat.h> |
| #include <string.h> |
| |
| /** evutil_usleep_() */ |
| #if defined(_WIN32) |
| #elif defined(EVENT__HAVE_NANOSLEEP) |
| #elif defined(EVENT__HAVE_USLEEP) |
| #include <unistd.h> |
| #endif |
| |
| #include "event2/util.h" |
| #include "util-internal.h" |
| #include "log-internal.h" |
| #include "mm-internal.h" |
| |
| #ifndef EVENT__HAVE_GETTIMEOFDAY |
| /* No gettimeofday; this must be windows. */ |
| |
| typedef void (WINAPI *GetSystemTimePreciseAsFileTime_fn_t) (LPFILETIME); |
| |
| int |
| evutil_gettimeofday(struct timeval *tv, struct timezone *tz) |
| { |
| #ifdef _MSC_VER |
| #define U64_LITERAL(n) n##ui64 |
| #else |
| #define U64_LITERAL(n) n##llu |
| #endif |
| |
| /* Conversion logic taken from Tor, which in turn took it |
| * from Perl. GetSystemTimeAsFileTime returns its value as |
| * an unaligned (!) 64-bit value containing the number of |
| * 100-nanosecond intervals since 1 January 1601 UTC. */ |
| #define EPOCH_BIAS U64_LITERAL(116444736000000000) |
| #define UNITS_PER_SEC U64_LITERAL(10000000) |
| #define USEC_PER_SEC U64_LITERAL(1000000) |
| #define UNITS_PER_USEC U64_LITERAL(10) |
| union { |
| FILETIME ft_ft; |
| ev_uint64_t ft_64; |
| } ft; |
| |
| if (tv == NULL) |
| return -1; |
| |
| static GetSystemTimePreciseAsFileTime_fn_t GetSystemTimePreciseAsFileTime_fn = NULL; |
| static int check_precise = 1; |
| |
| if (EVUTIL_UNLIKELY(check_precise)) { |
| HMODULE h = evutil_load_windows_system_library_(TEXT("kernel32.dll")); |
| if (h != NULL) |
| GetSystemTimePreciseAsFileTime_fn = |
| (GetSystemTimePreciseAsFileTime_fn_t) |
| GetProcAddress(h, "GetSystemTimePreciseAsFileTime"); |
| check_precise = 0; |
| } |
| |
| if (GetSystemTimePreciseAsFileTime_fn != NULL) |
| GetSystemTimePreciseAsFileTime_fn(&ft.ft_ft); |
| else |
| GetSystemTimeAsFileTime(&ft.ft_ft); |
| |
| if (EVUTIL_UNLIKELY(ft.ft_64 < EPOCH_BIAS)) { |
| /* Time before the unix epoch. */ |
| return -1; |
| } |
| ft.ft_64 -= EPOCH_BIAS; |
| tv->tv_sec = (long) (ft.ft_64 / UNITS_PER_SEC); |
| tv->tv_usec = (long) ((ft.ft_64 / UNITS_PER_USEC) % USEC_PER_SEC); |
| return 0; |
| } |
| #endif |
| |
| #define MAX_SECONDS_IN_MSEC_LONG \ |
| (((LONG_MAX) - 999) / 1000) |
| |
| long |
| evutil_tv_to_msec_(const struct timeval *tv) |
| { |
| if (tv->tv_usec > 1000000 || tv->tv_sec > MAX_SECONDS_IN_MSEC_LONG) |
| return -1; |
| |
| return (tv->tv_sec * 1000) + ((tv->tv_usec + 999) / 1000); |
| } |
| |
| /* |
| Replacement for usleep on platforms that don't have one. Not guaranteed to |
| be any more finegrained than 1 msec. |
| */ |
| void |
| evutil_usleep_(const struct timeval *tv) |
| { |
| if (!tv) |
| return; |
| #if defined(_WIN32) |
| { |
| __int64 usec; |
| LARGE_INTEGER li; |
| HANDLE timer; |
| |
| usec = tv->tv_sec * 1000000LL + tv->tv_usec; |
| if (!usec) |
| return; |
| |
| li.QuadPart = -10LL * usec; |
| timer = CreateWaitableTimer(NULL, TRUE, NULL); |
| if (!timer) |
| return; |
| |
| SetWaitableTimer(timer, &li, 0, NULL, NULL, 0); |
| WaitForSingleObject(timer, INFINITE); |
| CloseHandle(timer); |
| } |
| #elif defined(EVENT__HAVE_NANOSLEEP) |
| { |
| struct timespec ts; |
| ts.tv_sec = tv->tv_sec; |
| ts.tv_nsec = tv->tv_usec*1000; |
| nanosleep(&ts, NULL); |
| } |
| #elif defined(EVENT__HAVE_USLEEP) |
| /* Some systems don't like to usleep more than 999999 usec */ |
| sleep(tv->tv_sec); |
| usleep(tv->tv_usec); |
| #else |
| { |
| struct timeval tv2 = *tv; |
| select(0, NULL, NULL, NULL, &tv2); |
| } |
| #endif |
| } |
| |
| int |
| evutil_date_rfc1123(char *date, const size_t datelen, const struct tm *tm) |
| { |
| static const char *DAYS[] = |
| { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; |
| static const char *MONTHS[] = |
| { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; |
| |
| time_t t = time(NULL); |
| |
| #if defined(EVENT__HAVE__GMTIME64_S) || !defined(_WIN32) |
| struct tm sys; |
| #endif |
| |
| /* If `tm` is null, set system's current time. */ |
| if (tm == NULL) { |
| #if !defined(_WIN32) |
| gmtime_r(&t, &sys); |
| tm = &sys; |
| /** detect _gmtime64()/_gmtime64_s() */ |
| #elif defined(EVENT__HAVE__GMTIME64_S) |
| errno_t err; |
| err = _gmtime64_s(&sys, &t); |
| if (err) { |
| event_errx(1, "Invalid argument to _gmtime64_s"); |
| } else { |
| tm = &sys; |
| } |
| #elif defined(EVENT__HAVE__GMTIME64) |
| tm = _gmtime64(&t); |
| #else |
| tm = gmtime(&t); |
| #endif |
| } |
| |
| return evutil_snprintf( |
| date, datelen, "%s, %02d %s %4d %02d:%02d:%02d GMT", |
| DAYS[tm->tm_wday], tm->tm_mday, MONTHS[tm->tm_mon], |
| 1900 + tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec); |
| } |
| |
| /* |
| This function assumes it's called repeatedly with a |
| not-actually-so-monotonic time source whose outputs are in 'tv'. It |
| implements a trivial ratcheting mechanism so that the values never go |
| backwards. |
| */ |
| static void |
| adjust_monotonic_time(struct evutil_monotonic_timer *base, |
| struct timeval *tv) |
| { |
| evutil_timeradd(tv, &base->adjust_monotonic_clock, tv); |
| |
| if (evutil_timercmp(tv, &base->last_time, <)) { |
| /* Guess it wasn't monotonic after all. */ |
| struct timeval adjust; |
| evutil_timersub(&base->last_time, tv, &adjust); |
| evutil_timeradd(&adjust, &base->adjust_monotonic_clock, |
| &base->adjust_monotonic_clock); |
| *tv = base->last_time; |
| } |
| base->last_time = *tv; |
| } |
| |
| /* |
| Allocate a new struct evutil_monotonic_timer |
| */ |
| struct evutil_monotonic_timer * |
| evutil_monotonic_timer_new(void) |
| { |
| struct evutil_monotonic_timer *p = NULL; |
| |
| p = mm_malloc(sizeof(*p)); |
| if (!p) goto done; |
| |
| memset(p, 0, sizeof(*p)); |
| |
| done: |
| return p; |
| } |
| |
| /* |
| Free a struct evutil_monotonic_timer |
| */ |
| void |
| evutil_monotonic_timer_free(struct evutil_monotonic_timer *timer) |
| { |
| if (timer) { |
| mm_free(timer); |
| } |
| } |
| |
| /* |
| Set up a struct evutil_monotonic_timer for initial use |
| */ |
| int |
| evutil_configure_monotonic_time(struct evutil_monotonic_timer *timer, |
| int flags) |
| { |
| return evutil_configure_monotonic_time_(timer, flags); |
| } |
| |
| /* |
| Query the current monotonic time |
| */ |
| int |
| evutil_gettime_monotonic(struct evutil_monotonic_timer *timer, |
| struct timeval *tp) |
| { |
| return evutil_gettime_monotonic_(timer, tp); |
| } |
| |
| |
| #if defined(HAVE_POSIX_MONOTONIC) |
| /* ===== |
| The POSIX clock_gettime() interface provides a few ways to get at a |
| monotonic clock. CLOCK_MONOTONIC is most widely supported. Linux also |
| provides a CLOCK_MONOTONIC_COARSE with accuracy of about 1-4 msec. |
| |
| On all platforms I'm aware of, CLOCK_MONOTONIC really is monotonic. |
| Platforms don't agree about whether it should jump on a sleep/resume. |
| */ |
| |
| int |
| evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base, |
| int flags) |
| { |
| /* CLOCK_MONOTONIC exists on FreeBSD, Linux, and Solaris. You need to |
| * check for it at runtime, because some older kernel versions won't |
| * have it working. */ |
| #ifdef CLOCK_MONOTONIC_COARSE |
| const int precise = flags & EV_MONOT_PRECISE; |
| #endif |
| const int fallback = flags & EV_MONOT_FALLBACK; |
| struct timespec ts; |
| |
| #ifdef CLOCK_MONOTONIC_COARSE |
| if (CLOCK_MONOTONIC_COARSE < 0) { |
| /* Technically speaking, nothing keeps CLOCK_* from being |
| * negative (as far as I know). This check and the one below |
| * make sure that it's safe for us to use -1 as an "unset" |
| * value. */ |
| event_errx(1,"I didn't expect CLOCK_MONOTONIC_COARSE to be < 0"); |
| } |
| if (! precise && ! fallback) { |
| if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) { |
| base->monotonic_clock = CLOCK_MONOTONIC_COARSE; |
| return 0; |
| } |
| } |
| #endif |
| if (!fallback && clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { |
| base->monotonic_clock = CLOCK_MONOTONIC; |
| return 0; |
| } |
| |
| if (CLOCK_MONOTONIC < 0) { |
| event_errx(1,"I didn't expect CLOCK_MONOTONIC to be < 0"); |
| } |
| |
| base->monotonic_clock = -1; |
| return 0; |
| } |
| |
| int |
| evutil_gettime_monotonic_(struct evutil_monotonic_timer *base, |
| struct timeval *tp) |
| { |
| struct timespec ts; |
| |
| if (base->monotonic_clock < 0) { |
| if (evutil_gettimeofday(tp, NULL) < 0) |
| return -1; |
| adjust_monotonic_time(base, tp); |
| return 0; |
| } |
| |
| if (clock_gettime(base->monotonic_clock, &ts) == -1) |
| return -1; |
| tp->tv_sec = ts.tv_sec; |
| tp->tv_usec = ts.tv_nsec / 1000; |
| |
| return 0; |
| } |
| #endif |
| |
| #if defined(HAVE_MACH_MONOTONIC) |
| /* ====== |
| Apple is a little late to the POSIX party. And why not? Instead of |
| clock_gettime(), they provide mach_absolute_time(). Its units are not |
| fixed; we need to use mach_timebase_info() to get the right functions to |
| convert its units into nanoseconds. |
| |
| To all appearances, mach_absolute_time() seems to be honest-to-goodness |
| monotonic. Whether it stops during sleep or not is unspecified in |
| principle, and dependent on CPU architecture in practice. |
| */ |
| |
| int |
| evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base, |
| int flags) |
| { |
| const int fallback = flags & EV_MONOT_FALLBACK; |
| struct mach_timebase_info mi; |
| memset(base, 0, sizeof(*base)); |
| /* OSX has mach_absolute_time() */ |
| if (!fallback && |
| mach_timebase_info(&mi) == 0 && |
| mach_absolute_time() != 0) { |
| /* mach_timebase_info tells us how to convert |
| * mach_absolute_time() into nanoseconds, but we |
| * want to use microseconds instead. */ |
| mi.denom *= 1000; |
| memcpy(&base->mach_timebase_units, &mi, sizeof(mi)); |
| } else { |
| base->mach_timebase_units.numer = 0; |
| } |
| return 0; |
| } |
| |
| int |
| evutil_gettime_monotonic_(struct evutil_monotonic_timer *base, |
| struct timeval *tp) |
| { |
| ev_uint64_t abstime, usec; |
| if (base->mach_timebase_units.numer == 0) { |
| if (evutil_gettimeofday(tp, NULL) < 0) |
| return -1; |
| adjust_monotonic_time(base, tp); |
| return 0; |
| } |
| |
| abstime = mach_absolute_time(); |
| usec = (abstime * base->mach_timebase_units.numer) |
| / (base->mach_timebase_units.denom); |
| tp->tv_sec = usec / 1000000; |
| tp->tv_usec = usec % 1000000; |
| |
| return 0; |
| } |
| #endif |
| |
| #if defined(HAVE_WIN32_MONOTONIC) |
| /* ===== |
| Turn we now to Windows. Want monontonic time on Windows? |
| |
| Windows has QueryPerformanceCounter(), which gives time most high- |
| resolution time. It's a pity it's not so monotonic in practice; it's |
| also got some fun bugs, especially: with older Windowses, under |
| virtualizations, with funny hardware, on multiprocessor systems, and so |
| on. PEP418 [1] has a nice roundup of the issues here. |
| |
| There's GetTickCount64() on Vista and later, which gives a number of 1-msec |
| ticks since startup. The accuracy here might be as bad as 10-20 msec, I |
| hear. There's an undocumented function (NtSetTimerResolution) that |
| allegedly increases the accuracy. Good luck! |
| |
| There's also GetTickCount(), which is only 32 bits, but seems to be |
| supported on pre-Vista versions of Windows. Apparently, you can coax |
| another 14 bits out of it, giving you 2231 years before rollover. |
| |
| The less said about timeGetTime() the better. |
| |
| "We don't care. We don't have to. We're the Phone Company." |
| -- Lily Tomlin, SNL |
| |
| Our strategy, if precise timers are turned off, is to just use the best |
| GetTickCount equivalent available. If we've been asked for precise timing, |
| then we mostly[2] assume that GetTickCount is monotonic, and correct |
| GetPerformanceCounter to approximate it. |
| |
| [1] http://www.python.org/dev/peps/pep-0418 |
| [2] Of course, we feed the Windows stuff into adjust_monotonic_time() |
| anyway, just in case it isn't. |
| |
| */ |
| /* |
| Parts of our logic in the win32 timer code here are closely based on |
| BitTorrent's libUTP library. That code is subject to the following |
| license: |
| |
| Copyright (c) 2010 BitTorrent, Inc. |
| |
| Permission is hereby granted, free of charge, to any person obtaining a |
| copy of this software and associated documentation files (the |
| "Software"), to deal in the Software without restriction, including |
| without limitation the rights to use, copy, modify, merge, publish, |
| distribute, sublicense, and/or sell copies of the Software, and to |
| permit persons to whom the Software is furnished to do so, subject to |
| the following conditions: |
| |
| The above copyright notice and this permission notice shall be included |
| in all copies or substantial portions of the Software. |
| |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| static ev_uint64_t |
| evutil_GetTickCount_(struct evutil_monotonic_timer *base) |
| { |
| if (base->GetTickCount64_fn) { |
| /* Let's just use GetTickCount64 if we can. */ |
| return base->GetTickCount64_fn(); |
| } else if (base->GetTickCount_fn) { |
| /* Greg Hazel assures me that this works, that BitTorrent has |
| * done it for years, and this it won't turn around and |
| * bite us. He says they found it on some game programmers' |
| * forum some time around 2007. |
| */ |
| ev_uint64_t v = base->GetTickCount_fn(); |
| return (DWORD)v | ((v >> 18) & 0xFFFFFFFF00000000); |
| } else { |
| /* Here's the fallback implementation. We have to use |
| * GetTickCount() with its given signature, so we only get |
| * 32 bits worth of milliseconds, which will roll ove every |
| * 49 days or so. */ |
| DWORD ticks = GetTickCount(); |
| if (ticks < base->last_tick_count) { |
| base->adjust_tick_count += ((ev_uint64_t)1) << 32; |
| } |
| base->last_tick_count = ticks; |
| return ticks + base->adjust_tick_count; |
| } |
| } |
| |
| int |
| evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base, |
| int flags) |
| { |
| const int precise = flags & EV_MONOT_PRECISE; |
| const int fallback = flags & EV_MONOT_FALLBACK; |
| HANDLE h; |
| memset(base, 0, sizeof(*base)); |
| |
| h = evutil_load_windows_system_library_(TEXT("kernel32.dll")); |
| if (h != NULL && !fallback) { |
| base->GetTickCount64_fn = (ev_GetTickCount_func)GetProcAddress(h, "GetTickCount64"); |
| base->GetTickCount_fn = (ev_GetTickCount_func)GetProcAddress(h, "GetTickCount"); |
| } |
| |
| base->first_tick = base->last_tick_count = evutil_GetTickCount_(base); |
| if (precise && !fallback) { |
| LARGE_INTEGER freq; |
| if (QueryPerformanceFrequency(&freq)) { |
| LARGE_INTEGER counter; |
| QueryPerformanceCounter(&counter); |
| base->first_counter = counter.QuadPart; |
| base->usec_per_count = 1.0e6 / freq.QuadPart; |
| base->use_performance_counter = 1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| static inline ev_int64_t |
| abs64(ev_int64_t i) |
| { |
| return i < 0 ? -i : i; |
| } |
| |
| |
| int |
| evutil_gettime_monotonic_(struct evutil_monotonic_timer *base, |
| struct timeval *tp) |
| { |
| ev_uint64_t ticks = evutil_GetTickCount_(base); |
| if (base->use_performance_counter) { |
| /* Here's a trick we took from BitTorrent's libutp, at Greg |
| * Hazel's recommendation. We use QueryPerformanceCounter for |
| * our high-resolution timer, but use GetTickCount*() to keep |
| * it sane, and adjust_monotonic_time() to keep it monotonic. |
| */ |
| LARGE_INTEGER counter; |
| ev_int64_t counter_elapsed, counter_usec_elapsed, ticks_elapsed; |
| QueryPerformanceCounter(&counter); |
| counter_elapsed = (ev_int64_t) |
| (counter.QuadPart - base->first_counter); |
| ticks_elapsed = ticks - base->first_tick; |
| /* TODO: This may upset VC6. If you need this to work with |
| * VC6, please supply an appropriate patch. */ |
| counter_usec_elapsed = (ev_int64_t) |
| (counter_elapsed * base->usec_per_count); |
| |
| if (abs64(ticks_elapsed*1000 - counter_usec_elapsed) > 1000000) { |
| /* It appears that the QueryPerformanceCounter() |
| * result is more than 1 second away from |
| * GetTickCount() result. Let's adjust it to be as |
| * accurate as we can; adjust_monotnonic_time() below |
| * will keep it monotonic. */ |
| counter_usec_elapsed = ticks_elapsed * 1000; |
| base->first_counter = (ev_uint64_t) (counter.QuadPart - counter_usec_elapsed / base->usec_per_count); |
| } |
| tp->tv_sec = (time_t) (counter_usec_elapsed / 1000000); |
| tp->tv_usec = counter_usec_elapsed % 1000000; |
| |
| } else { |
| /* We're just using GetTickCount(). */ |
| tp->tv_sec = (time_t) (ticks / 1000); |
| tp->tv_usec = (ticks % 1000) * 1000; |
| } |
| adjust_monotonic_time(base, tp); |
| |
| return 0; |
| } |
| #endif |
| |
| #if defined(HAVE_FALLBACK_MONOTONIC) |
| /* ===== |
| And if none of the other options work, let's just use gettimeofday(), and |
| ratchet it forward so that it acts like a monotonic timer, whether it |
| wants to or not. |
| */ |
| |
| int |
| evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base, |
| int precise) |
| { |
| memset(base, 0, sizeof(*base)); |
| return 0; |
| } |
| |
| int |
| evutil_gettime_monotonic_(struct evutil_monotonic_timer *base, |
| struct timeval *tp) |
| { |
| if (evutil_gettimeofday(tp, NULL) < 0) |
| return -1; |
| adjust_monotonic_time(base, tp); |
| return 0; |
| |
| } |
| #endif |