/* Conversion logic taken from Tor, which in turn took it *fromPerl.GetSystemTimeAsFileTimereturnsitsvalueas *anunaligned(!)64-bitvaluecontainingthenumberof
* 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); return0;
} #endif
int
evutil_configure_monotonic_time_(struct evutil_monotonic_timer *base,
int flags)
{ /* CLOCK_MONOTONIC exists on FreeBSD, Linux, and Solaris. You need to *checkforitatruntime,becausesomeolderkernelversionswon'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(asfarasIknow).Thischeckandtheonebelow *makesurethatit'ssafeforustouse-1asan"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; return0;
}
} #endif
if (!fallback && clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
base->monotonic_clock = CLOCK_MONOTONIC; return0;
}
if (CLOCK_MONOTONIC < 0) {
event_errx(1,"I didn't expect CLOCK_MONOTONIC to be < 0");
}
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 *doneitforyears,andthisitwon'tturnaroundand *biteus.Hesaystheyfounditonsomegameprogrammers' *forumsometimearound2007.
*/
ev_uint64_t v = base->GetTickCount_fn(); return (DWORD)v | ((v >> 18) & 0xFFFFFFFF00000000);
} else { /* Here's the fallback implementation. We have to use *GetTickCount()withitsgivensignature,soweonlyget *32bitsworthofmilliseconds,whichwillrolloveevery
* 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");
}
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'srecommendation.WeuseQueryPerformanceCounterfor *ourhigh-resolutiontimer,butuseGetTickCount*()tokeep *itsane,andadjust_monotonic_time()tokeepitmonotonic.
*/
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() *resultismorethan1secondawayfrom *GetTickCount()result.Let'sadjustittobeas *accurateaswecan;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;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.