thoughts on timestamp problems
Fri Oct 16 13:12:00 GMT 2009
My recent utimens_fs patch helped, but was not enough - the gnulib tests
for utimensat are still failing. I've traced it to the fact that
clock_gettime can lag behind GetSystemTimeAsFileTime. If this sequence is
the first action that primes hires_ms:
then the two st_mtim values match. But if enough other timestamp activity
occurs between hires_ms::prime and the above sequence, then I'm frequently
seeing st1 have a newer timestamp than st2, meaning that cygwin's notion
of clock_gettime has fallen behind.
Looking more at times.cc and at various things found by google, I'm
wondering why hires_ms is calling timeGetTime() at all - that is only
documented as having a resolution between 1 and 15.25 milliseconds. But
our systime() call, which wraps GetSystemTimeAsFileTime, has higher
resolution (100 ns) but the same quantization (when timeGetTime has 15 ms
resolution, then GetSystemTimeAsFileTime only observably increments in
15ms chunks). In other words, if we were to forgo timeGetTime altogether,
then the timestamps we pick up in utimens_fs will always match the
timestamps that windows would have chosen at the same moment in time, so
that we will never make file times appear to move backwards due to UTIME_NOW.
Or maybe I need to understand more about the difference between hires_ms
and hires_us. cgf did a lot of work on this back in Nov 2005, but I still
think there is more that can be done.
Right now, hires_us, but not hires_ms, is using QueryPerformanceCounter to
determine time to a better quantization than timeGetTime or
GetSystemTimeAsFileTime. But MSDN makes it seem like
QueryPerformanceCounter might not always exist, and the cygwin code for
hires_us caters to that with an ENOSYS path. Also, it looks like most
cygwin code uses hires_ms, not hires_us (only strace.cc referenced the
Then there was this web page:
which suggests a way to use a mixture of timeGetTime and
QueryPerformanceCounter to get sub-millesecond sleep accuracy without the
penalty of calling timeBeginPeriod (in other words, use normal millisecond
granularity to burn most of the time down, then QueryPerformanceCounter to
get the rest of the way without burning processor time for the bulk of the
I guess I'd like any insights on whether changing hires_ms to quit using
timeGetTime, or even changing clock_gettime to use hires_us instead of
hires_ms, might have any performance impacts I'm not aware of.
Don't work too hard, make some time for fun as well!
Eric Blake email@example.com
More information about the Cygwin-developers