summaryrefslogtreecommitdiff
path: root/erts
diff options
context:
space:
mode:
authorRickard Green <rickard@erlang.org>2020-05-07 21:44:11 +0200
committerRickard Green <rickard@erlang.org>2020-05-07 21:44:11 +0200
commitffc91c472da403cfd4cd9bf4047c550f57f85570 (patch)
tree57d28dc50c321d86e0baf6858b9ed36a0522da7a /erts
parent0a6cf7f2605db284939232cc6902036aaf772c9a (diff)
parent644e6bd1fba4388289d521ca9b10be08ec9383a3 (diff)
downloaderlang-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.c3
-rw-r--r--erts/emulator/test/process_SUITE.erl116
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;