aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/sys/win32
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/sys/win32')
-rw-r--r--erts/emulator/sys/win32/erl_win_sys.h10
-rw-r--r--erts/emulator/sys/win32/sys_time.c68
2 files changed, 69 insertions, 9 deletions
diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h
index f04bb6a0e5..febf3b5cca 100644
--- a/erts/emulator/sys/win32/erl_win_sys.h
+++ b/erts/emulator/sys/win32/erl_win_sys.h
@@ -172,11 +172,13 @@ typedef long long Sint64;
# endif
typedef long long ErtsMonotonicTime;
+typedef long long ErtsSysHrTime;
#else
typedef ULONGLONG Uint64;
typedef LONGLONG Sint64;
typedef LONGLONG ErtsMonotonicTime;
+typedef LONGLONG ErtsSysHrTime;
#endif
#define ERTS_MONOTONIC_TIME_MIN (((ErtsMonotonicTime) 1) << 63)
@@ -187,6 +189,7 @@ typedef LONGLONG ErtsMonotonicTime;
struct erts_sys_time_read_only_data__ {
ErtsMonotonicTime (*os_monotonic_time)(void);
+ ErtsSysHrTime (*sys_hrtime)(void);
};
typedef struct {
@@ -201,6 +204,7 @@ typedef struct {
extern ErtsSysTimeData__ erts_sys_time_data__;
ERTS_GLB_INLINE ErtsMonotonicTime erts_os_monotonic_time(void);
+ERTS_GLB_INLINE ErtsSysHrTime erts_sys_hrtime(void);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
@@ -210,6 +214,12 @@ erts_os_monotonic_time(void)
return (*erts_sys_time_data__.r.o.os_monotonic_time)();
}
+ERTS_GLB_INLINE ErtsSysHrTime
+erts_sys_hrtime(void)
+{
+ return (*erts_sys_time_data__.r.o.sys_hrtime)();
+}
+
#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
extern void sys_gettimeofday(SysTimeval *tv);
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;