aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded/src/erts_code_purger.erl
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2016-07-27 19:45:41 +0200
committerRickard Green <[email protected]>2016-08-26 15:50:22 +0200
commit2fe03e832adb11c50bcfc62679cf17779b284124 (patch)
treeb338e0f77a25091ebfd3e2c183c33edb219ff42c /erts/preloaded/src/erts_code_purger.erl
parentaeb645a709b73e1bda0281f87dda2af3ce92dfe7 (diff)
downloadotp-2fe03e832adb11c50bcfc62679cf17779b284124.tar.gz
otp-2fe03e832adb11c50bcfc62679cf17779b284124.tar.bz2
otp-2fe03e832adb11c50bcfc62679cf17779b284124.zip
Reclaim literal area after purge has completed
Diffstat (limited to 'erts/preloaded/src/erts_code_purger.erl')
-rw-r--r--erts/preloaded/src/erts_code_purger.erl49
1 files changed, 44 insertions, 5 deletions
diff --git a/erts/preloaded/src/erts_code_purger.erl b/erts/preloaded/src/erts_code_purger.erl
index d1e64342e0..f9208624b7 100644
--- a/erts/preloaded/src/erts_code_purger.erl
+++ b/erts/preloaded/src/erts_code_purger.erl
@@ -28,7 +28,36 @@
start() ->
register(erts_code_purger, self()),
process_flag(trap_exit, true),
- loop().
+ try
+ %% Pass bad arguments to copy_literals() in
+ %% order to determine purge strategy used
+ %% by the VM...
+ Res = erts_internal:copy_literals(4711, badarg),
+ exit({copy_literals_returned, Res})
+ catch
+ error : badarg -> %% VM use old purge strategy
+ old_loop();
+ error : notsup -> %% VM use new purge strategy
+ loop();
+ Type : Reason ->
+ %% This should not be possible...
+ exit({"Unexpected copy_literals() behaviour",
+ {Type, Reason}})
+ end.
+
+old_loop() ->
+ _ = receive
+ {purge,Mod,From,Ref} when is_atom(Mod), is_pid(From) ->
+ Res = do_old_purge(Mod),
+ From ! {reply, purge, Res, Ref};
+
+ {soft_purge,Mod,From,Ref} when is_atom(Mod), is_pid(From) ->
+ Res = do_old_soft_purge(Mod),
+ From ! {reply, soft_purge, Res, Ref};
+
+ _Other -> ignore
+ end,
+ old_loop().
loop() ->
_ = receive
@@ -61,7 +90,7 @@ purge(Mod) when is_atom(Mod) ->
end.
-do_purge(Mod) ->
+do_old_purge(Mod) ->
case erts_internal:copy_literals(Mod, true) of
false ->
{false, false};
@@ -72,6 +101,11 @@ do_purge(Mod) ->
{WasPurged, DidKill}
end.
+do_purge(Mod) ->
+ DidKill = check_proc_code(erlang:processes(), Mod, true),
+ WasPurged = erts_internal:purge_module(Mod),
+ {WasPurged, DidKill}.
+
%% soft_purge(Module)
%% Purge old code only if no procs remain that run old code.
%% Return true in that case, false if procs remain (in this
@@ -86,7 +120,7 @@ soft_purge(Mod) ->
end.
-do_soft_purge(Mod) ->
+do_old_soft_purge(Mod) ->
case erts_internal:copy_literals(Mod, true) of
false ->
true;
@@ -102,6 +136,12 @@ do_soft_purge(Mod) ->
end
end.
+do_soft_purge(Mod) ->
+ case check_proc_code(erlang:processes(), Mod, false) of
+ false -> false;
+ true -> erts_internal:purge_module(Mod)
+ end.
+
%%
%% check_proc_code(Pids, Mod, Hard) - Send asynchronous
%% requests to all processes to perform a check_process_code
@@ -283,8 +323,7 @@ cpc_sched_kill(Pid,
cpc_request(#cpc_static{tag = Tag, module = Mod}, Pid, AllowGc) ->
erts_internal:check_process_code(Pid, Mod, [{async, {Tag, Pid, AllowGc}},
- {allow_gc, AllowGc},
- {copy_literals, true}]).
+ {allow_gc, AllowGc}]).
cpc_request_gc(CpcS, [Pid|Pids]) ->
cpc_request(CpcS, Pid, true),