aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2015-03-24 15:28:11 +0100
committerRickard Green <[email protected]>2015-03-24 16:14:07 +0100
commitc20482023b70768bd84d25f1e34dbbc2fe09cf31 (patch)
treed6f8725463f3b8f02661ac1d7e56ece7a055ac86 /erts/emulator
parent052695858c07477db480d25d2d858540088d04c3 (diff)
downloadotp-c20482023b70768bd84d25f1e34dbbc2fe09cf31.tar.gz
otp-c20482023b70768bd84d25f1e34dbbc2fe09cf31.tar.bz2
otp-c20482023b70768bd84d25f1e34dbbc2fe09cf31.zip
Better OS system time implementation
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/beam/erl_bif_info.c2
-rw-r--r--erts/emulator/beam/erl_time.h1
-rw-r--r--erts/emulator/beam/erl_time_sup.c214
-rw-r--r--erts/emulator/beam/sys.h10
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys.h4
-rw-r--r--erts/emulator/sys/unix/sys_time.c167
-rw-r--r--erts/emulator/sys/win32/erl_win_sys.h4
-rw-r--r--erts/emulator/sys/win32/sys_time.c73
8 files changed, 350 insertions, 125 deletions
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() /