File 2481-win32-Use-QPC-timer-on-Windows.patch of Package erlang

From cd9c87d64dec190639c459de4added891ef330d4 Mon Sep 17 00:00:00 2001
From: Dan Gudmundsson <dgud@erlang.org>
Date: Tue, 4 Aug 2020 14:55:06 +0200
Subject: [PATCH 1/2] win32: Use QPC timer on Windows

If resolution is good enough use QueryPerformanceTimer on windows,
which with thread compensation gives an ~0.1ms resolution instead of 15ms.

The cost is ~30% higher for qpc than for GetTickCound64
and the thread compensation cost adds another 0.5% amortized cost.
---
 erts/emulator/sys/win32/sys_time.c | 31 ++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index a1dd14f871..a14b9dd2c0 100644
--- a/erts/emulator/sys/win32/sys_time.c
+++ b/erts/emulator/sys/win32/sys_time.c
@@ -141,15 +141,27 @@ SystemTime2MilliSec(SYSTEMTIME *stp)
     return stime;
 }
 
+#define SKIP 0x3FF
+
 static ErtsMonotonicTime
 os_monotonic_time_qpc(void)
 {
     LARGE_INTEGER pc;
 
-    if (!(*internal_state.r.o.pQueryPerformanceCounter)(&pc))
-	erts_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n");
+    ErtsMonotonicTime temp;
 
-    return (ErtsMonotonicTime) pc.QuadPart;
+    /*
+     * Windows QPC does not ensure that the returned clocks
+     * are monotonic over several threads, reduce resolution to ensure
+     * that we return monotonic clocks even on multiple threads.
+     */
+    do {
+        if (!(*internal_state.r.o.pQueryPerformanceCounter)(&pc))
+            erts_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n");
+        temp = (ErtsMonotonicTime) pc.QuadPart;
+    } while(!(temp & SKIP));
+
+    return temp & (0xFFFFFFFFFFFFFFFF-SKIP);
 }
 
 static void
@@ -365,18 +377,9 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
 
 	    internal_state.r.o.pcf = (Uint32) pf.QuadPart;
 	    sys_hrtime_func = sys_hrtime_qpc;
-	    
-	    /*
-	     * We only use QueryPerformanceCounter() for
-	     * os-monotonic-time if its frequency is equal
-	     * to, or larger than GHz in order to ensure
-	     * that the user wont be able to observe faulty
-	     * order between values retrieved on different threads.
-	     */
-	    if (pf.QuadPart < (LONGLONG) 1000*1000*1000)
-		goto get_tick_count64;
 
-	    if (ERTS_DISABLE_USE_OF_QPC_FOR_MONOTONIC_TIME)
+            /* We need at least 0.1 microseconds resolution */
+	    if (pf.QuadPart < (LONGLONG) 9*1000*1000)
 		goto get_tick_count64;
 
 	    init_resp->os_monotonic_time_info.func = "QueryPerformanceCounter";
-- 
2.26.2

openSUSE Build Service is sponsored by