diff options
author | Rickard Green <[email protected]> | 2015-03-22 20:20:28 +0100 |
---|---|---|
committer | Rickard Green <[email protected]> | 2015-03-23 14:06:31 +0100 |
commit | d07319f790eb38c867bd04a23de674e2393825ff (patch) | |
tree | 78237385072b7c478ec01cbd957941b2c1fc8084 /erts/emulator/beam | |
parent | 50713b7d6179477d6018e6a9ca5610617e3de1fe (diff) | |
download | otp-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.h | 17 | ||||
-rw-r--r-- | erts/emulator/beam/erl_time_sup.c | 237 | ||||
-rw-r--r-- | erts/emulator/beam/sys.h | 2 |
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); |