diff options
author | Rickard Green <rickard@erlang.org> | 2020-05-07 15:17:08 +0200 |
---|---|---|
committer | Rickard Green <rickard@erlang.org> | 2020-05-07 17:51:32 +0200 |
commit | 597178ab97b24b8f0e932235c640a67aa5046054 (patch) | |
tree | 977113c2e1ce4ff26ed2098b3e1100c7820162c1 | |
parent | 7fe7fa3dde556b5b92522f8279d465bb52baf1f6 (diff) | |
download | erlang-597178ab97b24b8f0e932235c640a67aa5046054.tar.gz |
Fix delayed low prio system tasks
-rw-r--r-- | erts/emulator/beam/erl_process.c | 3 | ||||
-rw-r--r-- | erts/emulator/test/process_SUITE.erl | 118 |
2 files changed, 118 insertions, 3 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 1f464e2e5a..613d9bda87 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -10134,13 +10134,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 0cb0d6c1e2..3d287ed703 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -62,7 +62,8 @@ system_task_on_suspended/1, system_task_failed_enqueue/1, gc_request_when_gc_disabled/1, - gc_request_blast_when_gc_disabled/1]). + gc_request_blast_when_gc_disabled/1, + otp_16642/1]). -export([prio_server/2, prio_client/2, init/1, handle_event/2]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -110,7 +111,8 @@ groups() -> {system_task, [], [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]}]. + gc_request_when_gc_disabled, gc_request_blast_when_gc_disabled, + otp_16642]}]. init_per_suite(Config) -> A0 = case application:start(sasl) of @@ -2802,9 +2804,121 @@ gc_request_blast_when_gc_disabled(Config) when is_list(Config) -> receive {'DOWN', M, process, P, _Reason} -> ok end, 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; |