aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2015-03-22 20:20:28 +0100
committerRickard Green <[email protected]>2015-03-23 14:06:31 +0100
commitd07319f790eb38c867bd04a23de674e2393825ff (patch)
tree78237385072b7c478ec01cbd957941b2c1fc8084 /erts/emulator/beam
parent50713b7d6179477d6018e6a9ca5610617e3de1fe (diff)
downloadotp-d07319f790eb38c867bd04a23de674e2393825ff.tar.gz
otp-d07319f790eb38c867bd04a23de674e2393825ff.tar.bz2
otp-d07319f790eb38c867bd04a23de674e2393825ff.zip
Better support for poor os monotonic sources
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/erl_time.h17
-rw-r--r--erts/emulator/beam/erl_time_sup.c237
-rw-r--r--erts/emulator/beam/sys.h2
3 files changed, 174 insertions, 82 deletions
diff --git a/erts/emulator/beam/erl_time.h b/erts/emulator/beam/erl_time.h
index 924b0b6091..35a1442dbd 100644
--- a/erts/emulator/beam/erl_time.h
+++ b/erts/emulator/beam/erl_time.h
@@ -219,6 +219,10 @@ erts_time_unit_conversion(Uint64 value,
* it is assumed (and need) to be a power of 10.
*/
+#if ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT < 1000*1000
+# error Compile time time unit needs to be at least 1000000
+#endif
+
#define ERTS_MONOTONIC_TIME_UNIT \
((ErtsMonotonicTime) ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT)
@@ -248,19 +252,6 @@ erts_time_unit_conversion(Uint64 value,
#define ERTS_USEC_TO_MONOTONIC__(USEC) ((ErtsMonotonicTime) (USEC))
#define ERTS_NSEC_TO_MONOTONIC__(NSEC) (((ErtsMonotonicTime) (NSEC))/1000)
-#elif ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT == 1000
-/* Milli-second time unit */
-
-#define ERTS_MONOTONIC_TO_SEC__(MSEC) ((USEC)/(1000))
-#define ERTS_MONOTONIC_TO_MSEC__(MSEC) (MSEC)
-#define ERTS_MONOTONIC_TO_USEC__(MSEC) ((MSEC)*1000)
-#define ERTS_MONOTONIC_TO_NSEC__(MSEC) ((MSEC)*(1000*1000))
-
-#define ERTS_SEC_TO_MONOTONIC__(SEC) (((ErtsMonotonicTime) (SEC))*1000)
-#define ERTS_MSEC_TO_MONOTONIC__(MSEC) ((ErtsMonotonicTime) (MSEC))
-#define ERTS_USEC_TO_MONOTONIC__(USEC) (((ErtsMonotonicTime) (USEC))/1000)
-#define ERTS_NSEC_TO_MONOTONIC__(NSEC) (((ErtsMonotonicTime) (NSEC))/(1000*1000))
-
#else
#error Missing implementation for monotonic time unit
#endif
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index b809fa8316..d961fae81a 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -21,6 +21,8 @@
* Support routines for the time
*/
+/* #define ERTS_TIME_CORRECTION_PRINT */
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -75,12 +77,12 @@ schedule_send_time_offset_changed_notifications(ErtsMonotonicTime new_offset);
#else /* ARCH_64 */
-#if ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT <= 1000*1000
+#if ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT <= 10*1000*1000
/*
* Using micro second time unit or lower. Start at zero since
* time will remain an immediate for a very long time anyway
- * (18279 years in the micro second case)...
+ * (1827 years in the 10 micro second case)...
*/
#define ERTS_MONOTONIC_TIME_START ((ErtsMonotonicTime) 0)
@@ -99,11 +101,16 @@ schedule_send_time_offset_changed_notifications(ErtsMonotonicTime new_offset);
#endif /* ARCH_64 */
-#define ERTS_MONOTONIC_OFFSET_NATIVE ERTS_MONOTONIC_TIME_START
-#define ERTS_MONOTONIC_OFFSET_NSEC ERTS_MONOTONIC_TO_NSEC__(ERTS_MONOTONIC_TIME_START)
-#define ERTS_MONOTONIC_OFFSET_USEC ERTS_MONOTONIC_TO_USEC__(ERTS_MONOTONIC_TIME_START)
-#define ERTS_MONOTONIC_OFFSET_MSEC ERTS_MONOTONIC_TO_MSEC__(ERTS_MONOTONIC_TIME_START)
-#define ERTS_MONOTONIC_OFFSET_SEC ERTS_MONOTONIC_TO_SEC__(ERTS_MONOTONIC_TIME_START)
+#define ERTS_MONOTONIC_OFFSET_NATIVE \
+ (ERTS_MONOTONIC_TIME_START - ERTS_MONOTONIC_TIME_UNIT)
+#define ERTS_MONOTONIC_OFFSET_NSEC \
+ ERTS_MONOTONIC_TO_NSEC__(ERTS_MONOTONIC_OFFSET_NATIVE)
+#define ERTS_MONOTONIC_OFFSET_USEC \
+ ERTS_MONOTONIC_TO_USEC__(ERTS_MONOTONIC_OFFSET_NATIVE)
+#define ERTS_MONOTONIC_OFFSET_MSEC \
+ ERTS_MONOTONIC_TO_MSEC__(ERTS_MONOTONIC_OFFSET_NATIVE)
+#define ERTS_MONOTONIC_OFFSET_SEC \
+ ERTS_MONOTONIC_TO_SEC__(ERTS_MONOTONIC_OFFSET_NATIVE)
#else /* ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT */
@@ -120,25 +127,6 @@ schedule_send_time_offset_changed_notifications(ErtsMonotonicTime new_offset);
#endif /* ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT */
-#define ERTS_MONOTONIC_TO_SYS_TIME_VAL(TVP, MT) \
- do { \
- ErtsMonotonicTime sec__, usec__; \
- sec__ = ERTS_MONOTONIC_TO_SEC((MT)); \
- usec__ = ERTS_MONOTONIC_TO_USEC((MT)) - sec__*1000000; \
- ASSERT(usec__ < 1000000); \
- (TVP)->tv_sec = sec__; \
- (TVP)->tv_usec = usec__; \
- } while (0)
-
-#define ERTS_MAX_SYSTEM_TIME_DIFF ERTS_MSEC_TO_MONOTONIC(10)
-#define ERTS_SYSTEM_TIME_DIFF_EXCEED_LIMIT(ESYSTIME, OSSYSTIME) \
- (((Uint64) (ESYSTIME)) - (((Uint64) (OSSYSTIME)) \
- - ERTS_MAX_SYSTEM_TIME_DIFF) \
- > 2*ERTS_MAX_SYSTEM_TIME_DIFF)
-
-#define ERTS_TIME_CORRECTION_LARGE_ADJ_DIFF (ERTS_MAX_SYSTEM_TIME_DIFF/2)
-#define ERTS_TIME_CORRECTION_SMALL_ADJ_DIFF ERTS_USEC_TO_MONOTONIC(500)
-
struct time_sup_read_only__ {
ErtsMonotonicTime (*get_time)(void);
int correction;
@@ -150,6 +138,7 @@ struct time_sup_read_only__ {
char *os_monotonic_clock_id;
int os_monotonic_locked;
Uint64 os_monotonic_resolution;
+ Uint64 os_monotonic_extended;
#endif
#if !ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT
ErtsMonotonicTime start;
@@ -161,6 +150,10 @@ struct time_sup_read_only__ {
ErtsMonotonicTime sec;
} start_offset;
#endif
+ struct {
+ ErtsMonotonicTime large_diff;
+ ErtsMonotonicTime small_diff;
+ } adj;
};
typedef struct {
@@ -338,13 +331,77 @@ static ErtsMonotonicTime get_corrected_time(void)
return calc_corrected_erl_mtime(os_mtime, cip, NULL);
}
+#ifdef ERTS_TIME_CORRECTION_PRINT
+
+static ERTS_INLINE void
+print_correction(int change,
+ ErtsMonotonicTime sdiff,
+ ErtsMonotonicTime old_ecorr,
+ ErtsMonotonicTime old_dcorr,
+ ErtsMonotonicTime new_ecorr,
+ ErtsMonotonicTime new_dcorr,
+ Uint tmo)
+{
+ ErtsMonotonicTime usec_sdiff;
+ if (sdiff < 0)
+ usec_sdiff = -1*ERTS_MONOTONIC_TO_USEC(-1*sdiff);
+ else
+ usec_sdiff = ERTS_MONOTONIC_TO_USEC(sdiff);
+
+ if (!change)
+ fprintf(stderr,
+ "sdiff = %lld usec : [ec=%lld ppm, dc=%lld ppm] : "
+ "tmo = %lld msec\r\n",
+ (long long) usec_sdiff,
+ (long long) (1000000*old_ecorr) / ERTS_TCORR_ERR_UNIT,
+ (long long) (1000000*old_dcorr) / ERTS_MONOTONIC_TIME_UNIT,
+ (long long) tmo);
+ else
+ fprintf(stderr,
+ "sdiff = %lld usec : [ec=%lld ppm, dc=%lld ppm] "
+ "-> [ec=%lld ppm, dc=%lld ppm] : tmo = %lld msec\r\n",
+ (long long) usec_sdiff,
+ (long long) (1000000*old_ecorr) / ERTS_TCORR_ERR_UNIT,
+ (long long) (1000000*old_dcorr) / ERTS_MONOTONIC_TIME_UNIT,
+ (long long) (1000000*new_ecorr) / ERTS_TCORR_ERR_UNIT,
+ (long long) (1000000*new_dcorr) / ERTS_MONOTONIC_TIME_UNIT,
+ (long long) tmo);
+
+}
+
+#endif
+
static void
check_time_correction(void *unused)
{
+#ifndef ERTS_TIME_CORRECTION_PRINT
+# define ERTS_PRINT_CORRECTION
+#else
+# ifdef ERTS_HAVE_CORRECTED_OS_MONOTONIC
+# define ERTS_PRINT_CORRECTION \
+ print_correction(set_new_correction, \
+ sdiff, \
+ cip->correction.error, \
+ 0, \
+ new_correction.error, \
+ 0, \
+ timeout)
+# else
+# define ERTS_PRINT_CORRECTION \
+ print_correction(set_new_correction, \
+ sdiff, \
+ cip->correction.error, \
+ cip->correction.drift, \
+ new_correction.error, \
+ new_correction.drift, \
+ timeout)
+# endif
+#endif
ErtsMonotonicCorrectionData cdata;
ErtsMonotonicCorrection new_correction;
ErtsMonotonicCorrectionInstance *cip;
- ErtsMonotonicTime mdiff, sdiff, os_mtime, erl_mtime, os_stime, erl_stime, time_offset;
+ 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;
@@ -377,8 +434,8 @@ check_time_correction(void *unused)
new_correction = cip->correction;
if (time_sup.r.o.warp_mode == ERTS_MULTI_TIME_WARP_MODE
- && (sdiff < -2*ERTS_TIME_CORRECTION_SMALL_ADJ_DIFF
- || 2*ERTS_TIME_CORRECTION_SMALL_ADJ_DIFF < sdiff)) {
+ && (sdiff < -2*time_sup.r.o.adj.small_diff
+ || 2*time_sup.r.o.adj.small_diff < sdiff)) {
/* System time diff exeeded limits; change time offset... */
time_offset -= sdiff;
sdiff = 0;
@@ -393,16 +450,16 @@ check_time_correction(void *unused)
}
}
else if (cdata.curr.correction.error == 0) {
- if (sdiff < -ERTS_TIME_CORRECTION_SMALL_ADJ_DIFF) {
+ if (sdiff < -time_sup.r.o.adj.small_diff) {
set_new_correction = 1;
- if (sdiff < -ERTS_TIME_CORRECTION_LARGE_ADJ_DIFF)
+ if (sdiff < -time_sup.r.o.adj.large_diff)
new_correction.error = ERTS_TCORR_ERR_LARGE_ADJ;
else
new_correction.error = ERTS_TCORR_ERR_SMALL_ADJ;
}
- else if (sdiff > ERTS_TIME_CORRECTION_SMALL_ADJ_DIFF) {
+ else if (sdiff > time_sup.r.o.adj.small_diff) {
set_new_correction = 1;
- if (sdiff > ERTS_TIME_CORRECTION_LARGE_ADJ_DIFF)
+ if (sdiff > time_sup.r.o.adj.large_diff)
new_correction.error = -ERTS_TCORR_ERR_LARGE_ADJ;
else
new_correction.error = -ERTS_TCORR_ERR_SMALL_ADJ;
@@ -414,16 +471,16 @@ check_time_correction(void *unused)
else if (cdata.curr.correction.error > 0) {
if (sdiff < 0) {
if (cdata.curr.correction.error == ERTS_TCORR_ERR_LARGE_ADJ
- || -ERTS_TIME_CORRECTION_LARGE_ADJ_DIFF <= sdiff)
+ || -time_sup.r.o.adj.large_diff <= sdiff)
set_new_correction = 0;
else {
new_correction.error = ERTS_TCORR_ERR_LARGE_ADJ;
set_new_correction = 1;
}
}
- else if (sdiff > ERTS_TIME_CORRECTION_SMALL_ADJ_DIFF) {
+ else if (sdiff > time_sup.r.o.adj.small_diff) {
set_new_correction = 1;
- if (sdiff > ERTS_TIME_CORRECTION_LARGE_ADJ_DIFF)
+ if (sdiff > time_sup.r.o.adj.large_diff)
new_correction.error = -ERTS_TCORR_ERR_LARGE_ADJ;
else
new_correction.error = -ERTS_TCORR_ERR_SMALL_ADJ;
@@ -436,7 +493,7 @@ check_time_correction(void *unused)
else /* if (cdata.curr.correction.error < 0) */ {
if (0 < sdiff) {
if (cdata.curr.correction.error == -ERTS_TCORR_ERR_LARGE_ADJ
- || sdiff <= ERTS_TIME_CORRECTION_LARGE_ADJ_DIFF)
+ || sdiff <= time_sup.r.o.adj.large_diff)
set_new_correction = 0;
else {
new_correction.error = -ERTS_TCORR_ERR_LARGE_ADJ;
@@ -444,9 +501,9 @@ check_time_correction(void *unused)
}
set_new_correction = 0;
}
- else if (sdiff < -ERTS_TIME_CORRECTION_SMALL_ADJ_DIFF) {
+ else if (sdiff < -time_sup.r.o.adj.small_diff) {
set_new_correction = 1;
- if (sdiff < -ERTS_TIME_CORRECTION_LARGE_ADJ_DIFF)
+ if (sdiff < -time_sup.r.o.adj.large_diff)
new_correction.error = ERTS_TCORR_ERR_LARGE_ADJ;
else
new_correction.error = ERTS_TCORR_ERR_SMALL_ADJ;
@@ -475,11 +532,13 @@ check_time_correction(void *unused)
mtime_acc = ddp->acc.mon;
stime_acc = ddp->acc.sys;
- avg_drift_adj = ((stime_acc - mtime_acc)*ERTS_MONOTONIC_TIME_UNIT) / mtime_acc;
+ avg_drift_adj = (((stime_acc - mtime_acc)*ERTS_MONOTONIC_TIME_UNIT)
+ / mtime_acc);
mtime_diff = os_mtime - old_os_mtime;
stime_diff = os_stime - old_os_stime;
- drift_adj = ((stime_diff - mtime_diff)*ERTS_MONOTONIC_TIME_UNIT) / mtime_diff;
+ drift_adj = (((stime_diff - mtime_diff)*ERTS_MONOTONIC_TIME_UNIT)
+ / mtime_diff);
ix++;
if (ix >= ERTS_DRIFT_INTERVALS)
@@ -499,10 +558,11 @@ check_time_correction(void *unused)
ddp->acc.sys = stime_acc;
/*
- * If calculated drift adjustment is if off by more than 20% from the
- * average drift we interpret this as a discontinous leap in system
- * time and ignore it. If it actually is a change in drift we will
- * later detect this when the average drift change.
+ * If calculated drift adjustment is if off by more than 20%
+ * from the average drift we interpret this as a discontinous
+ * leap in system time and ignore it. If it actually is a
+ * change in drift we will later detect this when the average
+ * drift change.
*/
drift_adj_diff = avg_drift_adj - drift_adj;
if (drift_adj_diff < -ERTS_TIME_DRIFT_MAX_ADJ_DIFF
@@ -512,7 +572,8 @@ check_time_correction(void *unused)
}
else {
if (ddp->dirty_counter <= 0) {
- drift_adj = ((stime_acc - mtime_acc)*ERTS_MONOTONIC_TIME_UNIT) / mtime_acc;
+ drift_adj = ((stime_acc - mtime_acc)
+ *ERTS_MONOTONIC_TIME_UNIT) / mtime_acc;
}
if (ddp->dirty_counter >= 0) {
if (ddp->dirty_counter == 0) {
@@ -573,7 +634,9 @@ check_time_correction(void *unused)
&& time_sup.inf.c.parmon.cdata.short_check_interval) {
timeout = ERTS_MONOTONIC_TO_MSEC(ERTS_SHORT_TIME_CORRECTION_CHECK);
}
-
+
+ ERTS_PRINT_CORRECTION;
+
if (set_new_correction) {
erts_smp_rwmtx_rwlock(&time_sup.inf.c.parmon.rwmtx);
@@ -610,6 +673,8 @@ check_time_correction(void *unused)
NULL,
NULL,
timeout);
+
+#undef ERTS_PRINT_CORRECTION
}
#ifndef ERTS_HAVE_CORRECTED_OS_MONOTONIC
@@ -618,7 +683,8 @@ static void
init_check_time_correction(void *unused)
{
ErtsMonotonicDriftData *ddp;
- ErtsMonotonicTime old_mtime, old_stime, mtime, stime, mtime_diff, stime_diff;
+ ErtsMonotonicTime old_mtime, old_stime, mtime, stime, mtime_diff,
+ stime_diff;
int ix;
SysTimeval tod;
@@ -690,6 +756,7 @@ static void
late_init_time_correction(void)
{
if (time_sup.inf.c.finalized_offset) {
+
erts_init_timer(&time_sup.inf.c.parmon.timer);
erts_set_timer(&time_sup.inf.c.parmon.timer,
#ifndef ERTS_HAVE_CORRECTED_OS_MONOTONIC
@@ -792,6 +859,8 @@ void erts_init_sys_time_sup(void)
= 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;
#endif
}
@@ -799,7 +868,7 @@ int
erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
{
#if !ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT
- ErtsMonotonicTime abs_start;
+ ErtsMonotonicTime abs_native_offset, native_offset;
#endif
ASSERT(ERTS_MONOTONIC_TIME_MIN < ERTS_MONOTONIC_TIME_MAX);
@@ -822,36 +891,42 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
time_sup.r.o.start /= ERTS_MONOTONIC_TIME_UNIT;
time_sup.r.o.start *= ERTS_MONOTONIC_TIME_UNIT;
time_sup.r.o.start += ERTS_MONOTONIC_TIME_UNIT;
- abs_start = time_sup.r.o.start;
+ native_offset = time_sup.r.o.start - ERTS_MONOTONIC_TIME_UNIT;
+ native_offset = native_offset;
#else /* ARCH_64 */
- if (ERTS_MONOTONIC_TIME_UNIT <= 1000*1000)
- abs_start = time_sup.r.o.start = 0;
+ if (ERTS_MONOTONIC_TIME_UNIT <= 10*1000*1000) {
+ time_sup.r.o.start = 0;
+ native_offset = -ERTS_MONOTONIC_TIME_UNIT;
+ abs_native_offset = ERTS_MONOTONIC_TIME_UNIT;
+ }
else {
time_sup.r.o.start = ((ErtsMonotonicTime) MIN_SMALL);
time_sup.r.o.start /= ERTS_MONOTONIC_TIME_UNIT;
time_sup.r.o.start *= ERTS_MONOTONIC_TIME_UNIT;
- abs_start = -1*time_sup.r.o.start;
+ native_offset = time_sup.r.o.start - ERTS_MONOTONIC_TIME_UNIT;
+ abs_native_offset = -1*native_offset;
}
#endif
- time_sup.r.o.start_offset.native = time_sup.r.o.start;
+ time_sup.r.o.start_offset.native = (time_sup.r.o.start
+ - ERTS_MONOTONIC_TIME_UNIT);
time_sup.r.o.start_offset.nsec = (ErtsMonotonicTime)
- erts_time_unit_conversion((Uint64) abs_start,
+ erts_time_unit_conversion((Uint64) abs_native_offset,
(Uint32) ERTS_MONOTONIC_TIME_UNIT,
(Uint32) 1000*1000*1000);
time_sup.r.o.start_offset.usec = (ErtsMonotonicTime)
- erts_time_unit_conversion((Uint64) abs_start,
+ erts_time_unit_conversion((Uint64) abs_native_offset,
(Uint32) ERTS_MONOTONIC_TIME_UNIT,
(Uint32) 1000*1000);
time_sup.r.o.start_offset.msec = (ErtsMonotonicTime)
- erts_time_unit_conversion((Uint64) abs_start,
+ erts_time_unit_conversion((Uint64) abs_native_offset,
(Uint32) ERTS_MONOTONIC_TIME_UNIT,
(Uint32) 1000);
time_sup.r.o.start_offset.sec = (ErtsMonotonicTime)
- erts_time_unit_conversion((Uint64) abs_start,
+ erts_time_unit_conversion((Uint64) abs_native_offset,
(Uint32) ERTS_MONOTONIC_TIME_UNIT,
(Uint32) 1);
- if (time_sup.r.o.start < 0) {
+ if (native_offset < 0) {
time_sup.r.o.start_offset.nsec *= -1;
time_sup.r.o.start_offset.usec *= -1;
time_sup.r.o.start_offset.msec *= -1;
@@ -860,6 +935,26 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
#endif
+ 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.small_diff = time_sup.r.o.adj.large_diff/10;
+
+#ifdef ERTS_TIME_CORRECTION_PRINT
+ fprintf(stderr, "start = %lld\n\r", (long long) ERTS_MONOTONIC_TIME_START);
+ fprintf(stderr, "native offset = %lld\n\r", (long long) ERTS_MONOTONIC_OFFSET_NATIVE);
+ fprintf(stderr, "nsec offset = %lld\n\r", (long long) ERTS_MONOTONIC_OFFSET_NSEC);
+ fprintf(stderr, "usec offset = %lld\n\r", (long long) ERTS_MONOTONIC_OFFSET_USEC);
+ fprintf(stderr, "msec offset = %lld\n\r", (long long) ERTS_MONOTONIC_OFFSET_MSEC);
+ fprintf(stderr, "sec offset = %lld\n\r", (long long) ERTS_MONOTONIC_OFFSET_SEC);
+ fprintf(stderr, "large diff = %lld usec\r\n",
+ (long long) ERTS_MONOTONIC_TO_USEC(time_sup.r.o.adj.large_diff));
+ fprintf(stderr, "small diff = %lld usec\r\n",
+ (long long) ERTS_MONOTONIC_TO_USEC(time_sup.r.o.adj.small_diff));
+#endif
+
if (ERTS_MONOTONIC_TIME_UNIT < ERTS_CLKTCK_RESOLUTION)
ERTS_INTERNAL_ERROR("Too small monotonic time time unit");
@@ -878,6 +973,7 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
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 -= ERTS_MONOTONIC_TIME_UNIT;
init_time_offset(offset);
rwmtx_opts.type = ERTS_SMP_RWMTX_TYPE_EXTREMELY_FREQUENT_READ;
@@ -897,7 +993,7 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
cdatap->curr.correction.drift = 0;
#endif
cdatap->curr.correction.error = 0;
- cdatap->curr.erl_mtime = 0;
+ cdatap->curr.erl_mtime = ERTS_MONOTONIC_TIME_UNIT;
cdatap->curr.os_mtime = time_sup.inf.c.minit;
cdatap->last_check = time_sup.inf.c.minit;
cdatap->short_check_interval = ERTS_INIT_SHORT_INTERVAL_COUNTER;
@@ -910,9 +1006,10 @@ 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);
- offset = stime;
+ stime += ERTS_USEC_TO_MONOTONIC(time_sup.inf.c.inittv.tv_usec);
+ offset = stime - ERTS_MONOTONIC_TIME_UNIT;
time_sup.inf.c.not_corrected_moffset = offset;
init_time_offset(offset);
time_sup.f.c.last_not_corrected_time = 0;
@@ -937,6 +1034,7 @@ erts_late_init_time_sup(void)
if (time_sup.r.o.get_time == get_corrected_time)
late_init_time_correction();
#endif
+ erts_late_sys_init_time();
}
ErtsTimeWarpMode erts_time_warp_mode(void)
@@ -1737,7 +1835,7 @@ make_time_val(Process *c_p, ErtsMonotonicTime time_val)
Eterm
erts_get_monotonic_start_time(struct process *c_p)
{
- return make_time_val(c_p, ERTS_MONOTONIC_OFFSET_NATIVE);
+ return make_time_val(c_p, ERTS_MONOTONIC_TIME_START);
}
static Eterm
@@ -1747,8 +1845,8 @@ bld_monotonic_time_source(Uint **hpp, Uint *szp, Sint64 os_mtime)
return NIL;
#else
int i = 0;
- Eterm k[5];
- Eterm v[5];
+ Eterm k[6];
+ Eterm v[6];
if (time_sup.r.o.os_monotonic_disable)
return NIL;
@@ -1761,10 +1859,11 @@ bld_monotonic_time_source(Uint **hpp, Uint *szp, Sint64 os_mtime)
v[i++] = erts_bld_atom(hpp, szp, time_sup.r.o.os_monotonic_clock_id);
}
- if (time_sup.r.o.os_monotonic_resolution) {
- k[i] = erts_bld_atom(hpp, szp, "resolution");
- v[i++] = erts_bld_uint64(hpp, szp, time_sup.r.o.os_monotonic_resolution);
- }
+ k[i] = erts_bld_atom(hpp, szp, "resolution");
+ v[i++] = erts_bld_uint64(hpp, szp, time_sup.r.o.os_monotonic_resolution);
+
+ k[i] = erts_bld_atom(hpp, szp, "extended");
+ v[i++] = time_sup.r.o.os_monotonic_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;
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index a108e819c6..d83bdf8d31 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -692,6 +692,7 @@ typedef struct {
char *func;
char *clock_id;
int locked_use;
+ int extended;
} os_monotonic_info;
} ErtsSysInitTimeResult;
@@ -700,6 +701,7 @@ typedef struct {
extern void erts_init_sys_time_sup(void);
extern void sys_init_time(ErtsSysInitTimeResult *);
+extern void erts_late_sys_init_time(void);
extern void erts_deliver_time(void);
extern void erts_time_remaining(SysTimeval *);
extern int erts_init_time_sup(int, ErtsTimeWarpMode);