File 8202-erts-Add-info-about-used-resolution-for-OS-monotonic.patch of Package erlang

From 0a1f990d8f9fc1ed948f938e3f9302bcb6c8e63e Mon Sep 17 00:00:00 2001
From: Rickard Green <rickard@erlang.org>
Date: Fri, 5 Apr 2024 16:48:54 +0200
Subject: [PATCH 2/2] [erts] Add info about used resolution for OS monotonic
 time

---
 erts/doc/src/erlang.xml            | 12 ++++++++++++
 erts/emulator/beam/erl_time_sup.c  | 13 +++++++++++--
 erts/emulator/beam/sys.h           |  1 +
 erts/emulator/sys/win32/sys_time.c | 15 +++++++++++----
 4 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index a5e4a3b331..51b4c4438e 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -10247,6 +10247,18 @@ Metadata = #{ pid => pid(),
                 however, know that the precision is not better than
                 <c>OsMonotonicTimeResolution</c>.</p>
               </item>
+              <tag><c>{used_resolution, UsedOsMonotonicTimeResolution}</c></tag>
+              <item><p>
+                The OS monotonic time resolution used by the runtime system.
+                This is very often the same as <c>OsMonotonicTimeResolution</c>.
+                However, on some systems the resolution has to be reduced in
+                order to reliably produce monotonic timestamps. An example of
+                this is when <c>QueryPerformanceCounter()</c> is used as
+                OS monotonic time source on Windows. If such a reduction of
+                the resolution has been done,
+                <c>UsedOsMonotonicTimeResolution</c> will be smaller than
+                <c>OsMonotonicTimeResolution</c>.
+              </p></item>
               <tag><c>{extended, Extended}</c></tag>
               <item><p><c>Extended</c> equals <c>yes</c> if
                 the range of time values has been extended;
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index 0e1d4b087f..abb945ebd2 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -93,6 +93,7 @@ struct time_sup_read_only__ {
     char *os_monotonic_time_clock_id;
     int os_monotonic_time_locked;
     Uint64 os_monotonic_time_resolution;
+    Uint64 os_monotonic_time_used_resolution;
     Uint64 os_monotonic_time_extended;
 #endif
     char *os_system_time_func;
@@ -934,6 +935,10 @@ void erts_init_sys_time_sup(void)
 	= sys_init_time_res.os_monotonic_time_info.locked_use;
     time_sup.r.o.os_monotonic_time_resolution
 	= sys_init_time_res.os_monotonic_time_info.resolution;
+    time_sup.r.o.os_monotonic_time_used_resolution
+	= (!sys_init_time_res.os_monotonic_time_info.used_resolution
+           ? sys_init_time_res.os_monotonic_time_info.resolution
+           : sys_init_time_res.os_monotonic_time_info.used_resolution);
     time_sup.r.o.os_monotonic_time_extended
 	= sys_init_time_res.os_monotonic_time_info.extended;
 #endif
@@ -2044,8 +2049,8 @@ bld_monotonic_time_source(Uint **hpp, Uint *szp, Sint64 os_mtime)
     return NIL;
 #else
     int i = 0;
-    Eterm k[6];
-    Eterm v[6];
+    Eterm k[7];
+    Eterm v[7];
 
     if (time_sup.r.o.os_monotonic_time_disable)
 	return NIL;
@@ -2064,6 +2069,10 @@ bld_monotonic_time_source(Uint **hpp, Uint *szp, Sint64 os_mtime)
     v[i++] = erts_bld_uint64(hpp, szp,
 			     time_sup.r.o.os_monotonic_time_resolution);
 
+    k[i] = erts_bld_atom(hpp, szp, "used_resolution");
+    v[i++] = erts_bld_uint64(hpp, szp,
+                             time_sup.r.o.os_monotonic_time_used_resolution);
+
     k[i] = erts_bld_atom(hpp, szp, "extended");
     v[i++] = time_sup.r.o.os_monotonic_time_extended ? am_yes : am_no;
 
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 1ffc7f5028..6a5908d51b 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -727,6 +727,7 @@ typedef struct {
     ErtsMonotonicTime sys_clock_resolution;
     struct {
 	Uint64 resolution;
+        Uint64 used_resolution;
 	char *func;
 	char *clock_id;
 	int locked_use;
diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index 1febfee829..81e621eb2e 100644
--- a/erts/emulator/sys/win32/sys_time.c
+++ b/erts/emulator/sys/win32/sys_time.c
@@ -29,8 +29,12 @@
 #include "erl_os_monotonic_time_extender.h"
 #include "erl_time.h"
 
-/* Need to look more closely at qpc before use... */
-#define ERTS_DISABLE_USE_OF_QPC_FOR_MONOTONIC_TIME 1
+/*
+ * How much to reduce the resolution of the by QueryPerformanceCounter()
+ * returned values in order to make them monotonic...
+ */
+#define ERTS_WIN_QPC_SKIP_BITS 10
+#define ERTS_WIN_QPC_SKIP_MASK ((1 << ERTS_WIN_QPC_SKIP_BITS) - 1)
 
 #define LL_LITERAL(X) ERTS_I64_LITERAL(X)
 
@@ -159,9 +163,9 @@ os_monotonic_time_qpc(void)
         if (!(*internal_state.r.o.pQueryPerformanceCounter)(&pc))
             erts_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n");
         temp = (ErtsMonotonicTime) pc.QuadPart;
-    } while(!(temp & SKIP));
+    } while(!(temp & ERTS_WIN_QPC_SKIP_MASK));
 
-    return temp & (ERTS_I64_LITERAL(0xFFFFFFFFFFFFFFFF)-SKIP);
+    return temp & (ERTS_I64_LITERAL(0xFFFFFFFFFFFFFFFF)-ERTS_WIN_QPC_SKIP_MASK);
 }
 
 static void
@@ -381,6 +385,9 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
 	    time_unit = (ErtsMonotonicTime) pf.QuadPart;
 	    internal_state.r.o.using_get_tick_count_time_unit = 0;
 	    init_resp->os_monotonic_time_info.resolution = time_unit;
+            /* We reduce the used resolution in order to make it monotonic... */
+	    init_resp->os_monotonic_time_info.used_resolution
+                = time_unit >> ERTS_WIN_QPC_SKIP_BITS;
 	    os_mtime_func = os_monotonic_time_qpc;
 	    os_times_func = os_times_qpc;
 	}
-- 
2.35.3

openSUSE Build Service is sponsored by