From 5eaa64f9d86cae422016c3b08476b1cea556628e Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 26 Nov 2018 17:47:53 +0100 Subject: [PATCH] Cygwin: timers: use spinlock to prime hires_ns thread-safe The current method to make hires_ns priming thread-safe isn't thread-safe. Rather than hoping that running the thread in TIME_CRITICAL priority is doing the right thing, use a spinlock. Signed-off-by: Corinna Vinschen --- winsup/cygwin/hires.h | 2 +- winsup/cygwin/times.cc | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/winsup/cygwin/hires.h b/winsup/cygwin/hires.h index d07bf394d..10aed7baf 100644 --- a/winsup/cygwin/hires.h +++ b/winsup/cygwin/hires.h @@ -40,7 +40,7 @@ details. */ class hires_ns { - int inited; + LONG inited; LARGE_INTEGER primed_pc; double freq; void prime (); diff --git a/winsup/cygwin/times.cc b/winsup/cygwin/times.cc index 1ead18efc..4e405b2df 100644 --- a/winsup/cygwin/times.cc +++ b/winsup/cygwin/times.cc @@ -24,6 +24,7 @@ details. */ #include "thread.h" #include "cygtls.h" #include "ntdll.h" +#include "spinlock.h" hires_ms NO_COPY gtod; @@ -465,19 +466,16 @@ ftime (struct timeb *tp) void hires_ns::prime () { - LARGE_INTEGER ifreq; + spinlock hspin (inited, 1); + if (!hspin) + { + LARGE_INTEGER ifreq; - /* On XP or later the perf counter functions will always succeed. */ - QueryPerformanceFrequency (&ifreq); - - int priority = GetThreadPriority (GetCurrentThread ()); - - SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL); - QueryPerformanceCounter (&primed_pc); - - freq = (double) ((double) NSPERSEC / (double) ifreq.QuadPart); - inited = true; - SetThreadPriority (GetCurrentThread (), priority); + /* On XP or later the perf counter functions will always succeed. */ + QueryPerformanceFrequency (&ifreq); + freq = (double) ((double) NSPERSEC / (double) ifreq.QuadPart); + QueryPerformanceCounter (&primed_pc); + } } LONGLONG @@ -485,7 +483,7 @@ hires_ns::nsecs (bool monotonic) { LARGE_INTEGER now; - if (!inited) + if (inited <= 0) prime (); QueryPerformanceCounter (&now); // FIXME: Use round() here? @@ -627,7 +625,7 @@ static ULONG minperiod; // FIXME: Maintain period after a fork. LONGLONG hires_ns::resolution () { - if (!inited) + if (inited <= 0) prime (); return (freq <= 1.0) ? 1LL : (LONGLONG) freq; }