aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/sys/win32/sys_time.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/sys/win32/sys_time.c')
-rw-r--r--erts/emulator/sys/win32/sys_time.c68
1 files changed, 59 insertions, 9 deletions
diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index 5fa575fa3b..ea180f067f 100644
--- a/erts/emulator/sys/win32/sys_time.c
+++ b/erts/emulator/sys/win32/sys_time.c
@@ -26,6 +26,7 @@
#include "sys.h"
#include "assert.h"
#include "erl_os_monotonic_time_extender.h"
+#include "erl_time.h"
#define LL_LITERAL(X) ERTS_I64_LITERAL(X)
@@ -79,6 +80,7 @@ static int days_in_month[2][13] = {
struct sys_time_internal_state_read_only__ {
ULONGLONG (WINAPI *pGetTickCount64)(void);
BOOL (WINAPI *pQueryPerformanceCounter)(LARGE_INTEGER *);
+ Sint32 pcf;
};
struct sys_time_internal_state_read_mostly__ {
@@ -148,6 +150,42 @@ os_monotonic_time_gtc64(void)
return (ErtsMonotonicTime) ticks << 10;
}
+static ErtsSysHrTime
+sys_hrtime_qpc(void)
+{
+ LARGE_INTEGER pc;
+
+ if (!(*internal_state.r.o.pQueryPerformanceCounter)(&pc))
+ erl_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n");
+
+ ASSERT(pc.QuadPart > 0);
+
+ return (ErtsSysHrTime) erts_time_unit_conversion((Uint64) pc.QuadPart,
+ internal_state.r.o.pcf,
+ (Uint32) 1000*1000*1000);
+}
+
+static ErtsSysHrTime
+sys_hrtime_gtc32(void)
+{
+ ErtsSysHrTime time;
+ Uint32 ticks = (Uint32) GetTickCount();
+ ERTS_CHK_EXTEND_OS_MONOTONIC_TIME(&internal_state.wr.m.os_mtime_xtnd,
+ tick_count);
+ time = (ErtsSysHrTime) ERTS_EXTEND_OS_MONOTONIC_TIME(&internal_state.wr.m.os_mtime_xtnd,
+ ticks);
+ time *= (ErtsSysHrTime) (1000 * 1000);
+ return time;
+}
+
+static ErtsSysHrTime
+sys_hrtime_gtc64(void)
+{
+ ErtsSysHrTime time = (*internal_state.r.o.pGetTickCount64)();
+ time *= (ErtsSysHrTime) (1000*1000);
+ return time;
+}
+
/*
* Init
*/
@@ -156,6 +194,7 @@ void
sys_init_time(ErtsSysInitTimeResult *init_resp)
{
ErtsMonotonicTime (*os_mtime_func)(void);
+ ErtsSysHrTime (*sys_hrtime_func)(void) = NULL;
ErtsMonotonicTime time_unit;
char kernel_dll_name[] = "kernel32";
HMODULE module;
@@ -180,6 +219,8 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
erts_init_os_monotonic_time_extender(&internal_state.wr.m.os_mtime_xtnd,
get_tick_count,
60*60*24*7); /* Check once a week */
+ if (!sys_hrtime_func)
+ sys_hrtime_func = sys_hrtime_gtc32;
}
else {
int major, minor, build;
@@ -202,6 +243,8 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
init_resp->os_monotonic_info.resolution = 100; /* 10 ms */
time_unit = (ErtsMonotonicTime) (1000 << 10);
os_mtime_func = os_monotonic_time_gtc64;
+ if (!sys_hrtime_func)
+ sys_hrtime_func = sys_hrtime_gtc64;
}
else { /* Vista or newer... */
@@ -214,21 +257,28 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
goto get_tick_count64;
if (!(*QPF)(&pf))
goto get_tick_count64;
- /*
- * We only use QueryPerformanceCounter() 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;
+
internal_state.r.o.pQueryPerformanceCounter
= ((BOOL (WINAPI *)(LARGE_INTEGER *))
GetProcAddress(module, "QueryPerformanceCounter"));
if (!internal_state.r.o.pQueryPerformanceCounter)
goto get_tick_count64;
+ if (pf.QuadPart < (((LONGLONG) 1) << 32)) {
+ 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;
+
init_resp->os_monotonic_info.func = "QueryPerformanceCounter";
init_resp->os_monotonic_info.locked_use = 0;
time_unit = (ErtsMonotonicTime) pf.QuadPart;