File 1541-erts-Use-processes_iterator-0-processes_next-1.patch of Package erlang

From 5c30071c8c9adcf4e42b7cb4100253820dab468a Mon Sep 17 00:00:00 2001
From: lucioleKi <isabell@erlang.org>
Date: Wed, 11 Dec 2024 14:20:25 +0100
Subject: [PATCH] erts: Use `processes_iterator/0, processes_next/1`

---
 erts/emulator/beam/erl_ptab.c                 |   8 ++-
 erts/preloaded/ebin/erts_code_purger.beam     | Bin 5748 -> 5856 bytes
 .../ebin/erts_literal_area_collector.beam     | Bin 2252 -> 2432 bytes
 erts/preloaded/ebin/init.beam                 | Bin 27956 -> 27916 bytes
 erts/preloaded/src/erts_code_purger.erl       |  46 +++++++------
 .../src/erts_literal_area_collector.erl       |  63 ++++++++++--------
 erts/preloaded/src/init.erl                   |  45 ++++++-------
 7 files changed, 89 insertions(+), 73 deletions(-)

diff --git a/erts/emulator/beam/erl_ptab.c b/erts/emulator/beam/erl_ptab.c
index aec2938b61..5a88fe8e68 100644
--- a/erts/emulator/beam/erl_ptab.c
+++ b/erts/emulator/beam/erl_ptab.c
@@ -1478,7 +1478,12 @@ erts_ptab_processes_next(Process *c_p, ErtsPTab *ptab, Uint first)
     Eterm* hp;
     Eterm *hp_end;
 
+#ifdef DEBUG
+    int max_pids = 1;
+#else
     int max_pids = MAX(ERTS_BIF_REDS_LEFT(c_p), 1);
+#endif
+
     int num_pids = 0;
     int n = max_pids * ERTS_PTAB_REDS_MULTIPLIER;
     limit = MIN(ptab->r.o.max, first+n);
@@ -1500,7 +1505,7 @@ erts_ptab_processes_next(Process *c_p, ErtsPTab *ptab, Uint first)
         return THE_NON_VALUE;
     }
 
-    need = n * 2;
+    need = 3 + max_pids * 2;
     hp = HAlloc(c_p, need); /* we need two heap words for each id */
     hp_end = hp + need;
     res = make_list(hp);
@@ -1524,6 +1529,7 @@ erts_ptab_processes_next(Process *c_p, ErtsPTab *ptab, Uint first)
     scanned = (i - first) / ERTS_PTAB_REDS_MULTIPLIER + 1;
 
     res = TUPLE2(hp, make_small(i), res);
+    hp += 3;
     HRelease(c_p, hp_end, hp);
 
     BUMP_REDS(c_p, scanned);
diff --git a/erts/preloaded/src/erts_code_purger.erl b/erts/preloaded/src/erts_code_purger.erl
index ba2e278717..08294adf3b 100644
--- a/erts/preloaded/src/erts_code_purger.erl
+++ b/erts/preloaded/src/erts_code_purger.erl
@@ -120,7 +120,7 @@ do_purge(Mod, Reqs) ->
 	false ->
 	    {{false, false}, Reqs};
 	true ->
