[newlib-cygwin] Cygwin: clocks: use either tickcount or tick period

Corinna Vinschen corinna@sourceware.org
Thu Nov 29 12:04:00 GMT 2018


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=43e8fddfa654365f96ffa87825a99ccc63cfa0db

commit 43e8fddfa654365f96ffa87825a99ccc63cfa0db
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Thu Nov 29 12:56:18 2018 +0100

    Cygwin: clocks: use either tickcount or tick period
    
    Use whatever native unit the system provides for the resolution of
    a timer to avoid rounding problems
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/clock.cc | 37 ++++++++++++++++++++++---------------
 winsup/cygwin/clock.h  |  4 ++++
 2 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/winsup/cygwin/clock.cc b/winsup/cygwin/clock.cc
index 99d0a28..0c8390a 100644
--- a/winsup/cygwin/clock.cc
+++ b/winsup/cygwin/clock.cc
@@ -6,16 +6,17 @@
 #include "spinlock.h"
 
 static LONGLONG
-system_qpc_resolution ()
+system_qpc_tickspersec ()
 {
   LARGE_INTEGER qpf;
 
+  /* ticks per sec */
   QueryPerformanceFrequency (&qpf);
   return qpf.QuadPart;
 }
 
 static LONGLONG
-system_tickcount_resolution ()
+system_tickcount_period ()
 {
   ULONG coarsest = 0, finest, actual;
 
@@ -26,7 +27,7 @@ system_tickcount_resolution ()
        can rely on is the coarsest value. */
       NtQueryTimerResolution (&coarsest, &finest, &actual);
     }
-  return NS100PERSEC / coarsest;
+  return coarsest;
 }
 
 void
@@ -34,7 +35,7 @@ clk_t::init ()
 {
   spinlock spin (inited, 1);
   if (!spin)
-    ticks_per_sec = system_tickcount_resolution ();
+    period = system_tickcount_period ();
 }
 
 void
@@ -42,9 +43,12 @@ clk_realtime_t::init ()
 {
   spinlock spin (inited, 1);
   if (!spin)
-    ticks_per_sec = wincap.has_precise_system_time ()
-		    ? system_qpc_resolution ()
-		    : system_tickcount_resolution ();
+    {
+      if (wincap.has_precise_system_time ())
+	ticks_per_sec = system_qpc_tickspersec ();
+      else
+	period = system_tickcount_period ();
+    }
 }
 
 void
@@ -52,7 +56,7 @@ clk_monotonic_t::init ()
 {
   spinlock spin (inited, 1);
   if (!spin)
-    ticks_per_sec = system_qpc_resolution ();
+    ticks_per_sec = system_qpc_tickspersec ();
 }
 
 int
@@ -202,16 +206,16 @@ clk_monotonic_coarse_t::now (clockid_t clockid, struct timespec *ts)
     }
   else
     {
-      /* Vista-only: GetTickCount64 is biased but it's coarse and
-         monotonic. */
-      LONGLONG now;
+      /* Vista-only: GetTickCount64 is biased but it's coarse and monotonic. */
+      ULONGLONG now;
 
       if (inited <= 0)
 	init ();
       now = GetTickCount64 ();
-      ts->tv_sec = now / ticks_per_sec;
-      now %= ticks_per_sec;
-      ts->tv_nsec = (now * NSPERSEC) / ticks_per_sec;
+      now *= period;	/* Normalize to 100ns period */
+      ts->tv_sec = now / NS100PERSEC;
+      now %= NS100PERSEC;
+      ts->tv_nsec = now * (NSPERSEC/NS100PERSEC);
     }
   return 0;
 }
@@ -249,7 +253,10 @@ clk_t::resolution (struct timespec *ts)
   if (inited <= 0)
     init ();
   ts->tv_sec = 0;
-  ts->tv_nsec = NSPERSEC / ticks_per_sec;
+  if (ticks_per_sec)
+    ts->tv_nsec = NSPERSEC / ticks_per_sec;
+  else
+    ts->tv_nsec = period * (NSPERSEC/NS100PERSEC);
 }
 
 static clk_realtime_coarse_t clk_realtime_coarse;
diff --git a/winsup/cygwin/clock.h b/winsup/cygwin/clock.h
index 3c5bd5f..075aaed 100644
--- a/winsup/cygwin/clock.h
+++ b/winsup/cygwin/clock.h
@@ -53,7 +53,11 @@ class clk_t
 {
  protected:
   LONG inited;
+  /* Some values are returned as ticks/s, some as 100ns period of a
+     single tick.  Store the original value and use a computation method
+     making the most sense for the value given, to avoid rounding issues. */
   LONGLONG ticks_per_sec;
+  LONGLONG period;
   virtual void init ();
   virtual int now (clockid_t, struct timespec *) = 0;



More information about the Cygwin-cvs mailing list