diff options
author | Erlang/OTP <otp@erlang.org> | 2021-03-29 15:12:49 +0200 |
---|---|---|
committer | Erlang/OTP <otp@erlang.org> | 2021-03-29 15:12:49 +0200 |
commit | ddcda22c41dfe5b595036a42ab5d42dcb1957b1b (patch) | |
tree | 8a5589447f599daacaebb28c9e5f4e53811f5c74 | |
parent | fd8d1e319f645edd9136ee86d48d609bd46cb4a5 (diff) | |
parent | ec5357bb04f13ef3e3206816dd477c54febd7c7d (diff) | |
download | erlang-ddcda22c41dfe5b595036a42ab5d42dcb1957b1b.tar.gz |
Merge branch 'rickard/multizero-timeout-in-timeout-fix/21/OTP-17253' into maint-21
* rickard/multizero-timeout-in-timeout-fix/21/OTP-17253:
erts: Fix bug in timer wheel at cancel during bump yield
erts: Tidy up some harmless code typos
Fix multi-zero timeout callback handling in timer wheel
-rw-r--r-- | erts/emulator/beam/erl_bif_info.c | 34 | ||||
-rw-r--r-- | erts/emulator/beam/time.c | 13 | ||||
-rw-r--r-- | erts/emulator/test/timer_bif_SUITE.erl | 26 |
3 files changed, 67 insertions, 6 deletions
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 51af067908..27bd734490 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -4416,6 +4416,28 @@ static void broken_halt_test(Eterm bif_arg_2) erts_exit(ERTS_DUMP_EXIT, "%T", bif_arg_2); } +static void +test_multizero_timeout_in_timeout3(void *vproc) +{ + Process *proc = (Process *) vproc; + ErtsMessage *mp = erts_alloc_message(0, NULL); + ERTS_DECL_AM(multizero_timeout_in_timeout_done); + erts_queue_message(proc, 0, mp, AM_multizero_timeout_in_timeout_done, am_system); + erts_proc_dec_refc(proc); +} + +static void +test_multizero_timeout_in_timeout2(void *vproc) +{ + erts_start_timer_callback(0, test_multizero_timeout_in_timeout3, vproc); +} + +static void +test_multizero_timeout_in_timeout(void *vproc) +{ + erts_start_timer_callback(0, test_multizero_timeout_in_timeout2, vproc); +} + BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2) { /* @@ -4740,6 +4762,18 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2) BIF_P->mbuf_sz += sz; BIF_RET(copy); } + else if (ERTS_IS_ATOM_STR("multizero_timeout_in_timeout", BIF_ARG_1)) { + Sint64 timeout; + if (term_to_Sint64(BIF_ARG_2, &timeout)) { + if (timeout < 0) + timeout = 0; + erts_proc_inc_refc(BIF_P); + erts_start_timer_callback((ErtsMonotonicTime) timeout, + test_multizero_timeout_in_timeout, + (void *) BIF_P); + BIF_RET(am_ok); + } + } } BIF_ERROR(BIF_P, BADARG); diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c index a3069e419a..73538dc375 100644 --- a/erts/emulator/beam/time.c +++ b/erts/emulator/beam/time.c @@ -316,7 +316,7 @@ struct ErtsTimerWheel_ { #define ERTS_TW_SLOT_AT_ONCE (-1) #define ERTS_TW_BUMP_LATER_WHEEL(TIW) \ - ((tiw)->pos + ERTS_TW_LATER_WHEEL_SLOT_SIZE >= (TIW)->later.pos) + ((TIW)->pos + ERTS_TW_LATER_WHEEL_SLOT_SIZE >= (TIW)->later.pos) static int bump_later_wheel(ErtsTimerWheel *tiw, int *yield_count_p); @@ -480,6 +480,8 @@ find_next_timeout(ErtsSchedulerData *esdp, ErtsTimerWheel *tiw) ERTS_HARD_DBG_CHK_WHEELS(tiw, 0); + ERTS_TW_ASSERT(tiw->at_once.nto == 0); + ERTS_TW_ASSERT(tiw->nto == tiw->soon.nto + tiw->later.nto); ERTS_TW_ASSERT(tiw->yield_slot == ERTS_TW_SLOT_INACTIVE); if (tiw->nto == 0) { /* no timeouts in wheel */ @@ -701,7 +703,8 @@ remove_timer(ErtsTimerWheel *tiw, ErtsTWheelTimer *p) if (slot < ERTS_TW_SOON_WHEEL_END_SLOT) { if (empty_slot && tiw->true_next_timeout_time - && p->timeout_pos == tiw->next_timeout_pos) { + && p->timeout_pos == tiw->next_timeout_pos + && tiw->yield_slot == ERTS_TW_SLOT_INACTIVE) { tiw->true_next_timeout_time = 0; } if (--tiw->soon.nto == 0) @@ -714,7 +717,8 @@ remove_timer(ErtsTimerWheel *tiw, ErtsTWheelTimer *p) ErtsMonotonicTime tpos = tiw->later.min_tpos; tpos &= ERTS_TW_LATER_WHEEL_POS_MASK; tpos -= ERTS_TW_LATER_WHEEL_SLOT_SIZE; - if (tpos == tiw->next_timeout_pos) + if (tpos == tiw->next_timeout_pos + && tiw->yield_slot == ERTS_TW_SLOT_INACTIVE) tiw->true_next_timeout_time = 0; } if (--tiw->later.nto == 0) { @@ -864,6 +868,8 @@ erts_bump_timers(ErtsTimerWheel *tiw, ErtsMonotonicTime curr_time) } if (tiw->pos >= bump_to) { + if (tiw->at_once.nto) + continue; ERTS_MSACC_POP_STATE_M_X(); break; } @@ -908,7 +914,6 @@ erts_bump_timers(ErtsTimerWheel *tiw, ErtsMonotonicTime curr_time) { ErtsMonotonicTime tmp_slots = bump_to - tiw->pos; - tmp_slots = (bump_to - tiw->pos); if (tmp_slots < ERTS_TW_SOON_WHEEL_SIZE) slots = (int) tmp_slots; else diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl index 4c25f067aa..71ab84edd6 100644 --- a/erts/emulator/test/timer_bif_SUITE.erl +++ b/erts/emulator/test/timer_bif_SUITE.erl @@ -31,7 +31,8 @@ same_time_yielding_with_cancel/1, same_time_yielding_with_cancel_other/1, % same_time_yielding_with_cancel_other_accessor/1, auto_cancel_yielding/1, - suspended_scheduler_timeout/1]). + suspended_scheduler_timeout/1, + multizero_timeout_in_timeout/1]). -include_lib("common_test/include/ct.hrl"). @@ -70,7 +71,8 @@ all() -> same_time_yielding_with_cancel_other, % same_time_yielding_with_cancel_other_accessor, auto_cancel_yielding, - suspended_scheduler_timeout]. + suspended_scheduler_timeout, + multizero_timeout_in_timeout]. %% Basic start_timer/3 functionality @@ -657,6 +659,26 @@ suspended_scheduler_timeout(Config) when is_list(Config) -> end, ok. +multizero_timeout_in_timeout(Config) when is_list(Config) -> + Timeout = 500, + MaxTimeoutDiff = 1000, + + %% We want to operate on the same timer wheel all the time... + process_flag(scheduler, erlang:system_info(schedulers_online)), + + erlang:send_after(5*(Timeout+MaxTimeoutDiff), self(), pling), + erlang:yield(), + Start = erlang:monotonic_time(), + erts_debug:set_internal_state(multizero_timeout_in_timeout, Timeout), + receive multizero_timeout_in_timeout_done -> ok end, + End = erlang:monotonic_time(), + Time = erlang:convert_time_unit(End-Start, native, millisecond), + io:format("Time=~p~n", [Time]), + true = Time < Timeout + MaxTimeoutDiff, + ok. + + + process_is_cleaned_up(P) when is_pid(P) -> undefined == erts_debug:get_internal_state({process_status, P}). |