diff options
author | Rickard Green <rickard@erlang.org> | 2020-05-07 21:44:11 +0200 |
---|---|---|
committer | Rickard Green <rickard@erlang.org> | 2020-05-07 21:44:11 +0200 |
commit | ffc91c472da403cfd4cd9bf4047c550f57f85570 (patch) | |
tree | 57d28dc50c321d86e0baf6858b9ed36a0522da7a /erts | |
parent | 0a6cf7f2605db284939232cc6902036aaf772c9a (diff) | |
parent | 644e6bd1fba4388289d521ca9b10be08ec9383a3 (diff) | |
download | erlang-ffc91c472da403cfd4cd9bf4047c550f57f85570.tar.gz |
Merge branch 'rickard/low-prio-sys-task-delay-bufix-22/OTP-16642' into rickard/low-prio-sys-task-delay-bufix-23/OTP-16642
* rickard/low-prio-sys-task-delay-bufix-22/OTP-16642:
Fix delayed low prio system tasks
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/erl_process.c | 3 | ||||
-rw-r--r-- | erts/emulator/test/process_SUITE.erl | 116 |
2 files changed, 117 insertions, 2 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 47586256ca..a16263cea1 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -10191,13 +10191,14 @@ fetch_sys_task(Process *c_p, erts_aint32_t state, int *qmaskp, int *priop) *priop = PRIORITY_HIGH; break; case NORMAL_BIT: - if (!(qmask & PRIORITY_LOW) + if (!(qmask & LOW_BIT) || ++c_p->sys_task_qs->ncount <= RESCHEDULE_LOW) { qp = &c_p->sys_task_qs->q[PRIORITY_NORMAL]; *priop = PRIORITY_NORMAL; break; } c_p->sys_task_qs->ncount = 0; + qbit = LOW_BIT; /* Fall through */ case LOW_BIT: qp = &c_p->sys_task_qs->q[PRIORITY_LOW]; diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index f36e00d3ce..7b83857311 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -64,6 +64,7 @@ gc_request_when_gc_disabled/1, gc_request_blast_when_gc_disabled/1, otp_16436/1, + otp_16642/1, spawn_huge_arglist/1, spawn_request_bif/1, spawn_request_monitor_demonitor/1, @@ -135,7 +136,7 @@ groups() -> [no_priority_inversion, no_priority_inversion2, system_task_blast, system_task_on_suspended, system_task_failed_enqueue, gc_request_when_gc_disabled, gc_request_blast_when_gc_disabled, - otp_16436]}]. + otp_16436, otp_16642]}]. init_per_suite(Config) -> A0 = case application:start(sasl) of @@ -3863,8 +3864,121 @@ otp_16436(Config) when is_list(Config) -> exit(P, kill), ok. +otp_16642(Config) when is_list(Config) -> + %% + %% Whitebox testing... + %% + %% Ensure that low prio system tasks are interleaved with + %% normal prio system tasks as they should. + %% + process_flag(priority, high), + process_flag(scheduler, 1), + Pid = spawn_opt(fun () -> receive after infinity -> ok end end, + [link, {scheduler, 1}]), + ReqSTasks = fun (Prio, Start, Stop) -> + lists:foreach( + fun (N) -> + erts_internal:request_system_task( + Pid, + Prio, + {check_process_code, + {Prio, N}, + '__non_existing_module__'}) + end, + lists:seq(Start, Stop)) + end, + MkResList = fun (Prio, Start, Stop) -> + lists:map(fun (N) -> + {check_process_code, + {Prio, N}, + false} + end, + lists:seq(Start, Stop)) + end, + + %%% Test when normal queue clears first... + + ReqSTasks(low, 0, 1), + ReqSTasks(normal, 0, 10), + ReqSTasks(low, 2, 4), + ReqSTasks(normal, 11, 26), + + Msgs1 = recv_msgs(32), + io:format("Got test 1 messages: ~p~n", [Msgs1]), + + ExpMsgs1 = + MkResList(normal, 0, 7) + ++ MkResList(low, 0, 0) + ++ MkResList(normal, 8, 15) + ++ MkResList(low, 1, 1) + ++ MkResList(normal, 16, 23) + ++ MkResList(low, 2, 2) + ++ MkResList(normal, 24, 26) + ++ MkResList(low, 3, 4), + + case Msgs1 =:= ExpMsgs1 of + true -> + ok; + false -> + io:format("Expected test 1 messages ~p~n", + [ExpMsgs1]), + ct:fail(unexpected_messages) + end, + + receive Unexp1 -> ct:fail({unexpected_message, Unexp1}) + after 500 -> ok + end, + + io:format("Test 1 as expected~n", []), + + %%% Test when low queue clears first... + + ReqSTasks(low, 0, 1), + ReqSTasks(normal, 0, 20), + + Msgs2 = recv_msgs(23), + io:format("Got test 2 messages: ~p~n", [Msgs2]), + + ExpMsgs2 = + MkResList(normal, 0, 7) + ++ MkResList(low, 0, 0) + ++ MkResList(normal, 8, 15) + ++ MkResList(low, 1, 1) + ++ MkResList(normal, 16, 20), + + case Msgs2 =:= ExpMsgs2 of + true -> + ok; + false -> + io:format("Expected test 2 messages ~p~n", + [ExpMsgs2]), + ct:fail(unexpected_messages) + end, + + receive Unexp2 -> ct:fail({unexpected_message, Unexp2}) + after 500 -> ok + end, + + io:format("Test 2 as expected~n", []), + + unlink(Pid), + exit(Pid, kill), + false = is_process_alive(Pid), + ok. + %% Internal functions +recv_msgs(N) -> + recv_msgs(N, []). + +recv_msgs(0, Msgs) -> + lists:reverse(Msgs); +recv_msgs(N, Msgs) -> + receive + Msg -> + recv_msgs(N-1, [Msg|Msgs]) + end. + wait_until(Fun) -> case Fun() of true -> true; |