File 0909-Fix-delayed-low-prio-system-tasks.patch of Package erlang

From 597178ab97b24b8f0e932235c640a67aa5046054 Mon Sep 17 00:00:00 2001
From: Rickard Green <rickard@erlang.org>
Date: Thu, 7 May 2020 15:17:08 +0200
Subject: [PATCH] Fix delayed low prio system tasks

---
 erts/emulator/beam/erl_process.c     |   3 +-
 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
@@ -63,7 +63,8 @@
          system_task_failed_enqueue/1,
 	 gc_request_when_gc_disabled/1,
 	 gc_request_blast_when_gc_disabled/1,
-         otp_16436/1]).
+         otp_16436/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]).
@@ -112,7 +113,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
@@ -2877,9 +2878,122 @@ gc_request_blast_when_gc_disabled(Config) when is_list(Config) ->
     unlink(P),
     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;
-- 
2.26.1

openSUSE Build Service is sponsored by