-	    {DidKill, NewReqs} = check_proc_code(erlang:processes(),
+	    {DidKill, NewReqs} = check_proc_code(erlang:processes_iterator(),
 						 Mod, true, Reqs),
 	    true = erts_internal:purge_module(Mod, complete),
 	    {{true, DidKill}, NewReqs}
@@ -144,7 +144,7 @@ do_soft_purge(Mod, Reqs) ->
 	false ->
 	    {true, Reqs};
 	true ->
-	    {PurgeOp, NewReqs} = check_proc_code(erlang:processes(),
+	    {PurgeOp, NewReqs} = check_proc_code(erlang:processes_iterator(),
 						 Mod, false, Reqs),
 	    {erts_internal:purge_module(Mod, PurgeOp), NewReqs}
     end.
@@ -172,7 +172,7 @@ do_finish_after_on_load(Mod, Keep, Reqs) ->
 		    Reqs;
 		true ->
 		    {_DidKill, NewReqs} =
-			check_proc_code(erlang:processes(),
+			check_proc_code(erlang:processes_iterator(),
 					Mod, true, Reqs),
 		    true = erts_internal:purge_module(Mod, complete),
 		    NewReqs
@@ -181,7 +181,7 @@ do_finish_after_on_load(Mod, Keep, Reqs) ->
 
 
 %%
-%% check_proc_code(Pids, Mod, Hard, Preqs) - Send asynchronous
+%% check_proc_code(ProcessesIterator, Mod, Hard, Preqs) - Send asynchronous
 %%   requests to all processes to perform a check_process_code
 %%   operation. Each process will check their own state and
 %%   reply with the result. If 'Hard' equals
@@ -208,7 +208,7 @@ do_finish_after_on_load(Mod, Keep, Reqs) ->
 		   waiting = [],
 		   killed = false}).
 
-check_proc_code(Pids, Mod, Hard, PReqs) ->
+check_proc_code(Iter, Mod, Hard, PReqs) ->
     Tag = erlang:make_ref(),
     OReqLim = erlang:system_info(outstanding_system_requests_limit),
     CpcS = #cpc_static{hard = Hard,
@@ -222,26 +222,26 @@ check_proc_code(Pids, Mod, Hard, PReqs) ->
                         OReqLim
                 end,
     KS = #cpc_kill{outstanding_limit = KillLimit},
-    cpc_receive(CpcS, cpc_make_requests(CpcS, KS, 0, Pids), KS, []).
+    cpc_receive(CpcS, cpc_make_requests(CpcS, KS, 0, Iter), KS, []).
 
 cpc_receive(#cpc_static{hard = true} = CpcS,
-	    {0, []},
+	    {0, none},
 	    #cpc_kill{outstanding = [], waiting = [], killed = Killed},
 	    PReqs) ->
     %% No outstanding cpc requests. We did a hard check, so result is
     %% whether or not we killed any processes...
     cpc_result(CpcS, PReqs, Killed);
-cpc_receive(#cpc_static{hard = false} = CpcS, {0, []}, _KillState, PReqs) ->
+cpc_receive(#cpc_static{hard = false} = CpcS, {0, none}, _KillState, PReqs) ->
     %% No outstanding cpc requests and we did a soft check that succeeded...
     cpc_result(CpcS, PReqs, complete);
-cpc_receive(#cpc_static{tag = Tag} = CpcS, {NoReq, PidsLeft} = ReqInfo,
+cpc_receive(#cpc_static{tag = Tag} = CpcS, {NoReq, Iter} = ReqInfo,
             KillState0, PReqs) ->
     receive
 	{check_process_code, {Tag, _Pid}, false} ->
 	    %% Process not referring the module; done with this process...
 	    cpc_receive(CpcS,
                         cpc_make_requests(CpcS, KillState0,
-                                          NoReq-1, PidsLeft),
+                                          NoReq-1, Iter),
                         KillState0,
                         PReqs);
 	{check_process_code, {Tag, Pid}, true} ->
@@ -258,7 +258,7 @@ cpc_receive(#cpc_static{tag = Tag} = CpcS, {NoReq, PidsLeft} = ReqInfo,
 		    KillState1 = cpc_sched_kill(Pid, KillState0),
 		    cpc_receive(CpcS,
                                 cpc_make_requests(CpcS, KillState1,
-                                                  NoReq-1, PidsLeft),
+                                                  NoReq-1, Iter),
                                 KillState1,
                                 PReqs)
 	    end;
@@ -266,7 +266,7 @@ cpc_receive(#cpc_static{tag = Tag} = CpcS, {NoReq, PidsLeft} = ReqInfo,
 	    KillState1 = cpc_handle_down(MonRef, KillState0),
 	    cpc_receive(CpcS,
                         cpc_make_requests(CpcS, KillState1,
-                                          NoReq, PidsLeft),
+                                          NoReq, Iter),
                         KillState1,
                         PReqs);
 	PReq when element(1, PReq) == purge;
@@ -341,16 +341,20 @@ cpc_request(#cpc_static{tag = Tag, module = Mod}, Pid) ->
     erts_internal:request_system_task(Pid, normal,
                                       {check_process_code, {Tag, Pid}, Mod}).
 
-cpc_make_requests(#cpc_static{}, #cpc_kill{}, NoCpcReqs, []) ->
-    {NoCpcReqs, []};
+cpc_make_requests(#cpc_static{}, #cpc_kill{}, NoCpcReqs, none) ->
+    {NoCpcReqs, none};
 cpc_make_requests(#cpc_static{oreq_limit = Limit},
                   #cpc_kill{no_outstanding = NoKillReqs},
-                  NoCpcReqs, Pids) when Limit =< NoCpcReqs + NoKillReqs ->
-    {NoCpcReqs, Pids};
+                  NoCpcReqs, Iter) when Limit =< NoCpcReqs + NoKillReqs ->
+    {NoCpcReqs, Iter};
 cpc_make_requests(#cpc_static{} = CpcS, #cpc_kill{} = KS,
-                  NoCpcReqs, [Pid|Pids]) ->
-    cpc_request(CpcS, Pid),
-    cpc_make_requests(CpcS, KS, NoCpcReqs+1, Pids).
+                  NoCpcReqs, Iter0) ->
+    case erlang:processes_next(Iter0) of
+        none -> {NoCpcReqs, none};
+        {Pid, Iter1} ->
+            cpc_request(CpcS, Pid),
+            cpc_make_requests(CpcS, KS, NoCpcReqs+1, Iter1)
+    end.
 
 change_prio(From, Ref, Prio) ->
     try
@@ -391,7 +395,7 @@ do_test_soft_purge(Mod, From, Ref, Reqs) ->
 	    _ = test_progress(continued, From, Ref, TestRes),
 	    {true, Reqs};
 	true ->
-	    {PurgeOp, NewReqs} = check_proc_code(erlang:processes(),
+	    {PurgeOp, NewReqs} = check_proc_code(erlang:processes_iterator(),
 						 Mod, false, Reqs),
 	    _ = test_progress(continued, From, Ref, TestRes),
 	    {erts_internal:purge_module(Mod, PurgeOp), NewReqs}
@@ -405,7 +409,7 @@ do_test_hard_purge(Mod, From, Ref, Reqs) ->
 	    _ = test_progress(continued, From, Ref, TestRes),
 	    {{false, false}, Reqs};
 	true ->
-	    {DidKill, NewReqs} = check_proc_code(erlang:processes(),
+	    {DidKill, NewReqs} = check_proc_code(erlang:processes_iterator(),
 						 Mod, true, Reqs),
 	    _ = test_progress(continued, From, Ref, TestRes),
 	    true = erts_internal:purge_module(Mod, complete),
diff --git a/erts/preloaded/src/erts_literal_area_collector.erl b/erts/preloaded/src/erts_literal_area_collector.erl
index 40a3f26859..57d66ee830 100644
--- a/erts/preloaded/src/erts_literal_area_collector.erl
+++ b/erts/preloaded/src/erts_literal_area_collector.erl
@@ -37,7 +37,7 @@
 %%
 start() ->
     process_flag(trap_exit, true),
-    msg_loop(undefined, {0, []}, 0, []).
+    msg_loop(undefined, {0, none}, 0, []).
 
 %%
 %% The VM will send us a 'copy_literals' message
@@ -63,16 +63,17 @@ msg_loop(Area, {Ongoing, NeedIReq} = OReqInfo, GcOutstnd, NeedGC) ->
 	    switch_area();
 
 	%% Process (_Pid) has completed the request...
-	{copy_literals, {Area, _ReqType, _Pid}, ok} when Ongoing == 1,
-                                                         NeedIReq == [] ->
-	    switch_area(); %% Last process completed...
 	{copy_literals, {Area, init, _Pid}, ok} ->
-	    msg_loop(Area, check_send_copy_req(Area, Ongoing-1, NeedIReq),
-                     GcOutstnd, NeedGC);
+            case check_send_copy_req(Area, Ongoing-1, NeedIReq) of
+                {0, none} -> switch_area(); %% Last process completed...
+                NewOReqInfo -> msg_loop(Area, NewOReqInfo, GcOutstnd, NeedGC)
+            end;
 	{copy_literals, {Area, ReqType, _Pid}, ok} when NeedGC == [],
                                                         ReqType /= init ->
-	    msg_loop(Area, check_send_copy_req(Area, Ongoing-1, NeedIReq),
-                     GcOutstnd-1, []);
+            case check_send_copy_req(Area, Ongoing-1, NeedIReq) of
+                {0, none} -> switch_area(); %% Last process completed...
+                NewOReqInfo -> msg_loop(Area, NewOReqInfo, GcOutstnd-1, [])
+            end;
 	{copy_literals, {Area, ReqType, _Pid}, ok} when ReqType /= init ->
             [{GCPid,GCWork} | NewNeedGC] = NeedGC,
 	    send_copy_req(GCPid, Area, GCWork),
@@ -117,7 +118,7 @@ switch_area() ->
     case Res of
 	false ->
 	    %% No more areas to handle...
-	    msg_loop(undefined, {0, []}, 0, []);
+	    msg_loop(undefined, {0, none}, 0, []);
 	true ->
 	    %% Send requests to OReqLim processes to copy
 	    %% all live data they have referring to the
@@ -126,27 +127,35 @@ switch_area() ->
             %% processes when responses comes back until
             %% all processes have been handled...
 	    Area = make_ref(),
-            Pids = erlang:processes(),
+            Iter = erlang:processes_iterator(),
             OReqLim = erlang:system_info(outstanding_system_requests_limit),
-	    msg_loop(Area, send_copy_reqs(Pids, Area, OReqLim), 0, [])
+	    msg_loop(Area, send_copy_reqs(Iter, Area, OReqLim), 0, [])
     end.
 
-check_send_copy_req(_Area, Ongoing, []) ->
-    {Ongoing, []};
-check_send_copy_req(Area, Ongoing, [Pid|Pids]) ->
-    send_copy_req(Pid, Area, init),
-    {Ongoing+1, Pids}.
-
-send_copy_reqs(Ps, Area, OReqLim) ->
-    send_copy_reqs(Ps, Area, OReqLim, 0).
-
-send_copy_reqs([], _Area, _OReqLim, N) ->
-    {N, []};
-send_copy_reqs(Ps, _Area, OReqLim, N) when N >= OReqLim ->
-    {N, Ps};
-send_copy_reqs([P|Ps], Area, OReqLim, N) ->
-    send_copy_req(P, Area, init),
-    send_copy_reqs(Ps, Area, OReqLim, N+1).
+check_send_copy_req(_Area, Ongoing, none) ->
+    {Ongoing, none};
+check_send_copy_req(Area, Ongoing, Iter0) ->
+    case erlang:processes_next(Iter0) of
+        none ->
+            {Ongoing, none};
+        {Pid, Iter1} ->
+            send_copy_req(Pid, Area, init),
+            {Ongoing+1, Iter1}
+    end.
+
+send_copy_reqs(Iter, Area, OReqLim) ->
+    send_copy_reqs(Iter, Area, OReqLim, 0).
+
+send_copy_reqs(Iter, _Area, OReqLim, N) when N >= OReqLim ->
+    {N, Iter};
+send_copy_reqs(Iter0, Area, OReqLim, N) ->
+    case erlang:processes_next(Iter0) of
+        none ->
+            {N, none};
+        {Pid, Iter1} ->
+            send_copy_req(Pid, Area, init),
+            send_copy_reqs(Iter1, Area, OReqLim, N+1)
+    end.
 
 send_copy_req(P, Area, How) ->
     erts_literal_area_collector:send_copy_request(P, Area, How).
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index 0a30fda9bb..79f557bf75 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -952,7 +952,7 @@ clear_system(Unload,BootPid,State) ->
     Logger = get_logger(State#state.kernel),
     shutdown_pids(Heart,Logger,BootPid,State),
     Unload andalso unload(Heart),
-    kill_em([Logger]),
+    exit(Logger,kill),
     Unload andalso do_unload([logger_server]).
 
 flush() ->
@@ -1065,30 +1065,27 @@ resend(_) ->
 %%
 %% Kill all existing pids in the system (except init and heart).
 kill_all_pids(Heart,Logger) ->
-    case get_pids(Heart,Logger) of
-	[] ->
-	    ok;
-	Pids ->
-	    kill_em(Pids),
-	    kill_all_pids(Heart,Logger)  % Continue until all are really killed.
+    Iter = erlang:processes_iterator(),
+    case kill_pids(Heart, Logger, Iter, false) of
+        true ->
+            %% Continue until all are really killed.
+            kill_all_pids(Heart, Logger);
+        false ->
+            ok
+    end.
+
+kill_pids(Heart, Logger, Iter0, MorePids) ->
+    case erlang:processes_next(Iter0) of
+        none -> MorePids;
+        {Pid, Iter1} ->
+            case erts_internal:is_system_process(Pid) orelse
+                lists:member(Pid, [Heart, Logger, self()]) of
+                true -> kill_pids(Heart, Logger, Iter1, MorePids);
+                false ->
+                    exit(Pid, kill),
+                    kill_pids(Heart, Logger, Iter1, true)
+            end
     end.
-    
-%% All except system processes.
-get_pids(Heart,Logger) ->
-    Pids = [P || P <- processes(), not erts_internal:is_system_process(P)],
-    delete(Heart,Logger,self(),Pids).
-
-delete(Heart,Logger,Init,[Heart|Pids]) -> delete(Heart,Logger,Init,Pids);
-delete(Heart,Logger,Init,[Logger|Pids])  -> delete(Heart,Logger,Init,Pids);
-delete(Heart,Logger,Init,[Init|Pids])  -> delete(Heart,Logger,Init,Pids);
-delete(Heart,Logger,Init,[Pid|Pids])   -> [Pid|delete(Heart,Logger,Init,Pids)];
-delete(_,_,_,[])                  -> [].
-    
-kill_em([Pid|Pids]) ->
-    exit(Pid,kill),
-    kill_em(Pids);
-kill_em([]) ->
-    ok.
 
 %%
 %% Kill all existing ports in the system (except the heart port),
-- 
2.43.0

openSUSE Build Service is sponsored by