[patch,1.7.10] clock_setres returns zero

Dave Korn dave.korn.cygwin@gmail.com
Mon Dec 12 22:58:00 GMT 2011


    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!

-------------- next part --------------
A non-text attachment was scrubbed...
Name: clock_getres_fix.diff
Type: text/x-c
Size: 483 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin-patches/attachments/20111212/6b89c46b/attachment.bin>


More information about the Cygwin-patches mailing list