diff options
Diffstat (limited to 'erts/preloaded/src/erts_literal_area_collector.erl')
-rw-r--r-- | erts/preloaded/src/erts_literal_area_collector.erl | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/erts/preloaded/src/erts_literal_area_collector.erl b/erts/preloaded/src/erts_literal_area_collector.erl index 8a73ed1685..bb2ad6b919 100644 --- a/erts/preloaded/src/erts_literal_area_collector.erl +++ b/erts/preloaded/src/erts_literal_area_collector.erl @@ -62,39 +62,46 @@ msg_loop(Area, {Ongoing, NeedIReq} = OReqInfo, GcOutstnd, NeedGC) -> switch_area(); %% Process (_Pid) has completed the request... - {copy_literals, {Area, _GcAllowed, _Pid}, ok} when Ongoing == 1, - NeedIReq == [] -> + {copy_literals, {Area, _ReqType, _Pid}, ok} when Ongoing == 1, + NeedIReq == [] -> switch_area(); %% Last process completed... - {copy_literals, {Area, false, _Pid}, ok} -> + {copy_literals, {Area, init, _Pid}, ok} -> msg_loop(Area, check_send_copy_req(Area, Ongoing-1, NeedIReq), GcOutstnd, NeedGC); - {copy_literals, {Area, true, _Pid}, ok} when NeedGC == [] -> + {copy_literals, {Area, ReqType, _Pid}, ok} when NeedGC == [], + ReqType /= init -> msg_loop(Area, check_send_copy_req(Area, Ongoing-1, NeedIReq), GcOutstnd-1, []); - {copy_literals, {Area, true, _Pid}, ok} -> - send_copy_req(hd(NeedGC), Area, true), - msg_loop(Area, {Ongoing-1, NeedIReq}, GcOutstnd, tl(NeedGC)); + {copy_literals, {Area, ReqType, _Pid}, ok} when ReqType /= init -> + [{GCPid,GCWork} | NewNeedGC] = NeedGC, + send_copy_req(GCPid, Area, GCWork), + msg_loop(Area, {Ongoing-1, NeedIReq}, GcOutstnd, NewNeedGC); %% Process (Pid) failed to complete the request %% since it needs to garbage collect in order to %% complete the request... - {copy_literals, {Area, false, Pid}, need_gc} when GcOutstnd < ?MAX_GC_OUTSTND -> - send_copy_req(Pid, Area, true), + {copy_literals, {Area, init, Pid}, GCWork} when GcOutstnd + < ?MAX_GC_OUTSTND -> + send_copy_req(Pid, Area, GCWork), msg_loop(Area, OReqInfo, GcOutstnd+1, NeedGC); - {copy_literals, {Area, false, Pid}, need_gc} -> + {copy_literals, {Area, init, Pid}, GCWork} -> msg_loop(Area, check_send_copy_req(Area, Ongoing, NeedIReq), - GcOutstnd, [Pid|NeedGC]); + GcOutstnd, [{Pid,GCWork} | NeedGC]); %% Not handled message regarding the area that we %% currently are working with. Crash the VM so %% we notice this bug... - {copy_literals, {Area, _, _}, _} = Msg when erlang:is_reference(Area) -> + {copy_literals, {Area, _, _}, _} = Msg -> exit({not_handled_message, Msg}); {change_prio, From, Ref, Prio} -> change_prio(From, Ref, Prio), msg_loop(Area, OReqInfo, GcOutstnd, NeedGC); + {get_status, Ref, From} when is_pid(From); is_reference(From) -> + From ! {Ref, if Ongoing == 0 -> idle; true -> working end}, + msg_loop(Area, OReqInfo, GcOutstnd, NeedGC); + %% Unexpected garbage message. Get rid of it... _Ignore -> msg_loop(Area, OReqInfo, GcOutstnd, NeedGC) @@ -126,7 +133,7 @@ switch_area() -> check_send_copy_req(_Area, Ongoing, []) -> {Ongoing, []}; check_send_copy_req(Area, Ongoing, [Pid|Pids]) -> - send_copy_req(Pid, Area, false), + send_copy_req(Pid, Area, init), {Ongoing+1, Pids}. send_copy_reqs(Ps, Area, OReqLim) -> @@ -137,23 +144,23 @@ send_copy_reqs([], _Area, _OReqLim, 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, false), + send_copy_req(P, Area, init), send_copy_reqs(Ps, Area, OReqLim, N+1). -send_copy_req(P, Area, GC) -> - erts_literal_area_collector:send_copy_request(P, Area, GC). +send_copy_req(P, Area, How) -> + erts_literal_area_collector:send_copy_request(P, Area, How). -spec release_area_switch() -> boolean(). release_area_switch() -> erlang:nif_error(undef). %% Implemented in beam_bif_load.c --spec send_copy_request(To, AreaId, GcAllowed) -> 'ok' when +-spec send_copy_request(To, AreaId, How) -> 'ok' when To :: pid(), AreaId :: term(), - GcAllowed :: boolean(). + How :: 'init' | 'check_gc' | 'need_gc'. -send_copy_request(_To, _AreaId, _GcAllowed) -> +send_copy_request(_To, _AreaId, _How) -> erlang:nif_error(undef). %% Implemented in beam_bif_load.c change_prio(From, Ref, Prio) -> |