From c20482023b70768bd84d25f1e34dbbc2fe09cf31 Mon Sep 17 00:00:00 2001
From: Rickard Green
Date: Tue, 24 Mar 2015 15:28:11 +0100
Subject: Better OS system time implementation
---
erts/aclocal.m4 | 95 ++++++++++++++-
erts/doc/src/erlang.xml | 55 +++++++++
erts/doc/src/time_correction.xml | 14 ++-
erts/emulator/beam/erl_bif_info.c | 2 +
erts/emulator/beam/erl_time.h | 1 +
erts/emulator/beam/erl_time_sup.c | 214 +++++++++++++++++++---------------
erts/emulator/beam/sys.h | 10 +-
erts/emulator/sys/unix/erl_unix_sys.h | 4 +
erts/emulator/sys/unix/sys_time.c | 167 +++++++++++++++++++++++---
erts/emulator/sys/win32/erl_win_sys.h | 4 +
erts/emulator/sys/win32/sys_time.c | 73 +++++++++---
erts/example/time_compat.erl | 1 +
erts/preloaded/ebin/erlang.beam | Bin 105832 -> 105852 bytes
erts/preloaded/src/erlang.erl | 1 +
14 files changed, 507 insertions(+), 134 deletions(-)
(limited to 'erts')
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4
index 6ba54e823e..7a969547cf 100644
--- a/erts/aclocal.m4
+++ b/erts/aclocal.m4
@@ -747,7 +747,7 @@ AC_DEFUN(ERL_MONOTONIC_CLOCK,
AC_CHECK_FUNCS([clock_getres gethrtime])
- AC_CACHE_CHECK([for mach clock_get_time()], erl_cv_mach_clock_get_time,
+ AC_CACHE_CHECK([for mach clock_get_time()], erl_cv_mach_clock_get_time_monotonic,
[
AC_TRY_COMPILE([
#include
@@ -762,13 +762,13 @@ AC_DEFUN(ERL_MONOTONIC_CLOCK,
res = clock_get_time(clk_srv, &time_spec);
mach_port_deallocate(mach_task_self(), clk_srv);
],
- erl_cv_mach_clock_get_time=yes,
- erl_cv_mach_clock_get_time=no)
+ erl_cv_mach_clock_get_time_monotonic=yes,
+ erl_cv_mach_clock_get_time_monotonic=no)
])
- case $erl_cv_clock_gettime_monotonic-$ac_cv_func_gethrtime-$erl_cv_mach_clock_get_time-$host_os in
+ case $erl_cv_clock_gettime_monotonic-$ac_cv_func_gethrtime-$erl_cv_mach_clock_get_time_monotonic-$host_os in
*-*-*-win32)
- erl_monotonic_clock_func=GetTickCount
+ erl_monotonic_clock_func=WindowsAPI
;;
CLOCK_*-*-*-linux*)
if test X$cross_compiling != Xyes; then
@@ -833,6 +833,70 @@ AC_DEFUN(ERL_MONOTONIC_CLOCK,
])
+AC_DEFUN(ERL_WALL_CLOCK,
+[
+ AC_CACHE_CHECK([for clock_gettime() with wall clock type], erl_cv_clock_gettime_wall,
+ [
+ for clock_type in CLOCK_REALTIME; do
+ AC_TRY_COMPILE([
+#include
+ ],
+ [
+ struct timespec ts;
+ long long result;
+ clock_gettime($clock_type,&ts);
+ result = ((long long) ts.tv_sec) * 1000000000LL +
+ ((long long) ts.tv_nsec);
+ ],
+ erl_cv_clock_gettime_wall=$clock_type,
+ erl_cv_clock_gettime_wall=no)
+ test $erl_cv_clock_gettime_wall = no || break
+ done
+ ])
+
+ AC_CHECK_FUNCS([clock_getres gettimeofday])
+
+ AC_CACHE_CHECK([for mach clock_get_time()], erl_cv_mach_clock_get_time_wall,
+ [
+ AC_TRY_COMPILE([
+#include
+#include
+ ],
+ [
+ kern_return_t res;
+ clock_serv_t clk_srv;
+ mach_timespec_t time_spec;
+
+ host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clk_srv);
+ res = clock_get_time(clk_srv, &time_spec);
+ mach_port_deallocate(mach_task_self(), clk_srv);
+ ],
+ erl_cv_mach_clock_get_time_wall=yes,
+ erl_cv_mach_clock_get_time_wall=no)
+ ])
+
+ erl_wall_clock_id=
+ case $erl_cv_clock_gettime_wall-$erl_cv_mach_clock_get_time_wall-$ac_cv_func_gettimeofday-$host_os in
+ *-*-*-win32)
+ erl_wall_clock_func=WindowsAPI
+ ;;
+ no-yes-*-*)
+ erl_wall_clock_func=mach_clock_get_time
+ erl_wall_clock_id=CALENDAR_CLOCK
+ ;;
+ CLOCK_*-*-*-*)
+ erl_wall_clock_func=clock_gettime
+ erl_wall_clock_id=$erl_cv_clock_gettime_wall
+ ;;
+ no-no-yes-*)
+ erl_wall_clock_func=gettimeofday
+ ;;
+ *)
+ erl_wall_clock_func=none
+ ;;
+ esac
+])
+
dnl ----------------------------------------------------------------------
dnl
dnl LM_CHECK_THR_LIB
@@ -1850,6 +1914,27 @@ dnl
AC_DEFUN(ERL_TIME_CORRECTION,
[
+ERL_WALL_CLOCK
+
+case $erl_wall_clock_func in
+ mach_clock_get_time)
+ AC_DEFINE(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME, [1], [Define if you want to implement erts_os_system_time() using mach clock_get_time()])
+ ;;
+ clock_gettime)
+ AC_DEFINE(OS_SYSTEM_TIME_USING_CLOCK_GETTIME, [1], [Define if you want to implement erts_os_system_time() using clock_gettime()])
+ ;;
+ gettimeofday)
+ AC_DEFINE(OS_SYSTEM_TIME_GETTIMEOFDAY, [1], [Define if you want to implement erts_os_system_time() using gettimeofday()])
+ ;;
+ *)
+ ;;
+esac
+
+if test "x$erl_wall_clock_id" != "x"; then
+ AC_DEFINE_UNQUOTED(WALL_CLOCK_ID_STR, ["$erl_wall_clock_id"], [Define as a string of wall clock id to use])
+ AC_DEFINE_UNQUOTED(WALL_CLOCK_ID, [$erl_wall_clock_id], [Define to wall clock id to use])
+fi
+
ERL_MONOTONIC_CLOCK
case $erl_monotonic_clock_func in
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 7cb417ac92..bd5efb712c 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -6031,6 +6031,8 @@ ok
+
+
Information about the system
Returns various information about the current system
@@ -6482,6 +6484,59 @@ ok
time unit.
+ os_system_time_source
+ -
+
Returns a list containing information about the source of
+ OS
+ system time that is used by the runtime system.
+ The list contains two-tuples with Keys
+ as first element, and Values as second element. The
+ order if these tuples is undefined. Currently the following
+ tuples may be part of the list, but more tuples may be
+ introduced in the future:
+
+ {function, Function}
+ Function is the name of the funcion
+ used.
+
+ {clock_id, ClockId}
+ This tuple only exist if Function
+ can be used with different clocks. ClockId
+ corresponds to the clock identifer used when calling
+ Function.
+
+ {resolution, OsSystemTimeResolution}
+ Highest possible
+ resolution
+ of current OS system time source as parts per
+ second. If no resolution information can be retreived
+ from the OS, OsSystemTimeResolution will be
+ set to the resolution of the time unit of
+ Functions return value. That is, the actual
+ resolution may be lower than
+ OsSystemTimeResolution. Also note that
+ the resolution does not say anything about the
+ accuracy,
+ and that the
+ precision
+ might not align with the resolution. You do,
+ however, know that the precision won't be
+ better than
+ OsSystemTimeResolution.
+
+ {parallel, Parallel}
+ Parallel equals yes if
+ Function is called in parallel from multiple
+ threads. If it is not called in parallel, because
+ calls needs to be serialized, Parallel equals
+ no.
+
+ {time, OsSystemTime}
+ OsSystemTime equals current OS
+ system time in native
+ time unit.
+
+
port_parallelism
Returns the default port parallelism scheduling hint used.
For more information see the
diff --git a/erts/doc/src/time_correction.xml b/erts/doc/src/time_correction.xml
index ed658ff58c..979a37d7ff 100644
--- a/erts/doc/src/time_correction.xml
+++ b/erts/doc/src/time_correction.xml
@@ -147,7 +147,9 @@
This may or may not be an accurate view of POSIX time. This time
may typically be adjusted both backwards and forwards without
limitation. That is, huge leaps both backwards and forwards in time
- may be observed.
+ may be observed. You can get information about the Erlang runtime
+ system's source of OS system time by calling
+ erlang:system_info(os_system_time_source).
@@ -161,7 +163,9 @@
point in time that is not connected to
OS system time. Note that
this type of time is not necessarily provided by all operating
- systems.
+ systems. You can get information about the Erlang runtime
+ system's source of OS monotonic time by calling
+ erlang:system_info(os_monotonic_time_source).
@@ -597,6 +601,7 @@
erlang:monitor(time_offset, clock_service)
erlang:system_flag(time_offset, finalize)
erlang:system_info(os_monotonic_time_source)
+ erlang:system_info(os_system_time_source)
erlang:system_info(time_offset)
erlang:system_info(time_warp_mode)
erlang:system_info(time_correction)
@@ -852,8 +857,9 @@ EventTag = {Time, UMI}
when it is not available. Fortunately almost all of the new
API can easily be implemented using existing primitives
(except for
- erlang:system_info(start_time), and
- erlang:system_info(os_monotonic_time_source)).
+ erlang:system_info(start_time),
+ erlang:system_info(os_monotonic_time_source), and
+ erlang:system_info(os_system_time_source)).
By wrapping the API with functions that fall back on
erlang:now/0 when the new API is not available,
and using these wrappers instead of using the API directly
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 70062b2305..8491c01b75 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -2120,6 +2120,8 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
}
} else if (ERTS_IS_ATOM_STR("os_monotonic_time_source", BIF_ARG_1)) {
BIF_RET(erts_monotonic_time_source(BIF_P));
+ } else if (ERTS_IS_ATOM_STR("os_system_time_source", BIF_ARG_1)) {
+ BIF_RET(erts_system_time_source(BIF_P));
} else if (ERTS_IS_ATOM_STR("time_correction", BIF_ARG_1)) {
BIF_RET(erts_has_time_correction() ? am_true : am_false);
} else if (ERTS_IS_ATOM_STR("start_time", BIF_ARG_1)) {
diff --git a/erts/emulator/beam/erl_time.h b/erts/emulator/beam/erl_time.h
index 35a1442dbd..7f8c4e0ed5 100644
--- a/erts/emulator/beam/erl_time.h
+++ b/erts/emulator/beam/erl_time.h
@@ -148,6 +148,7 @@ ErtsTimeOffsetState erts_finalize_time_offset(void);
struct process;
Eterm erts_get_monotonic_start_time(struct process *c_p);
Eterm erts_monotonic_time_source(struct process*c_p);
+Eterm erts_system_time_source(struct process*c_p);
#ifdef SYS_CLOCK_RESOLUTION
#define ERTS_CLKTCK_RESOLUTION ((ErtsMonotonicTime) (SYS_CLOCK_RESOLUTION*1000))
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index d961fae81a..ef39f4b5f4 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -133,12 +133,17 @@ struct time_sup_read_only__ {
ErtsTimeWarpMode warp_mode;
#ifdef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
ErtsMonotonicTime moffset;
- int os_monotonic_disable;
- char *os_monotonic_func;
- char *os_monotonic_clock_id;
- int os_monotonic_locked;
- Uint64 os_monotonic_resolution;
- Uint64 os_monotonic_extended;
+ int os_monotonic_time_disable;
+ char *os_monotonic_time_func;
+ char *os_monotonic_time_clock_id;
+ int os_monotonic_time_locked;
+ Uint64 os_monotonic_time_resolution;
+ Uint64 os_monotonic_time_extended;
+ char *os_system_time_func;
+ char *os_system_time_clock_id;
+ int os_system_time_locked;
+ Uint64 os_system_time_resolution;
+ Uint64 os_system_time_extended;
#endif
#if !ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT
ErtsMonotonicTime start;
@@ -209,7 +214,7 @@ struct time_sup_infrequently_changed__ {
ErtsMonotonicTime minit;
#endif
int finalized_offset;
- SysTimeval inittv; /* Used everywhere, the initial time-of-day */
+ ErtsSystemTime sinit;
ErtsMonotonicTime not_corrected_moffset;
erts_atomic64_t offset;
};
@@ -242,10 +247,8 @@ ErtsTimeSupData erts_time_sup__ erts_align_attribute(ERTS_CACHE_LINE_SIZE);
erts_approx_time_t
erts_get_approx_time(void)
{
- SysTimeval tv;
- sys_gettimeofday(&tv);
-
- return (erts_approx_time_t) tv.tv_sec;
+ ErtsSystemTime stime = erts_os_system_time();
+ return (erts_approx_time_t) ERTS_MONOTONIC_TO_SEC(stime);
}
static ERTS_INLINE void
@@ -403,7 +406,6 @@ check_time_correction(void *unused)
ErtsMonotonicTime mdiff, sdiff, os_mtime, erl_mtime, os_stime,
erl_stime, time_offset;
Uint timeout;
- SysTimeval tod;
int set_new_correction, begin_short_intervals = 0;
erts_smp_rwmtx_rlock(&time_sup.inf.c.parmon.rwmtx);
@@ -411,7 +413,7 @@ check_time_correction(void *unused)
ASSERT(time_sup.inf.c.finalized_offset);
os_mtime = erts_os_monotonic_time();
- sys_gettimeofday(&tod);
+ os_stime = erts_os_system_time();
cdata = time_sup.inf.c.parmon.cdata;
@@ -426,9 +428,6 @@ check_time_correction(void *unused)
time_offset = get_time_offset();
erl_stime = erl_mtime + time_offset;
- os_stime = ERTS_SEC_TO_MONOTONIC(tod.tv_sec);
- os_stime += ERTS_USEC_TO_MONOTONIC(tod.tv_usec);
-
sdiff = erl_stime - os_stime;
new_correction = cip->correction;
@@ -686,7 +685,6 @@ init_check_time_correction(void *unused)
ErtsMonotonicTime old_mtime, old_stime, mtime, stime, mtime_diff,
stime_diff;
int ix;
- SysTimeval tod;
ddp = &time_sup.inf.c.parmon.cdata.drift;
ix = ddp->ix;
@@ -694,10 +692,7 @@ init_check_time_correction(void *unused)
old_stime = ddp->intervals[0].time.sys;
mtime = erts_os_monotonic_time();
- sys_gettimeofday(&tod);
-
- stime = ERTS_SEC_TO_MONOTONIC(tod.tv_sec);
- stime += ERTS_USEC_TO_MONOTONIC(tod.tv_usec);
+ stime = erts_os_system_time();
mtime_diff = mtime - old_mtime;
stime_diff = stime - old_stime;
@@ -729,7 +724,7 @@ init_check_time_correction(void *unused)
#endif
static ErtsMonotonicTime
-finalize_corrected_time_offset(SysTimeval *todp)
+finalize_corrected_time_offset(ErtsSystemTime *stimep)
{
ErtsMonotonicTime os_mtime;
ErtsMonotonicCorrectionData cdata;
@@ -738,7 +733,7 @@ finalize_corrected_time_offset(SysTimeval *todp)
erts_smp_rwmtx_rlock(&time_sup.inf.c.parmon.rwmtx);
os_mtime = erts_os_monotonic_time();
- sys_gettimeofday(todp);
+ *stimep = erts_os_system_time();
cdata = time_sup.inf.c.parmon.cdata;
@@ -774,15 +769,11 @@ late_init_time_correction(void)
static ErtsMonotonicTime get_not_corrected_time(void)
{
- SysTimeval tmp_tv;
ErtsMonotonicTime stime, mtime;
erts_smp_mtx_lock(&erts_get_time_mtx);
- sys_gettimeofday(&tmp_tv);
-
- stime = ERTS_SEC_TO_MONOTONIC(tmp_tv.tv_sec);
- stime += ERTS_USEC_TO_MONOTONIC(tmp_tv.tv_usec);
+ stime = erts_os_system_time();
mtime = stime - time_sup.inf.c.not_corrected_moffset;
@@ -820,7 +811,7 @@ int erts_check_time_adj_support(int time_correction,
/* User wants time correction */
#ifdef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
- return !time_sup.r.o.os_monotonic_disable;
+ return !time_sup.r.o.os_monotonic_time_disable;
#else
return 0;
#endif
@@ -849,24 +840,33 @@ void erts_init_sys_time_sup(void)
#endif
#ifdef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
- time_sup.r.o.os_monotonic_disable
- = !sys_init_time_res.have_os_monotonic;
- time_sup.r.o.os_monotonic_func
- = sys_init_time_res.os_monotonic_info.func;
- time_sup.r.o.os_monotonic_clock_id
- = sys_init_time_res.os_monotonic_info.clock_id;
- time_sup.r.o.os_monotonic_locked
- = sys_init_time_res.os_monotonic_info.locked_use;
- time_sup.r.o.os_monotonic_resolution
- = sys_init_time_res.os_monotonic_info.resolution;
- time_sup.r.o.os_monotonic_extended
- = sys_init_time_res.os_monotonic_info.extended;
+ time_sup.r.o.os_monotonic_time_disable
+ = !sys_init_time_res.have_os_monotonic_time;
+ time_sup.r.o.os_monotonic_time_func
+ = sys_init_time_res.os_monotonic_time_info.func;
+ time_sup.r.o.os_monotonic_time_clock_id
+ = sys_init_time_res.os_monotonic_time_info.clock_id;
+ time_sup.r.o.os_monotonic_time_locked
+ = 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_extended
+ = sys_init_time_res.os_monotonic_time_info.extended;
+ time_sup.r.o.os_system_time_func
+ = sys_init_time_res.os_system_time_info.func;
+ time_sup.r.o.os_system_time_clock_id
+ = sys_init_time_res.os_system_time_info.clock_id;
+ time_sup.r.o.os_system_time_locked
+ = sys_init_time_res.os_system_time_info.locked_use;
+ time_sup.r.o.os_system_time_resolution
+ = sys_init_time_res.os_system_time_info.resolution;
#endif
}
int
erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
{
+ ErtsMonotonicTime resolution;
#if !ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT
ErtsMonotonicTime abs_native_offset, native_offset;
#endif
@@ -935,11 +935,15 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
#endif
+ resolution = time_sup.r.o.os_monotonic_time_resolution;
+ if (resolution > time_sup.r.o.os_system_time_resolution)
+ resolution = time_sup.r.o.os_system_time_resolution;
+
time_sup.r.o.adj.large_diff = erts_time_sup__.r.o.monotonic_time_unit;
time_sup.r.o.adj.large_diff *= 50;
- time_sup.r.o.adj.large_diff /= time_sup.r.o.os_monotonic_resolution;
- if (time_sup.r.o.adj.large_diff < ERTS_MSEC_TO_MONOTONIC(5))
- time_sup.r.o.adj.large_diff = ERTS_MSEC_TO_MONOTONIC(5);
+ time_sup.r.o.adj.large_diff /= resolution;
+ if (time_sup.r.o.adj.large_diff < ERTS_USEC_TO_MONOTONIC(500))
+ time_sup.r.o.adj.large_diff = ERTS_USEC_TO_MONOTONIC(500);
time_sup.r.o.adj.small_diff = time_sup.r.o.adj.large_diff/10;
#ifdef ERTS_TIME_CORRECTION_PRINT
@@ -961,7 +965,7 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
#ifndef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
time_sup.r.o.correction = 0;
#else
- if (time_sup.r.o.os_monotonic_disable)
+ if (time_sup.r.o.os_monotonic_time_disable)
time_sup.r.o.correction = 0;
if (time_sup.r.o.correction) {
@@ -969,10 +973,9 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
erts_smp_rwmtx_opt_t rwmtx_opts = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
ErtsMonotonicTime offset;
time_sup.inf.c.minit = erts_os_monotonic_time();
- sys_gettimeofday(&time_sup.inf.c.inittv);
+ time_sup.inf.c.sinit = erts_os_system_time();
time_sup.r.o.moffset = -1*time_sup.inf.c.minit;
- offset = ERTS_SEC_TO_MONOTONIC(time_sup.inf.c.inittv.tv_sec);
- offset += ERTS_USEC_TO_MONOTONIC(time_sup.inf.c.inittv.tv_usec);
+ offset = time_sup.inf.c.sinit;
offset -= ERTS_MONOTONIC_TIME_UNIT;
init_time_offset(offset);
@@ -985,10 +988,7 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
cdatap = &time_sup.inf.c.parmon.cdata;
#ifndef ERTS_HAVE_CORRECTED_OS_MONOTONIC
- cdatap->drift.intervals[0].time.sys
- = ERTS_SEC_TO_MONOTONIC(time_sup.inf.c.inittv.tv_sec);
- cdatap->drift.intervals[0].time.sys
- += ERTS_USEC_TO_MONOTONIC(time_sup.inf.c.inittv.tv_usec);
+ cdatap->drift.intervals[0].time.sys = time_sup.inf.c.sinit;
cdatap->drift.intervals[0].time.mon = time_sup.inf.c.minit;
cdatap->curr.correction.drift = 0;
#endif
@@ -1006,9 +1006,7 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
{
ErtsMonotonicTime stime, offset;
time_sup.r.o.get_time = get_not_corrected_time;
- sys_gettimeofday(&time_sup.inf.c.inittv);
- stime = ERTS_SEC_TO_MONOTONIC(time_sup.inf.c.inittv.tv_sec);
- stime += ERTS_USEC_TO_MONOTONIC(time_sup.inf.c.inittv.tv_usec);
+ stime = time_sup.inf.c.sinit = erts_os_system_time();
offset = stime - ERTS_MONOTONIC_TIME_UNIT;
time_sup.inf.c.not_corrected_moffset = offset;
init_time_offset(offset);
@@ -1085,17 +1083,12 @@ erts_finalize_time_offset(void)
if (!time_sup.inf.c.finalized_offset) {
ErtsMonotonicTime mtime, new_offset;
- SysTimeval tv;
#ifdef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
if (!time_sup.r.o.correction)
#endif
{
- ErtsMonotonicTime stime;
- sys_gettimeofday(&tv);
-
- stime = ERTS_SEC_TO_MONOTONIC(tv.tv_sec);
- stime += ERTS_USEC_TO_MONOTONIC(tv.tv_usec);
+ ErtsMonotonicTime stime = erts_os_system_time();
mtime = stime - time_sup.inf.c.not_corrected_moffset;
@@ -1114,11 +1107,9 @@ erts_finalize_time_offset(void)
}
#ifdef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
else {
- mtime = finalize_corrected_time_offset(&tv);
- new_offset = ERTS_SEC_TO_MONOTONIC(tv.tv_sec);
- new_offset += ERTS_USEC_TO_MONOTONIC(tv.tv_usec);
- new_offset -= mtime;
-
+ ErtsSystemTime stime;
+ mtime = finalize_corrected_time_offset(&stime);
+ new_offset = stime - mtime;
}
#endif
new_offset = ERTS_MONOTONIC_TO_USEC(new_offset);
@@ -1613,13 +1604,16 @@ erts_get_monotonic_time(void)
void
get_sys_now(Uint* megasec, Uint* sec, Uint* microsec)
{
- SysTimeval now;
-
- sys_gettimeofday(&now);
-
- *megasec = (Uint) (now.tv_sec / 1000000);
- *sec = (Uint) (now.tv_sec % 1000000);
- *microsec = (Uint) (now.tv_usec);
+ ErtsSystemTime stime = erts_os_system_time();
+ ErtsSystemTime ms, s, us;
+
+ us = ERTS_MONOTONIC_TO_USEC(stime);
+ s = us / (1000*1000);
+ ms = s / (1000*1000);
+
+ *megasec = (Uint) ms;
+ *sec = (Uint) (s - ms*(1000*1000));
+ *microsec = (Uint) (us - s*(1000*1000));
}
#ifdef HAVE_ERTS_NOW_CPU
@@ -1848,25 +1842,28 @@ bld_monotonic_time_source(Uint **hpp, Uint *szp, Sint64 os_mtime)
Eterm k[6];
Eterm v[6];
- if (time_sup.r.o.os_monotonic_disable)
+ if (time_sup.r.o.os_monotonic_time_disable)
return NIL;
k[i] = erts_bld_atom(hpp, szp, "function");
- v[i++] = erts_bld_atom(hpp, szp, time_sup.r.o.os_monotonic_func);
+ v[i++] = erts_bld_atom(hpp, szp,
+ time_sup.r.o.os_monotonic_time_func);
- if (time_sup.r.o.os_monotonic_clock_id) {
+ if (time_sup.r.o.os_monotonic_time_clock_id) {
k[i] = erts_bld_atom(hpp, szp, "clock_id");
- v[i++] = erts_bld_atom(hpp, szp, time_sup.r.o.os_monotonic_clock_id);
+ v[i++] = erts_bld_atom(hpp, szp,
+ time_sup.r.o.os_monotonic_time_clock_id);
}
k[i] = erts_bld_atom(hpp, szp, "resolution");
- v[i++] = erts_bld_uint64(hpp, szp, time_sup.r.o.os_monotonic_resolution);
+ v[i++] = erts_bld_uint64(hpp, szp,
+ time_sup.r.o.os_monotonic_time_resolution);
k[i] = erts_bld_atom(hpp, szp, "extended");
- v[i++] = time_sup.r.o.os_monotonic_extended ? am_yes : am_no;
+ v[i++] = time_sup.r.o.os_monotonic_time_extended ? am_yes : am_no;
k[i] = erts_bld_atom(hpp, szp, "parallel");
- v[i++] = time_sup.r.o.os_monotonic_locked ? am_no : am_yes;
+ v[i++] = time_sup.r.o.os_monotonic_time_locked ? am_no : am_yes;
k[i] = erts_bld_atom(hpp, szp, "time");
v[i++] = erts_bld_sint64(hpp, szp, os_mtime);
@@ -1882,7 +1879,7 @@ erts_monotonic_time_source(struct process *c_p)
Eterm *hp = NULL;
Sint64 os_mtime = 0;
#ifdef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
- if (!time_sup.r.o.os_monotonic_disable)
+ if (!time_sup.r.o.os_monotonic_time_disable)
os_mtime = (Sint64) erts_os_monotonic_time();
#endif
@@ -1892,6 +1889,49 @@ erts_monotonic_time_source(struct process *c_p)
return bld_monotonic_time_source(&hp, NULL, os_mtime);
}
+static Eterm
+bld_system_time_source(Uint **hpp, Uint *szp, Sint64 os_stime)
+{
+ int i = 0;
+ Eterm k[5];
+ Eterm v[5];
+
+ k[i] = erts_bld_atom(hpp, szp, "function");
+ v[i++] = erts_bld_atom(hpp, szp,
+ time_sup.r.o.os_system_time_func);
+
+ if (time_sup.r.o.os_system_time_clock_id) {
+ k[i] = erts_bld_atom(hpp, szp, "clock_id");
+ v[i++] = erts_bld_atom(hpp, szp,
+ time_sup.r.o.os_system_time_clock_id);
+ }
+
+ k[i] = erts_bld_atom(hpp, szp, "resolution");
+ v[i++] = erts_bld_uint64(hpp, szp,
+ time_sup.r.o.os_system_time_resolution);
+
+ k[i] = erts_bld_atom(hpp, szp, "parallel");
+ v[i++] = am_yes;
+
+ k[i] = erts_bld_atom(hpp, szp, "time");
+ v[i++] = erts_bld_sint64(hpp, szp, os_stime);
+
+ return erts_bld_2tup_list(hpp, szp, (Sint) i, k, v);
+}
+
+Eterm
+erts_system_time_source(struct process *c_p)
+{
+ Uint hsz = 0;
+ Eterm *hp = NULL;
+ Sint64 os_stime = (Sint64) erts_os_system_time();
+
+ bld_system_time_source(NULL, &hsz, os_stime);
+ if (hsz)
+ hp = HAlloc(c_p, hsz);
+ return bld_system_time_source(&hp, NULL, os_stime);
+}
+
#include "bif.h"
@@ -2066,21 +2106,13 @@ BIF_RETTYPE timestamp_0(BIF_ALIST_0)
BIF_RETTYPE os_system_time_0(BIF_ALIST_0)
{
- ErtsMonotonicTime stime;
- SysTimeval tod;
- sys_gettimeofday(&tod);
- stime = ERTS_SEC_TO_MONOTONIC(tod.tv_sec);
- stime += ERTS_USEC_TO_MONOTONIC(tod.tv_usec);
+ ErtsSystemTime stime = erts_os_system_time();
BIF_RET(make_time_val(BIF_P, stime));
}
BIF_RETTYPE os_system_time_1(BIF_ALIST_0)
{
- ErtsMonotonicTime stime;
- SysTimeval tod;
- sys_gettimeofday(&tod);
- stime = ERTS_SEC_TO_MONOTONIC(tod.tv_sec);
- stime += ERTS_USEC_TO_MONOTONIC(tod.tv_usec);
+ ErtsSystemTime stime = erts_os_system_time();
BIF_RET(time_unit_conversion(BIF_P, BIF_ARG_1, stime, 0));
}
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index c51b665db9..27a55e0ec7 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -684,7 +684,7 @@ typedef enum {
} ErtsTimeWarpMode;
typedef struct {
- int have_os_monotonic;
+ int have_os_monotonic_time;
ErtsMonotonicTime os_monotonic_time_unit;
ErtsMonotonicTime sys_clock_resolution;
struct {
@@ -693,7 +693,13 @@ typedef struct {
char *clock_id;
int locked_use;
int extended;
- } os_monotonic_info;
+ } os_monotonic_time_info;
+ struct {
+ Uint64 resolution;
+ char *func;
+ char *clock_id;
+ int locked_use;
+ } os_system_time_info;
} ErtsSysInitTimeResult;
#define ERTS_SYS_INIT_TIME_RESULT_INITER \
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h
index a14a4b3eae..5394e94c8c 100644
--- a/erts/emulator/sys/unix/erl_unix_sys.h
+++ b/erts/emulator/sys/unix/erl_unix_sys.h
@@ -169,6 +169,10 @@ typedef long long ErtsSysHrTime;
#error No signed 64-bit type found...
#endif
+typedef ErtsMonotonicTime ErtsSystemTime;
+
+ErtsSystemTime erts_os_system_time(void);
+
#define ERTS_MONOTONIC_TIME_MIN (((ErtsMonotonicTime) 1) << 63)
#define ERTS_MONOTONIC_TIME_MAX (~ERTS_MONOTONIC_TIME_MIN)
diff --git a/erts/emulator/sys/unix/sys_time.c b/erts/emulator/sys/unix/sys_time.c
index 134e3a67b0..d6591a8296 100644
--- a/erts/emulator/sys/unix/sys_time.c
+++ b/erts/emulator/sys/unix/sys_time.c
@@ -150,44 +150,46 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
{
#if !defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT)
- init_resp->have_os_monotonic = 0;
+ init_resp->have_os_monotonic_time = 0;
#else /* defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT) */
int major, minor, build, vsn;
- init_resp->os_monotonic_info.resolution = (Uint64) 1000*1000*1000;
+ init_resp->os_monotonic_time_info.resolution = (Uint64) 1000*1000*1000;
#if defined(HAVE_CLOCK_GETRES) && defined(MONOTONIC_CLOCK_ID)
{
struct timespec ts;
- if (clock_getres(MONOTONIC_CLOCK_ID, &ts) == 0
- && ts.tv_sec == 0 && ts.tv_nsec != 0) {
- init_resp->os_monotonic_info.resolution /= ts.tv_nsec;
+ if (clock_getres(MONOTONIC_CLOCK_ID, &ts) == 0) {
+ if (ts.tv_sec == 0 && ts.tv_nsec != 0)
+ init_resp->os_monotonic_time_info.resolution /= ts.tv_nsec;
+ else if (ts.tv_sec >= 1)
+ init_resp->os_monotonic_time_info.resolution = 1;
}
}
#endif
#ifdef MONOTONIC_CLOCK_ID_STR
- init_resp->os_monotonic_info.clock_id = MONOTONIC_CLOCK_ID_STR;
+ init_resp->os_monotonic_time_info.clock_id = MONOTONIC_CLOCK_ID_STR;
#else
- init_resp->os_monotonic_info.clock_id = NULL;
+ init_resp->os_monotonic_time_info.clock_id = NULL;
#endif
- init_resp->os_monotonic_info.locked_use = 0;
+ init_resp->os_monotonic_time_info.locked_use = 0;
#if defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)
- init_resp->os_monotonic_info.func = "clock_gettime";
+ init_resp->os_monotonic_time_info.func = "clock_gettime";
#elif defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME)
- init_resp->os_monotonic_info.func = "clock_get_time";
+ init_resp->os_monotonic_time_info.func = "clock_get_time";
#elif defined(OS_MONOTONIC_TIME_USING_GETHRTIME)
- init_resp->os_monotonic_info.func = "gethrtime";
+ init_resp->os_monotonic_time_info.func = "gethrtime";
#elif defined(OS_MONOTONIC_TIME_USING_TIMES)
- init_resp->os_monotonic_info.func = "times";
+ init_resp->os_monotonic_time_info.func = "times";
#else
# error Unknown erts_os_monotonic_time() implementation
#endif
- init_resp->have_os_monotonic = 1;
+ init_resp->have_os_monotonic_time = 1;
os_version(&major, &minor, &build);
@@ -210,7 +212,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
"os_monotonic_time");
internal_state.w.f.last_delivered
= clock_gettime_monotonic_raw();
- init_resp->os_monotonic_info.locked_use = 1;
+ init_resp->os_monotonic_time_info.locked_use = 1;
}
#else /* !(defined(__linux__) && defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)) */
{
@@ -227,7 +229,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
if (sysconf(_SC_NPROCESSORS_CONF) > 1)
#endif
- init_resp->have_os_monotonic = 0;
+ init_resp->have_os_monotonic_time = 0;
}
}
}
@@ -261,9 +263,9 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
shift++;
}
- init_resp->os_monotonic_info.resolution = resolution;
+ init_resp->os_monotonic_time_info.resolution = resolution;
init_resp->os_monotonic_time_unit = time_unit;
- init_resp->os_monotonic_info.extended = 1;
+ init_resp->os_monotonic_time_info.extended = 1;
internal_state.r.o.times_shift = shift;
erts_init_os_monotonic_time_extender(&internal_state.wr.m.os_mtime_xtnd,
@@ -272,6 +274,38 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
}
#endif /* defined(OS_MONOTONIC_TIME_USING_TIMES) */
+#ifdef WALL_CLOCK_ID_STR
+ init_resp->os_system_time_info.clock_id = WALL_CLOCK_ID_STR;
+#else
+ init_resp->os_system_time_info.clock_id = NULL;
+#endif
+
+ init_resp->os_system_time_info.locked_use = 0;
+ init_resp->os_system_time_info.resolution = (Uint64) 1000*1000*1000;
+#if defined(HAVE_CLOCK_GETRES) && defined(WALL_CLOCK_ID)
+ {
+ struct timespec ts;
+ if (clock_getres(WALL_CLOCK_ID, &ts) == 0) {
+ if (ts.tv_sec == 0 && ts.tv_nsec != 0)
+ init_resp->os_system_time_info.resolution /= ts.tv_nsec;
+ else if (ts.tv_sec >= 1)
+ init_resp->os_system_time_info.resolution = 1;
+ }
+ }
+#endif
+
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+ init_resp->os_system_time_info.func = "clock_gettime";
+#elif defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME)
+ init_resp->os_system_time_info.func = "clock_get_time";
+#elif defined(OS_SYSTEM_TIME_GETTIMEOFDAY)
+ init_resp->os_system_time_info.func = "gettimeofday";
+ init_resp->os_system_time_info.resolution = 1000*1000;
+ init_resp->os_system_time_info.clock_id = NULL;
+#else
+# error Missing erts_os_system_time() implmenentation
+#endif
+
}
void
@@ -282,6 +316,105 @@ erts_late_sys_init_time(void)
#endif
}
+static ERTS_INLINE ErtsSystemTime
+adj_stime_time_unit(ErtsSystemTime stime, Uint32 res)
+{
+ if (res == ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT)
+ return stime;
+ if (res == (Uint32) 1000*1000*1000
+ && ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT == 1000*1000)
+ return stime/1000;
+ if (res == (Uint32) 1000*1000
+ && ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT == 1000*1000*1000)
+ return stime*1000;
+ return ((ErtsSystemTime)
+ erts_time_unit_conversion(stime,
+ (Uint32) res,
+ (Uint32) ERTS_MONOTONIC_TIME_UNIT));
+}
+
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+
+ErtsSystemTime
+erts_os_system_time(void)
+{
+ ErtsSystemTime stime;
+ struct timespec ts;
+
+ if (clock_gettime(WALL_CLOCK_ID,&ts) != 0) {
+ int err = errno;
+ char *errstr = err ? strerror(err) : "unknown";
+ erl_exit(ERTS_ABORT_EXIT,
+ "clock_gettime(%s, _) failed: %s (%d)\n",
+ WALL_CLOCK_ID_STR, errstr, err);
+
+ }
+
+ stime = (ErtsSystemTime) ts.tv_sec;
+ stime *= (ErtsSystemTime) 1000*1000*1000;
+ stime += (ErtsSystemTime) ts.tv_nsec;
+ return adj_stime_time_unit(stime, (Uint32) 1000*1000*1000);
+}
+
+#elif defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME)
+
+ErtsSystemTime
+erts_os_system_time(void)
+{
+ ErtsSystemTime stime;
+ kern_return_t res;
+ clock_serv_t clk_srv;
+ mach_timespec_t time_spec;
+ int err;
+
+ host_get_clock_service(mach_host_self(),
+ WALL_CLOCK_ID,
+ &clk_srv);
+ errno = 0;
+ res = clock_get_time(clk_srv, &time_spec);
+ err = errno;
+ mach_port_deallocate(mach_task_self(), clk_srv);
+ if (res != KERN_SUCCESS) {
+ char *errstr = err ? strerror(err) : "unknown";
+ erl_exit(ERTS_ABORT_EXIT,
+ "clock_get_time(%s, _) failed: %s (%d)\n",
+ MONOTONIC_CLOCK_ID_STR, errstr, err);
+ }
+
+ stime = (ErtsSystemTime) time_spec.tv_sec;
+ stime *= (ErtsSystemTime) 1000*1000*1000;
+ stime += (ErtsSystemTime) time_spec.tv_nsec;
+
+ return adj_stime_time_unit(stime, (Uint32) 1000*1000*1000);
+}
+
+#elif defined(OS_SYSTEM_TIME_GETTIMEOFDAY)
+
+ErtsSystemTime
+erts_os_system_time(void)
+{
+ ErtsSystemTime stime;
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) != 0) {
+ int err = errno;
+ char *errstr = err ? strerror(err) : "unknown";
+ erl_exit(ERTS_ABORT_EXIT,
+ "gettimeofday(_, NULL) failed: %s (%d)\n",
+ errstr, err);
+ }
+
+ stime = (ErtsSystemTime) tv.tv_sec;
+ stime *= (ErtsSystemTime) 1000*1000;
+ stime += (ErtsSystemTime) tv.tv_usec;
+
+ return adj_stime_time_unit(stime, (Uint32) 1000*1000);
+}
+
+#else
+# error Missing erts_os_system_time() implmenentation
+#endif
+
#if defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)
static ERTS_INLINE ErtsMonotonicTime
diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h
index febf3b5cca..d214ba002c 100644
--- a/erts/emulator/sys/win32/erl_win_sys.h
+++ b/erts/emulator/sys/win32/erl_win_sys.h
@@ -181,6 +181,10 @@ typedef LONGLONG ErtsMonotonicTime;
typedef LONGLONG ErtsSysHrTime;
#endif
+typedef ErtsMonotonicTime ErtsSystemTime;
+
+ErtsSystemTime erts_os_system_time(void);
+
#define ERTS_MONOTONIC_TIME_MIN (((ErtsMonotonicTime) 1) << 63)
#define ERTS_MONOTONIC_TIME_MAX (~ERTS_MONOTONIC_TIME_MIN)
diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index ea180f067f..da9c4d2e29 100644
--- a/erts/emulator/sys/win32/sys_time.c
+++ b/erts/emulator/sys/win32/sys_time.c
@@ -73,6 +73,8 @@ static int days_in_month[2][13] = {
{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31}};
+#define ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT 10
+
/*
* erts_os_monotonic_time()
*/
@@ -81,6 +83,7 @@ struct sys_time_internal_state_read_only__ {
ULONGLONG (WINAPI *pGetTickCount64)(void);
BOOL (WINAPI *pQueryPerformanceCounter)(LARGE_INTEGER *);
Sint32 pcf;
+ int using_get_tick_count_time_unit;
};
struct sys_time_internal_state_read_mostly__ {
@@ -199,7 +202,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
char kernel_dll_name[] = "kernel32";
HMODULE module;
- init_resp->os_monotonic_info.clock_id = NULL;
+ init_resp->os_monotonic_time_info.clock_id = NULL;
module = GetModuleHandle(kernel_dll_name);
if (!module) {
@@ -209,13 +212,15 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
internal_state.w.f.wrap = 0;
internal_state.w.f.last_tick_count = 0;
- init_resp->os_monotonic_info.func = "GetTickCount";
- init_resp->os_monotonic_info.locked_use = 1;
+ init_resp->os_monotonic_time_info.func = "GetTickCount";
+ init_resp->os_monotonic_time_info.locked_use = 1;
/* 10-16 ms resolution according to MicroSoft documentation */
- init_resp->os_monotonic_info.resolution = 100; /* 10 ms */
- time_unit = (ErtsMonotonicTime) (1000 << 10);
+ init_resp->os_monotonic_time_info.resolution = 100; /* 10 ms */
+ time_unit = (ErtsMonotonicTime) 1000;
+ time_unit <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
+ internal_state.r.o.using_get_tick_count_time_unit = 1;
os_mtime_func = os_monotonic_time_gtc32;
- init_resp->os_monotonic_info.extended = 1;
+ init_resp->os_monotonic_time_info.extended = 1;
erts_init_os_monotonic_time_extender(&internal_state.wr.m.os_mtime_xtnd,
get_tick_count,
60*60*24*7); /* Check once a week */
@@ -237,11 +242,13 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
if (!internal_state.r.o.pGetTickCount64)
goto get_tick_count;
- init_resp->os_monotonic_info.func = "GetTickCount64";
- init_resp->os_monotonic_info.locked_use = 0;
+ init_resp->os_monotonic_time_info.func = "GetTickCount64";
+ init_resp->os_monotonic_time_info.locked_use = 0;
/* 10-16 ms resolution according to MicroSoft documentation */
- init_resp->os_monotonic_info.resolution = 100; /* 10 ms */
- time_unit = (ErtsMonotonicTime) (1000 << 10);
+ init_resp->os_monotonic_time_info.resolution = 100; /* 10 ms */
+ time_unit = (ErtsMonotonicTime) 1000;
+ time_unit <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
+ internal_state.r.o.using_get_tick_count_time_unit = 1;
os_mtime_func = os_monotonic_time_gtc64;
if (!sys_hrtime_func)
sys_hrtime_func = sys_hrtime_gtc64;
@@ -279,25 +286,30 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
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;
+ init_resp->os_monotonic_time_info.func = "QueryPerformanceCounter";
+ init_resp->os_monotonic_time_info.locked_use = 0;
time_unit = (ErtsMonotonicTime) pf.QuadPart;
- init_resp->os_monotonic_info.resolution = time_unit;
+ internal_state.r.o.using_get_tick_count_time_unit = 0;
+ init_resp->os_monotonic_time_info.resolution = time_unit;
os_mtime_func = os_monotonic_time_qpc;
}
}
erts_sys_time_data__.r.o.os_monotonic_time = os_mtime_func;
init_resp->os_monotonic_time_unit = time_unit;
- init_resp->have_os_monotonic = 1;
+ init_resp->have_os_monotonic_time = 1;
init_resp->sys_clock_resolution = 1;
+ init_resp->os_system_time_info.func = "GetSystemTime";
+ init_resp->os_system_time_info.clock_id = NULL;
+ init_resp->os_system_time_info.resolution = 100;
+ init_resp->os_system_time_info.locked_use = 0;
+
if(GetTimeZoneInformation(&static_tzi) &&
static_tzi.StandardDate.wMonth != 0 &&
static_tzi.DaylightDate.wMonth != 0) {
have_static_tzi = 1;
}
-
}
void
@@ -585,6 +597,37 @@ sys_gettimeofday(SysTimeval *tv)
EPOCH_JULIAN_DIFF);
}
+ErtsSystemTime
+erts_os_system_time(void)
+{
+ SYSTEMTIME t;
+ FILETIME ft;
+ ULARGE_INTEGER ull;
+ ErtsSystemTime stime;
+
+ GetSystemTime(&t);
+ SystemTimeToFileTime(&t, &ft);
+ FILETIME_TO_ULI(ull,ft);
+
+ /* now in 100 ns units */
+
+ stime = (ErtsSystemTime) ull.QuadPart;
+ stime -= (((ErtsSystemTime) EPOCH_JULIAN_DIFF)
+ * ((ErtsSystemTime) (10*1000*1000)));
+ stime /= (ErtsSystemTime) (10*1000);
+
+ if (internal_state.r.o.using_get_tick_count_time_unit) {
+ stime <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
+ return stime;
+ }
+
+ return ((ErtsSystemTime)
+ erts_time_unit_conversion(stime,
+ (Uint32) 1000,
+ (Uint32) ERTS_MONOTONIC_TIME_UNIT));
+}
+
+
clock_t
sys_times(SysTimes *buffer) {
clock_t kernel_ticks = (GetTickCount() /
diff --git a/erts/example/time_compat.erl b/erts/example/time_compat.erl
index d582117ceb..90b7fbcc80 100644
--- a/erts/example/time_compat.erl
+++ b/erts/example/time_compat.erl
@@ -240,6 +240,7 @@ system_info(Item) ->
time_offset ->
final;
NotSupArg when NotSupArg == os_monotonic_time_source;
+ NotSupArg == os_system_time_source;
NotSupArg == start_time ->
%% Cannot emulate this...
erlang:error(notsup, [NotSupArg]);
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index 303f3f47b6..fcfcafa6da 100644
Binary files a/erts/preloaded/ebin/erlang.beam and b/erts/preloaded/ebin/erlang.beam differ
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 83010b17d2..c5dc40f5d1 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -2531,6 +2531,7 @@ tuple_to_list(_Tuple) ->
(nif_version) -> string();
(otp_release) -> string();
(os_monotonic_time_source) -> [{atom(),term()}];
+ (os_system_time_source) -> [{atom(),term()}];
(port_count) -> non_neg_integer();
(port_limit) -> pos_integer();
(process_count) -> pos_integer();
--
cgit v1.2.3