Hi folks, I actually noticed this in 1.7.9, but looking at the source in CVS I can see it's still present in 1.7.10. Here's the STC:
> $ cat clockres.c #include <stdio.h> #include <time.h> #include <errno.h> int main (int argc, const char **argv) { struct timespec ts; if (clock_getres (CLOCK_MONOTONIC, &ts) < 0) { fprintf (stderr, "Bad: %d\n", errno); return -1; } printf ("%ld sec, %ld nanos\n", ts.tv_sec, ts.tv_nsec); return 0; } > $ gcc-4 clockres.c -o clockres -W -Wall -Wextra > clockres.c: In function 'main': > clockres.c:6:15: warning: unused parameter 'argc' > clockres.c:6:34: warning: unused parameter 'argv' > > $ ./clockres.exe > 0 sec, 0 nanos > > $ This happens because on my PC, QueryPerformanceFrequency returns 2511600000, so the following code in times.cc#hires_ns::prime() > freq = (double) ((double) 1000000000. / (double) ifreq.QuadPart); calculates freq correctly(*) as 0.39815257206561555. This means that the resolution is less than a nanosecond, so hires_ns::resolution(), which is where clock_getres gets the result from, ... > LONGLONG > hires_ns::resolution () > { > if (!inited) > prime (); > if (inited < 0) > { > set_errno (ENOSYS); > return (long long) -1; > } > > return (LONGLONG) freq; > } ... truncates it to zero. (The libgfortran testsuite barfs on this.) Although the resolution is too small to express in integer nanoseconds, that's ok when it's used to calculate the actual time, because that is all done in double precision before being truncated to integer, in hires_ns::nsecs() here: > // FIXME: Use round() here? > now.QuadPart = (LONGLONG) (freq * (double) (now.QuadPart - > primed_pc.QuadPart)); > return now.QuadPart; So we'll calculate the correct time to the nearest nanosecond anyway. Since that's the maximum resolution that we can return in a timespec from clock_gettime anyway, I think we should just round up resolutions less than 1ns to pretend they're exactly 1ns. winsup/cygwin/ChangeLog: * times.cc (hires_ns::resolution): Don't return less than 1. Tested by building the clean sources, copying the DLL and test executable into a temp dir on their own and invoking it from cmd.exe, patching the source and rebuilding the DLL, copying the new DLL into the temp dir and rerunning the testcase to see "0 sec, 1 nanos". Didn't do a full install though. OK? cheers, DaveK -- (*) - Apart from the fact that it's a period, not a frequency!
Index: winsup/cygwin/times.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/times.cc,v retrieving revision 1.112 diff -p -u -r1.112 times.cc --- winsup/cygwin/times.cc 3 Dec 2011 21:43:27 -0000 1.112 +++ winsup/cygwin/times.cc 12 Dec 2011 08:23:20 -0000 @@ -718,7 +718,7 @@ hires_ns::resolution () return (long long) -1; } - return (LONGLONG) freq; + return (freq <= 1.0) ? 1ll : (LONGLONG) freq; } UINT