Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
8212-erts-Improve-checking-of-monotonic-time.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 8212-erts-Improve-checking-of-monotonic-time.patch of Package erlang
From 122c5d5d7da34d63b0fa6b215137b6a5585a8d56 Mon Sep 17 00:00:00 2001 From: Rickard Green <rickard@erlang.org> Date: Tue, 26 Mar 2024 14:41:12 +0100 Subject: [PATCH 2/3] [erts] Improve checking of monotonic time --- erts/emulator/beam/erl_process.c | 3 + erts/emulator/beam/erl_process.h | 3 + erts/emulator/beam/erl_time.h | 6 ++ erts/emulator/beam/erl_time_sup.c | 120 ++++++++++++++++++++++-------- 4 files changed, 100 insertions(+), 32 deletions(-) diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index ab39507bd3..a6297a9518 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -5943,6 +5943,9 @@ init_scheduler_data(ErtsSchedulerData* esdp, int num, erts_init_atom_cache_map(&esdp->atom_cache_map); esdp->last_monotonic_time = 0; +#ifdef ERTS_CHECK_MONOTONIC_TIME + esdp->last_os_monotonic_time = ERTS_SINT64_MIN; +#endif esdp->check_time_reds = 0; esdp->thr_id = (Uint32) num; diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index a112229067..a4a37d691d 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -704,6 +704,9 @@ struct ErtsSchedulerData_ { ErtsAtomCacheMap atom_cache_map; ErtsMonotonicTime last_monotonic_time; +#ifdef ERTS_CHECK_MONOTONIC_TIME + ErtsMonotonicTime last_os_monotonic_time; +#endif int check_time_reds; Uint32 thr_id; diff --git a/erts/emulator/beam/erl_time.h b/erts/emulator/beam/erl_time.h index 968f21fd51..568899b144 100644 --- a/erts/emulator/beam/erl_time.h +++ b/erts/emulator/beam/erl_time.h @@ -98,6 +98,12 @@ void erts_p_slpq(void); /* time_sup */ +/* + * If ERTS_CHECK_MONOTONIC_TIME is defined we will check that Erlang + * and OS monotonic time are monotonic on a per thread basis... + */ +#define ERTS_CHECK_MONOTONIC_TIME 1 + #if (defined(HAVE_GETHRVTIME) || defined(HAVE_CLOCK_GETTIME_CPU_TIME)) # ifndef HAVE_ERTS_NOW_CPU # define HAVE_ERTS_NOW_CPU diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c index 0e1d4b087f..5c5ab22172 100644 --- a/erts/emulator/beam/erl_time_sup.c +++ b/erts/emulator/beam/erl_time_sup.c @@ -82,7 +82,7 @@ static void schedule_send_time_offset_changed_notifications(ErtsMonotonicTime new_offset); struct time_sup_read_only__ { - ErtsMonotonicTime (*get_time)(void); + ErtsMonotonicTime (*get_time)(ErtsSchedulerData *esdp); int correction; ErtsTimeWarpMode warp_mode; #ifdef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT @@ -214,17 +214,17 @@ get_time_offset(void) static ERTS_INLINE void update_last_mtime(ErtsSchedulerData *esdp, ErtsMonotonicTime mtime) { - if (!esdp) - esdp = erts_get_scheduler_data(); if (esdp) { -#if 1 - if (mtime < esdp->last_monotonic_time) +#ifdef ERTS_CHECK_MONOTONIC_TIME + if (esdp->last_monotonic_time > mtime) { + ERTS_ASSERT(esdp == erts_get_scheduler_data()); erts_exit(ERTS_ABORT_EXIT, - "Monotonic time stepped backwards!\n" + "Erlang monotonic time stepped backwards!\n" "Previous time: %b64d\n" "Current time: %b64d\n", esdp->last_monotonic_time, mtime); + } #endif ASSERT(mtime >= esdp->last_monotonic_time); esdp->last_monotonic_time = mtime; @@ -232,6 +232,26 @@ update_last_mtime(ErtsSchedulerData *esdp, ErtsMonotonicTime mtime) } } +static ERTS_INLINE void +check_os_monotonic_time(ErtsSchedulerData *esdp, ErtsMonotonicTime mtime) +{ +#ifdef ERTS_CHECK_MONOTONIC_TIME + if (esdp) { + if (esdp->last_os_monotonic_time > mtime) { + ERTS_ASSERT(esdp == erts_get_scheduler_data()); + erts_exit(ERTS_ABORT_EXIT, + "OS monotonic time stepped backwards!\n" + "Previous time: %b64d\n" + "Current time: %b64d\n", + esdp->last_os_monotonic_time, + mtime); + } + esdp->last_os_monotonic_time = mtime; + } +#endif +} + + #ifdef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT /* @@ -283,7 +312,7 @@ calc_corrected_erl_mtime(ErtsMonotonicTime os_mtime, } static ERTS_INLINE ErtsMonotonicTime -read_corrected_time(int os_drift_corrected) +read_corrected_time(int os_drift_corrected, ErtsSchedulerData *esdp) { ErtsMonotonicTime os_mtime; ErtsMonotonicCorrectionInstance ci; @@ -303,18 +332,20 @@ read_corrected_time(int os_drift_corrected) erts_rwmtx_runlock(&time_sup.inf.c.parmon.rwmtx); + check_os_monotonic_time(esdp, os_mtime); + return calc_corrected_erl_mtime(os_mtime, &ci, NULL, os_drift_corrected); } -static ErtsMonotonicTime get_os_drift_corrected_time(void) +static ErtsMonotonicTime get_os_drift_corrected_time(ErtsSchedulerData *esdp) { - return read_corrected_time(!0); + return read_corrected_time(!0, esdp); } -static ErtsMonotonicTime get_corrected_time(void) +static ErtsMonotonicTime get_corrected_time(ErtsSchedulerData *esdp) { - return read_corrected_time(0); + return read_corrected_time(0, esdp); } #ifdef ERTS_TIME_CORRECTION_PRINT @@ -379,6 +410,9 @@ check_time_correction(void *vesdp) int os_drift_corrected = time_sup.r.o.os_corrected_monotonic_time; int set_new_correction = 0, begin_short_intervals = 0; + if (!esdp) + esdp = erts_get_scheduler_data(); + erts_rwmtx_rlock(&time_sup.inf.c.parmon.rwmtx); erts_os_times(&os_mtime, &os_stime); @@ -387,6 +421,8 @@ check_time_correction(void *vesdp) erts_rwmtx_runlock(&time_sup.inf.c.parmon.rwmtx); + check_os_monotonic_time(esdp, os_mtime); + if (os_mtime < ci.os_mtime) erts_exit(ERTS_ABORT_EXIT, "OS monotonic time stepped backwards\n"); @@ -677,10 +713,9 @@ check_time_correction(void *vesdp) time_sup.inf.c.parmon.cdata.insts.curr.correction = new_correction; erts_rwmtx_rwunlock(&time_sup.inf.c.parmon.rwmtx); - } - if (!esdp) - esdp = erts_get_scheduler_data(); + check_os_monotonic_time(esdp, os_mtime); + } erts_twheel_set_timer(esdp->timer_wheel, &time_sup.inf.c.parmon.timer, @@ -689,10 +724,13 @@ check_time_correction(void *vesdp) timeout_pos); } -static ErtsMonotonicTime get_os_corrected_time(void) +static ErtsMonotonicTime get_os_corrected_time(ErtsSchedulerData *esdp) { + ErtsMonotonicTime os_mtime; ASSERT(time_sup.r.o.warp_mode == ERTS_MULTI_TIME_WARP_MODE); - return erts_os_monotonic_time() + time_sup.r.o.moffset; + os_mtime = erts_os_monotonic_time(); + check_os_monotonic_time(esdp, os_mtime); + return os_mtime + time_sup.r.o.moffset; } static void @@ -706,6 +744,8 @@ check_time_offset(void *vesdp) erts_os_times(&os_mtime, &os_stime); + check_os_monotonic_time(esdp, os_mtime); + erl_mtime = os_mtime + time_sup.r.o.moffset; time_offset = get_time_offset(); erl_stime = erl_mtime + time_offset; @@ -754,6 +794,11 @@ init_check_time_correction(void *vesdp) erts_os_times(&mtime, &stime); + check_os_monotonic_time((!vesdp + ? erts_get_scheduler_data() + : (ErtsSchedulerData *) vesdp), + mtime); + mtime_diff = mtime - old_mtime; stime_diff = stime - old_stime; smtime_diff = stime_diff - mtime_diff; @@ -802,6 +847,8 @@ finalize_corrected_time_offset(ErtsSystemTime *stimep) erts_rwmtx_runlock(&time_sup.inf.c.parmon.rwmtx); + check_os_monotonic_time(erts_get_scheduler_data(), os_mtime); + if (os_mtime < ci.os_mtime) erts_exit(ERTS_ABORT_EXIT, "OS monotonic time stepped backwards\n"); @@ -849,7 +896,7 @@ late_init_time_correction(ErtsSchedulerData *esdp) #endif /* ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT */ -static ErtsMonotonicTime get_not_corrected_time(void) +static ErtsMonotonicTime get_not_corrected_time(ErtsSchedulerData *esdp) { ErtsMonotonicTime stime, mtime; @@ -1120,8 +1167,7 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode) ErtsMonotonicCorrectionData *cdatap; erts_rwmtx_opt_t rwmtx_opts = ERTS_RWMTX_OPT_DEFAULT_INITER; ErtsMonotonicTime offset; - erts_os_times(&time_sup.inf.c.minit, - &time_sup.inf.c.sinit); + erts_os_times(&time_sup.inf.c.minit, &time_sup.inf.c.sinit); time_sup.r.o.moffset = -1*time_sup.inf.c.minit; time_sup.r.o.moffset += ERTS_MONOTONIC_BEGIN; offset = time_sup.inf.c.sinit; @@ -1371,9 +1417,10 @@ void erts_wall_clock_elapsed_both(ErtsMonotonicTime *ms_total, ErtsMonotonicTime *ms_diff) { ErtsMonotonicTime now, elapsed; + ErtsSchedulerData *esdp = erts_get_scheduler_data(); - now = time_sup.r.o.get_time(); - update_last_mtime(NULL, now); + now = time_sup.r.o.get_time(esdp); + update_last_mtime(esdp, now); elapsed = ERTS_MONOTONIC_TO_MSEC(now); elapsed -= ERTS_MONOTONIC_TO_MSEC(ERTS_MONOTONIC_BEGIN); @@ -1740,10 +1787,11 @@ void get_now(Uint* megasec, Uint* sec, Uint* microsec) { ErtsMonotonicTime now_megasec, now_sec, now, prev, mtime, time_offset; - - mtime = time_sup.r.o.get_time(); + ErtsSchedulerData *esdp = erts_get_scheduler_data(); + + mtime = time_sup.r.o.get_time(esdp); time_offset = get_time_offset(); - update_last_mtime(NULL, mtime); + update_last_mtime(esdp, mtime); now = ERTS_MONOTONIC_TO_USEC(mtime + time_offset); /* Make sure now time is later than last time */ @@ -1775,7 +1823,10 @@ get_now(Uint* megasec, Uint* sec, Uint* microsec) ErtsMonotonicTime erts_get_monotonic_time(ErtsSchedulerData *esdp) { - ErtsMonotonicTime mtime = time_sup.r.o.get_time(); + ErtsMonotonicTime mtime; + if (!esdp) + esdp = erts_get_scheduler_data(); + mtime = time_sup.r.o.get_time(esdp); update_last_mtime(esdp, mtime); return mtime; } @@ -2267,7 +2318,7 @@ erts_napi_monotonic_time(int time_unit) if (!esdp) return ERTS_NAPI_TIME_ERROR; - mtime = time_sup.r.o.get_time(); + mtime = time_sup.r.o.get_time(esdp); update_last_mtime(esdp, mtime); switch (time_unit) { @@ -2371,7 +2422,8 @@ erts_napi_convert_time_unit(ErtsMonotonicTime val, int from, int to) BIF_RETTYPE monotonic_time_0(BIF_ALIST_0) { - ErtsMonotonicTime mtime = time_sup.r.o.get_time(); + ErtsSchedulerData *esdp = erts_proc_sched_data(BIF_P); + ErtsMonotonicTime mtime = time_sup.r.o.get_time(esdp); update_last_mtime(erts_proc_sched_data(BIF_P), mtime); mtime += ERTS_MONOTONIC_OFFSET_NATIVE; BIF_RET(make_time_val(BIF_P, mtime)); @@ -2379,26 +2431,29 @@ BIF_RETTYPE monotonic_time_0(BIF_ALIST_0) BIF_RETTYPE monotonic_time_1(BIF_ALIST_1) { - ErtsMonotonicTime mtime = time_sup.r.o.get_time(); - update_last_mtime(erts_proc_sched_data(BIF_P), mtime); + ErtsSchedulerData *esdp = erts_proc_sched_data(BIF_P); + ErtsMonotonicTime mtime = time_sup.r.o.get_time(esdp); + update_last_mtime(esdp, mtime); BIF_RET(time_unit_conversion(BIF_P, BIF_ARG_1, mtime, 1)); } BIF_RETTYPE system_time_0(BIF_ALIST_0) { ErtsMonotonicTime mtime, offset; - mtime = time_sup.r.o.get_time(); + ErtsSchedulerData *esdp = erts_proc_sched_data(BIF_P); + mtime = time_sup.r.o.get_time(esdp); offset = get_time_offset(); - update_last_mtime(erts_proc_sched_data(BIF_P), mtime); + update_last_mtime(esdp, mtime); BIF_RET(make_time_val(BIF_P, mtime + offset)); } BIF_RETTYPE system_time_1(BIF_ALIST_0) { ErtsMonotonicTime mtime, offset; - mtime = time_sup.r.o.get_time(); + ErtsSchedulerData *esdp = erts_proc_sched_data(BIF_P); + mtime = time_sup.r.o.get_time(esdp); offset = get_time_offset(); - update_last_mtime(erts_proc_sched_data(BIF_P), mtime); + update_last_mtime(esdp, mtime); BIF_RET(time_unit_conversion(BIF_P, BIF_ARG_1, mtime + offset, 0)); } @@ -2425,10 +2480,11 @@ BIF_RETTYPE timestamp_0(BIF_ALIST_0) Eterm *hp, res; ErtsMonotonicTime mtime, offset; Uint mega_sec, sec, micro_sec; + ErtsSchedulerData *esdp = erts_proc_sched_data(BIF_P); - mtime = time_sup.r.o.get_time(); + mtime = time_sup.r.o.get_time(esdp); offset = get_time_offset(); - update_last_mtime(erts_proc_sched_data(BIF_P), mtime); + update_last_mtime(esdp, mtime); make_timestamp_value(&mega_sec, &sec, µ_sec, mtime, offset); -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor