Skip to content

Commit

Permalink
Use GetSystemTimeAsFileTime to implement gettimeofday on win32.
Browse files Browse the repository at this point in the history
It is (in my benchmarks) way faster than _ftime, though the
conversion process is not so straightforward.  In theory, it can
have a better granularity too, though in practice who knows what
you're getting.
  • Loading branch information
nmathewson committed Dec 16, 2010
1 parent 04ba27e commit b8b8aa5
Showing 1 changed file with 28 additions and 13 deletions.
41 changes: 28 additions & 13 deletions evutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,26 +364,41 @@ evutil_strtoll(const char *s, char **endptr, int base)
}

#ifndef _EVENT_HAVE_GETTIMEOFDAY
/* No gettimeofday; this muse be windows. */
/* No gettimeofday; this must be windows. */
int
evutil_gettimeofday(struct timeval *tv, struct timezone *tz)
{
struct _timeb tb;
#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;

/* XXXX
* _ftime is not the greatest interface here; GetSystemTimeAsFileTime
* would give us better resolution, whereas something cobbled together
* with GetTickCount could maybe give us monotonic behavior.
*
* Either way, I think this value might be skewed to ignore the
* timezone, and just return local time. That's not so good.
*/
_ftime(&tb);
tv->tv_sec = (long) tb.time;
tv->tv_usec = ((int) tb.millitm) * 1000;
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
Expand Down

0 comments on commit b8b8aa5

Please sign in to comment.