summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2020-02-27 11:53:59 +0100
committerErlang/OTP <otp@erlang.org>2020-02-27 11:53:59 +0100
commit887401f9be4923cf6c23e22802a62f2c8aa799e4 (patch)
treef5fbbaaee86f4a301987f664405636fe8e02270f
parent377fe6c430700a3b395cacfa0601f8d69415a44f (diff)
parent180c5e1782a94db9c6a7211bfe3a2fd159fb6111 (diff)
downloaderlang-887401f9be4923cf6c23e22802a62f2c8aa799e4.tar.gz
Merge branch 'rickard/dirty-low-prio-bug/ERL-1157/OTP-16446' into maint-20
* rickard/dirty-low-prio-bug/ERL-1157/OTP-16446: Fix low priority dirty execution
-rw-r--r--erts/emulator/beam/erl_process.c19
-rw-r--r--erts/emulator/test/scheduler_SUITE.erl77
2 files changed, 94 insertions, 2 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 3badc56043..521159d95e 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -10744,6 +10744,24 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
ASSERT(p); /* Wrong qmask in rq->flags? */
+#ifdef DEBUG
+ switch (((erts_aint32_t) 1) << ERTS_PSFLGS_GET_PRQ_PRIO(state)) {
+ case MAX_BIT:
+ ASSERT(qbit == MAX_BIT);
+ break;
+ case HIGH_BIT:
+ ASSERT(qbit == HIGH_BIT);
+ break;
+ case NORMAL_BIT:
+ case LOW_BIT:
+ ASSERT(qbit == NORMAL_BIT || qbit == LOW_BIT);
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+#endif
+
if (is_normal_sched) {
psflg_running = ERTS_PSFLG_RUNNING;
psflg_running_sys = ERTS_PSFLG_RUNNING_SYS;
@@ -10754,6 +10772,7 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
psflg_running = ERTS_PSFLG_DIRTY_RUNNING;
psflg_running_sys = ERTS_PSFLG_DIRTY_RUNNING_SYS;
psflg_band_mask = ~((erts_aint32_t) 0);
+ qbit = ((erts_aint32_t) 1) << ERTS_PSFLGS_GET_PRQ_PRIO(state);
}
if (!(state & ERTS_PSFLG_PROXY))
diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl
index af33de237c..c378e65602 100644
--- a/erts/emulator/test/scheduler_SUITE.erl
+++ b/erts/emulator/test/scheduler_SUITE.erl
@@ -57,7 +57,8 @@
scheduler_suspend_basic/1,
scheduler_suspend/1,
dirty_scheduler_threads/1,
- reader_groups/1]).
+ reader_groups/1,
+ otp_16446/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -72,7 +73,8 @@ all() ->
{group, scheduler_bind}, scheduler_threads,
scheduler_suspend_basic, scheduler_suspend,
dirty_scheduler_threads,
- reader_groups].
+ reader_groups,
+ otp_16446].
groups() ->
[{scheduler_bind, [],
@@ -1726,6 +1728,77 @@ reader_groups_map(CPUT, Groups) ->
erlang:system_flag(cpu_topology, Old),
lists:sort(Res).
+otp_16446(Config) when is_list(Config) ->
+ ct:timetrap({minutes, 1}),
+
+ process_flag(priority, high),
+
+ DIO = erlang:system_info(dirty_io_schedulers),
+ NoPrioProcs = 10*DIO,
+ io:format("DIO = ~p~nNoPrioProcs = ~p~n", [DIO, NoPrioProcs]),
+
+ DirtyLoop = fun Loop(P, N) ->
+ erts_debug:dirty_io(wait,1),
+ receive {get, From} -> From ! {P, N}
+ after 0 -> Loop(P,N+1)
+ end
+ end,
+
+ Spawn = fun SpawnLoop(_Prio, 0, Acc) ->
+ Acc;
+ SpawnLoop(Prio, N, Acc) ->
+ Pid = spawn_opt(fun () -> DirtyLoop(Prio, 0) end,
+ [link, {priority, Prio}]),
+ SpawnLoop(Prio, N-1, [Pid|Acc])
+ end,
+
+ Ns = Spawn(normal, NoPrioProcs, []),
+ Ls = Spawn(low, NoPrioProcs, []),
+
+ receive after 10000 -> ok end,
+
+ RequestInfo = fun (P) -> P ! {get, self()} end,
+ lists:foreach(RequestInfo, Ns),
+ lists:foreach(RequestInfo, Ls),
+
+ Collect = fun CollectFun(0, LLs, NLs) ->
+ {LLs, NLs};
+ CollectFun(N, LLs, NLs) ->
+ receive
+ {low, Calls} ->
+ CollectFun(N-1, LLs+Calls, NLs);
+ {normal, Calls} ->
+ CollectFun(N-1, LLs, NLs+Calls)
+ end
+ end,
+
+ {LLs, NLs} = Collect(2*NoPrioProcs, 0, 0),
+
+ %% expected ratio 0.125, but this is not especially exact...
+ Ratio = LLs / NLs,
+
+ io:format("LLs = ~p~nNLs = ~p~nRatio = ~p~n", [LLs, NLs, Ratio]),
+
+ true = Ratio > 0.05,
+ true = Ratio < 0.5,
+
+ WaitUntilDead = fun (P) ->
+ case is_process_alive(P) of
+ false ->
+ ok;
+ true ->
+ unlink(P),
+ exit(P, kill),
+ false = is_process_alive(P)
+ end
+ end,
+
+ lists:foreach(WaitUntilDead, Ns),
+ lists:foreach(WaitUntilDead, Ls),
+ Comment = "low/normal ratio: " ++ erlang:float_to_list(Ratio,[{decimals,4}]),
+ erlang:display(Comment),
+ {comment, Comment}.
+
%%
%% Utils
%%