aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded/src
diff options
context:
space:
mode:
authorRickard Green <[email protected]>2013-12-07 00:19:05 +0100
committerRickard Green <[email protected]>2013-12-07 00:19:05 +0100
commit9232f50d4cbe7b051dfd3e83625de0b22536c4c4 (patch)
treef3c52ccc719a9df7a0714de05e2d1e9dde700df0 /erts/preloaded/src
parent3c00452a81dfde57f85c882029186cfa3c0d348d (diff)
parent9f1f0bff7f98d62f8406e5ecd76f6eb7c1a66ff3 (diff)
downloadotp-9232f50d4cbe7b051dfd3e83625de0b22536c4c4.tar.gz
otp-9232f50d4cbe7b051dfd3e83625de0b22536c4c4.tar.bz2
otp-9232f50d4cbe7b051dfd3e83625de0b22536c4c4.zip
Merge branch 'rickard/garbage_collect/OTP-11388'
* rickard/garbage_collect/OTP-11388: Parallel check_process_code when code_server purge a module Functionality for disabling garbage collection Use asynchronous check_process_code in code_parallel_SUITE Execution of system tasks in context of another process Conflicts: bootstrap/lib/kernel/ebin/hipe_unified_loader.beam erts/preloaded/ebin/erlang.beam erts/preloaded/ebin/erts_internal.beam
Diffstat (limited to 'erts/preloaded/src')
-rw-r--r--erts/preloaded/src/erlang.erl132
-rw-r--r--erts/preloaded/src/erts_internal.erl21
2 files changed, 143 insertions, 10 deletions
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index aa50ae7f76..a21da2ecc9 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -81,7 +81,8 @@
-export([binary_to_list/3, binary_to_term/1, binary_to_term/2]).
-export([bit_size/1, bitsize/1, bitstr_to_list/1, bitstring_to_list/1]).
-export([bump_reductions/1, byte_size/1, call_on_load_function/1]).
--export([cancel_timer/1, check_old_code/1, check_process_code/2, crc32/1]).
+-export([cancel_timer/1, check_old_code/1, check_process_code/2,
+ check_process_code/3, crc32/1]).
-export([crc32/2, crc32_combine/3, date/0, decode_packet/3]).
-export([delete_element/2]).
-export([delete_module/1, demonitor/1, demonitor/2, display/1]).
@@ -91,7 +92,7 @@
-export([float_to_binary/1, float_to_binary/2,
float_to_list/1, float_to_list/2]).
-export([fun_info/2, fun_to_list/1, function_exported/3]).
--export([garbage_collect/0, garbage_collect/1]).
+-export([garbage_collect/0, garbage_collect/1, garbage_collect/2]).
-export([garbage_collect_message_area/0, get/0, get/1, get_keys/1]).
-export([get_module_info/1, get_stacktrace/0, group_leader/0]).
-export([group_leader/2, halt/0, halt/1, halt/2, hash/2, hibernate/3]).
@@ -429,11 +430,71 @@ check_old_code(_Module) ->
erlang:nif_error(undefined).
%% check_process_code/2
--spec check_process_code(Pid, Module) -> boolean() when
+-spec check_process_code(Pid, Module) -> CheckResult when
Pid :: pid(),
- Module :: module().
-check_process_code(_Pid, _Module) ->
- erlang:nif_error(undefined).
+ Module :: module(),
+ CheckResult :: boolean().
+check_process_code(Pid, Module) ->
+ try
+ erlang:check_process_code(Pid, Module, [{allow_gc, true}])
+ catch
+ error:Error -> erlang:error(Error, [Pid, Module])
+ end.
+
+%% check_process_code/3
+-spec check_process_code(Pid, Module, OptionList) -> CheckResult | async when
+ Pid :: pid(),
+ Module :: module(),
+ RequestId :: term(),
+ Option :: {async, RequestId} | {allow_gc, boolean()},
+ OptionList :: [Option],
+ CheckResult :: boolean() | aborted.
+check_process_code(Pid, Module, OptionList) ->
+ try
+ {Async, AllowGC} = get_cpc_opts(OptionList, sync, true),
+ case Async of
+ {async, ReqId} ->
+ {priority, Prio} = erlang:process_info(erlang:self(),
+ priority),
+ erts_internal:request_system_task(Pid,
+ Prio,
+ {check_process_code,
+ ReqId,
+ Module,
+ AllowGC}),
+ async;
+ sync ->
+ case Pid == erlang:self() of
+ true ->
+ erts_internal:check_process_code(Module,
+ [{allow_gc, AllowGC}]);
+ false ->
+ {priority, Prio} = erlang:process_info(erlang:self(),
+ priority),
+ ReqId = erlang:make_ref(),
+ erts_internal:request_system_task(Pid,
+ Prio,
+ {check_process_code,
+ ReqId,
+ Module,
+ AllowGC}),
+ receive
+ {check_process_code, ReqId, CheckResult} ->
+ CheckResult
+ end
+ end
+ end
+ catch
+ error:Error -> erlang:error(Error, [Pid, Module, OptionList])
+ end.
+
+% gets async and allow_gc opts and verify valid option list
+get_cpc_opts([{async, _ReqId} = AsyncTuple | Options], _OldAsync, AllowGC) ->
+ get_cpc_opts(Options, AsyncTuple, AllowGC);
+get_cpc_opts([{allow_gc, AllowGC} | Options], Async, _OldAllowGC) ->
+ get_cpc_opts(Options, Async, AllowGC);
+get_cpc_opts([], Async, AllowGC) ->
+ {Async, AllowGC}.
%% crc32/1
-spec erlang:crc32(Data) -> non_neg_integer() when
@@ -793,10 +854,61 @@ garbage_collect() ->
erlang:nif_error(undefined).
%% garbage_collect/1
--spec garbage_collect(Pid) -> boolean() when
- Pid :: pid().
-garbage_collect(_Pid) ->
- erlang:nif_error(undefined).
+-spec garbage_collect(Pid) -> GCResult when
+ Pid :: pid(),
+ GCResult :: boolean().
+garbage_collect(Pid) ->
+ try
+ erlang:garbage_collect(Pid, [])
+ catch
+ error:Error -> erlang:error(Error, [Pid])
+ end.
+
+%% garbage_collect/2
+-spec garbage_collect(Pid, OptionList) -> GCResult | async when
+ Pid :: pid(),
+ RequestId :: term(),
+ Option :: {async, RequestId},
+ OptionList :: [Option],
+ GCResult :: boolean().
+garbage_collect(Pid, OptionList) ->
+ try
+ Async = get_gc_opts(OptionList, sync),
+ case Async of
+ {async, ReqId} ->
+ {priority, Prio} = erlang:process_info(erlang:self(),
+ priority),
+ erts_internal:request_system_task(Pid,
+ Prio,
+ {garbage_collect, ReqId}),
+ async;
+ sync ->
+ case Pid == erlang:self() of
+ true ->
+ erlang:garbage_collect();
+ false ->
+ {priority, Prio} = erlang:process_info(erlang:self(),
+ priority),
+ ReqId = erlang:make_ref(),
+ erts_internal:request_system_task(Pid,
+ Prio,
+ {garbage_collect,
+ ReqId}),
+ receive
+ {garbage_collect, ReqId, GCResult} ->
+ GCResult
+ end
+ end
+ end
+ catch
+ error:Error -> erlang:error(Error, [Pid, OptionList])
+ end.
+
+% gets async opt and verify valid option list
+get_gc_opts([{async, _ReqId} = AsyncTuple | Options], _OldAsync) ->
+ get_gc_opts(Options, AsyncTuple);
+get_gc_opts([], Async) ->
+ Async.
%% garbage_collect_message_area/0
-spec erlang:garbage_collect_message_area() -> boolean().
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
index 8a8cd52d64..c8e8e7e069 100644
--- a/erts/preloaded/src/erts_internal.erl
+++ b/erts/preloaded/src/erts_internal.erl
@@ -33,6 +33,10 @@
-export([port_command/3, port_connect/2, port_close/1,
port_control/3, port_call/3, port_info/1, port_info/2]).
+-export([request_system_task/3]).
+
+-export([check_process_code/2]).
+
%%
%% Await result of send to port
%%
@@ -139,3 +143,20 @@ port_info(_Result) ->
port_info(_Result, _Item) ->
erlang:nif_error(undefined).
+
+-spec request_system_task(Pid, Prio, Request) -> 'ok' when
+ Prio :: 'max' | 'high' | 'normal' | 'low',
+ Request :: {'garbage_collect', term()}
+ | {'check_process_code', term(), module(), boolean()},
+ Pid :: pid().
+
+request_system_task(_Pid, _Prio, _Request) ->
+ erlang:nif_error(undefined).
+
+-spec check_process_code(Module, OptionList) -> boolean() when
+ Module :: module(),
+ Option :: {allow_gc, boolean()},
+ OptionList :: [Option].
+check_process_code(_Module, _OptionList) ->
+ erlang:nif_error(undefined).
+