aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded/src/erlang.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/preloaded/src/erlang.erl')
-rw-r--r--erts/preloaded/src/erlang.erl165
1 files changed, 145 insertions, 20 deletions
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index a969ef91dc..0ed677c3d8 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]).
@@ -361,15 +362,25 @@ binary_to_list(_Binary, _Start, _Stop) ->
%% binary_to_term/1
-spec binary_to_term(Binary) -> term() when
Binary :: ext_binary().
-binary_to_term(_Binary) ->
- erlang:nif_error(undefined).
+binary_to_term(Binary) ->
+ %% This BIF may throw badarg while trapping
+ try
+ erts_internal:binary_to_term(Binary)
+ catch
+ error:Reason -> erlang:error(Reason,[Binary])
+ end.
%% binary_to_term/2
-spec binary_to_term(Binary, Opts) -> term() when
Binary :: ext_binary(),
Opts :: [safe].
-binary_to_term(_Binary, _Opts) ->
- erlang:nif_error(undefined).
+binary_to_term(Binary, Opts) ->
+ %% This BIF may throw badarg while trapping
+ try
+ erts_internal:binary_to_term(Binary,Opts)
+ catch
+ error:Reason -> erlang:error(Reason,[Binary,Opts])
+ end.
%% bit_size/1
%% Shadowed by erl_bif_types: erlang:bit_size/1
@@ -429,11 +440,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 +864,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().
@@ -1073,8 +1195,8 @@ module_loaded(_Module) ->
%% monitor/2
-spec monitor(Type, Item) -> MonitorRef when
Type :: process,
- Item :: pid() | Module | {Module, Node},
- Module :: module(),
+ Item :: pid() | RegName | {RegName, Node},
+ RegName :: module(),
Node :: node(),
MonitorRef :: reference().
monitor(_Type, _Item) ->
@@ -1715,15 +1837,15 @@ nodes(_Arg) ->
erlang:nif_error(undefined).
-spec open_port(PortName, PortSettings) -> port() when
- PortName :: {spawn, Command :: string()} |
- {spawn_driver, Command :: [byte()]} |
+ PortName :: {spawn, Command :: string() | binary()} |
+ {spawn_driver, Command :: string() | binary()} |
{spawn_executable, FileName :: file:name() } |
{fd, In :: non_neg_integer(), Out :: non_neg_integer()},
PortSettings :: [Opt],
Opt :: {packet, N :: 1 | 2 | 4}
| stream
| {line, L :: non_neg_integer()}
- | {cd, Dir :: string()}
+ | {cd, Dir :: string() | binary()}
| {env, Env :: [{Name :: string(), Val :: string() | false}]}
| {args, [string() | binary()]}
| {arg0, string() | binary()}
@@ -2099,13 +2221,14 @@ tuple_to_list(_Tuple) ->
(creation) -> integer();
(debug_compiled) -> boolean();
(dist) -> binary();
+ (dist_buf_busy_limit) -> non_neg_integer();
(dist_ctrl) -> {Node :: node(),
ControllingEntity :: port() | pid()};
(driver_version) -> string();
(dynamic_trace) -> none | dtrace | systemtap;
(dynamic_trace_probes) -> boolean();
(elib_malloc) -> false;
- (dist_buf_busy_limit) -> non_neg_integer();
+ (ets_limit) -> pos_integer();
(fullsweep_after) -> {fullsweep_after, non_neg_integer()};
(garbage_collection) -> [{atom(), integer()}];
(heap_sizes) -> [non_neg_integer()];
@@ -3498,6 +3621,8 @@ mk_res_list([]) ->
mk_res_list([Alloc | Rest]) ->
[{Alloc, []} | mk_res_list(Rest)].
+insert_instance(I, N, Rest) when erlang:is_atom(N) ->
+ [{N, I} | Rest];
insert_instance(I, N, []) ->
[{instance, N, I}];
insert_instance(I, N, [{instance, M, _}|_] = Rest) when N < M ->