Skip to content

Commit

Permalink
Merge branch 'rickard/win-os-monotonic/OTP-19048' into maint
Browse files Browse the repository at this point in the history
* rickard/win-os-monotonic/OTP-19048:
  [erts] Add info about used resolution for OS monotonic time
  [erts] Fix retrieval of OS monotonic time on Windows
  • Loading branch information
rickard-green committed Apr 8, 2024
2 parents f57cdc6 + 0a1f990 commit e39a535
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 15 deletions.
12 changes: 12 additions & 0 deletions erts/doc/src/erlang.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10720,6 +10720,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;
Expand Down
13 changes: 11 additions & 2 deletions erts/emulator/beam/erl_time_sup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -943,6 +944,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
Expand Down Expand Up @@ -2058,8 +2063,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;
Expand All @@ -2078,6 +2083,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;

Expand Down
1 change: 1 addition & 0 deletions erts/emulator/beam/sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ typedef struct {
ErtsMonotonicTime sys_clock_resolution;
struct {
Uint64 resolution;
Uint64 used_resolution;
char *func;
char *clock_id;
int locked_use;
Expand Down
27 changes: 14 additions & 13 deletions erts/emulator/sys/win32/sys_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -86,7 +90,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;
Uint32 pcf;
int using_get_tick_count_time_unit;
};

Expand Down Expand Up @@ -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
Expand All @@ -170,16 +174,10 @@ os_times_qpc(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep)
LARGE_INTEGER pc;
SYSTEMTIME st;
ErtsSystemTime stime;
BOOL qpcr;

qpcr = (*internal_state.r.o.pQueryPerformanceCounter)(&pc);
*mtimep = os_monotonic_time_qpc();
GetSystemTime(&st);

if (!qpcr)
erts_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n");

*mtimep = (ErtsMonotonicTime) pc.QuadPart;

stime = SystemTime2MilliSec(&st);

*stimep = ((ErtsSystemTime)
Expand Down Expand Up @@ -372,7 +370,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
if (!internal_state.r.o.pQueryPerformanceCounter)
goto get_tick_count64;

if (pf.QuadPart > (((LONGLONG) 1) << 32))
if (pf.QuadPart >= (((LONGLONG) 1) << 32))
goto get_tick_count64;

internal_state.r.o.pcf = (Uint32) pf.QuadPart;
Expand All @@ -387,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;
}
Expand Down

0 comments on commit e39a535

Please sign in to comment.