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>
This commit is contained in:
Corinna Vinschen 2018-11-29 12:56:18 +01:00
parent 09870c6e95
commit 43e8fddfa6
2 changed files with 26 additions and 15 deletions

View File

@ -6,16 +6,17 @@
#include "spinlock.h" #include "spinlock.h"
static LONGLONG static LONGLONG
system_qpc_resolution () system_qpc_tickspersec ()
{ {
LARGE_INTEGER qpf; LARGE_INTEGER qpf;
/* ticks per sec */
QueryPerformanceFrequency (&qpf); QueryPerformanceFrequency (&qpf);
return qpf.QuadPart; return qpf.QuadPart;
} }
static LONGLONG static LONGLONG
system_tickcount_resolution () system_tickcount_period ()
{ {
ULONG coarsest = 0, finest, actual; ULONG coarsest = 0, finest, actual;
@ -26,7 +27,7 @@ system_tickcount_resolution ()
can rely on is the coarsest value. */ can rely on is the coarsest value. */
NtQueryTimerResolution (&coarsest, &finest, &actual); NtQueryTimerResolution (&coarsest, &finest, &actual);
} }
return NS100PERSEC / coarsest; return coarsest;
} }
void void
@ -34,7 +35,7 @@ clk_t::init ()
{ {
spinlock spin (inited, 1); spinlock spin (inited, 1);
if (!spin) if (!spin)
ticks_per_sec = system_tickcount_resolution (); period = system_tickcount_period ();
} }
void void
@ -42,9 +43,12 @@ clk_realtime_t::init ()
{ {
spinlock spin (inited, 1); spinlock spin (inited, 1);
if (!spin) if (!spin)
ticks_per_sec = wincap.has_precise_system_time () {
? system_qpc_resolution () if (wincap.has_precise_system_time ())
: system_tickcount_resolution (); ticks_per_sec = system_qpc_tickspersec ();
else
period = system_tickcount_period ();
}
} }
void void
@ -52,7 +56,7 @@ clk_monotonic_t::init ()
{ {
spinlock spin (inited, 1); spinlock spin (inited, 1);
if (!spin) if (!spin)
ticks_per_sec = system_qpc_resolution (); ticks_per_sec = system_qpc_tickspersec ();
} }
int int
@ -202,16 +206,16 @@ clk_monotonic_coarse_t::now (clockid_t clockid, struct timespec *ts)
} }
else else
{ {
/* Vista-only: GetTickCount64 is biased but it's coarse and /* Vista-only: GetTickCount64 is biased but it's coarse and monotonic. */
monotonic. */ ULONGLONG now;
LONGLONG now;
if (inited <= 0) if (inited <= 0)
init (); init ();
now = GetTickCount64 (); now = GetTickCount64 ();
ts->tv_sec = now / ticks_per_sec; now *= period; /* Normalize to 100ns period */
now %= ticks_per_sec; ts->tv_sec = now / NS100PERSEC;
ts->tv_nsec = (now * NSPERSEC) / ticks_per_sec; now %= NS100PERSEC;
ts->tv_nsec = now * (NSPERSEC/NS100PERSEC);
} }
return 0; return 0;
} }
@ -249,7 +253,10 @@ clk_t::resolution (struct timespec *ts)
if (inited <= 0) if (inited <= 0)
init (); init ();
ts->tv_sec = 0; ts->tv_sec = 0;
if (ticks_per_sec)
ts->tv_nsec = NSPERSEC / 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; static clk_realtime_coarse_t clk_realtime_coarse;

View File

@ -53,7 +53,11 @@ class clk_t
{ {
protected: protected:
LONG inited; 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 ticks_per_sec;
LONGLONG period;
virtual void init (); virtual void init ();
virtual int now (clockid_t, struct timespec *) = 0; virtual int now (clockid_t, struct timespec *) = 0;