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.erl119
1 files changed, 92 insertions, 27 deletions
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index dfbd116d6e..90fd536b15 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -230,27 +230,32 @@
send |
'receive' |
procs |
+ ports |
call |
- silent |
+ arity |
return_to |
+ silent |
running |
exiting |
+ running_procs |
+ running_ports |
garbage_collection |
timestamp |
cpu_timestamp |
monotonic_timestamp |
strict_monotonic_timestamp |
- arity |
set_on_spawn |
set_on_first_spawn |
set_on_link |
set_on_first_link |
- {tracer, pid() | port()}.
+ {tracer, pid() | port()} |
+ {tracer, module(), term()}.
-type trace_info_item_result() ::
{traced, global | local | false | undefined} |
{match_spec, trace_match_spec() | false | undefined} |
{meta, pid() | port() | false | undefined | []} |
+ {meta, module(), term() } |
{meta_match_spec, trace_match_spec() | false | undefined} |
{call_count, non_neg_integer() | boolean() | undefined} |
{call_time, [{pid(), non_neg_integer(),
@@ -276,6 +281,7 @@
undefined |
{flags, [trace_info_flag()]} |
{tracer, pid() | port() | []} |
+ {tracer, module(), term()} |
trace_info_item_result() |
{all, [ trace_info_item_result() ] | false | undefined}.
@@ -1157,10 +1163,10 @@ map_size(_Map) ->
erlang:nif_error(undefined).
%% match_spec_test/3
--spec erlang:match_spec_test(P1, P2, P3) -> TestResult when
- P1 :: [term()] | tuple(),
- P2 :: term(),
- P3 :: table | trace,
+-spec erlang:match_spec_test(MatchAgainst, MatchSpec, Type) -> TestResult when
+ MatchAgainst :: [term()] | tuple(),
+ MatchSpec :: term(),
+ Type :: table | trace,
TestResult :: {ok, term(), [return_trace], [ {error | warning, string()} ]} | {error, [ {error | warning, string()} ]}.
match_spec_test(_P1, _P2, _P3) ->
erlang:nif_error(undefined).
@@ -1705,12 +1711,35 @@ time() ->
erlang:nif_error(undefined).
%% trace/3
--spec erlang:trace(PidSpec, How, FlagList) -> integer() when
- PidSpec :: pid() | existing | new | all,
+-spec erlang:trace(PidPortSpec, How, FlagList) -> integer() when
+ PidPortSpec :: pid() | port()
+ | all | processes | ports
+ | existing | existing_processes | existing_ports
+ | new | new_processes | new_ports,
How :: boolean(),
FlagList :: [trace_flag()].
-trace(_PidSpec, _How, _FlagList) ->
- erlang:nif_error(undefined).
+trace(PidPortSpec, How, FlagList) ->
+ %% Make sure that we have loaded the tracer module
+ case lists:keyfind(tracer, 1, FlagList) of
+ {tracer, Module, State} when erlang:is_atom(Module) ->
+ case erlang:module_loaded(Module) of
+ false ->
+ Module:enabled(trace_status, erlang:self(), State);
+ true ->
+ ok
+ end;
+ _ ->
+ ignore
+ end,
+
+ try erts_internal:trace(PidPortSpec, How, FlagList) of
+ Res -> Res
+ catch E:R ->
+ {_, [_ | CST]} = erlang:process_info(
+ erlang:self(), current_stacktrace),
+ erlang:raise(
+ E, R, [{?MODULE, trace, [PidPortSpec, How, FlagList], []} | CST])
+ end.
%% trace_delivered/1
-spec erlang:trace_delivered(Tracee) -> Ref when
@@ -1720,14 +1749,16 @@ trace_delivered(_Tracee) ->
erlang:nif_error(undefined).
%% trace_info/2
--spec erlang:trace_info(PidOrFunc, Item) -> Res when
- PidOrFunc :: pid() | new | {Module, Function, Arity} | on_load,
+-spec erlang:trace_info(PidPortFuncEvent, Item) -> Res when
+ PidPortFuncEvent :: pid() | port() | new | new_processes | new_ports
+ | {Module, Function, Arity} | on_load | send | 'receive',
Module :: module(),
Function :: atom(),
Arity :: arity(),
- Item :: flags | tracer | traced | match_spec | meta | meta_match_spec | call_count | call_time | all,
+ Item :: flags | tracer | traced | match_spec
+ | meta | meta_match_spec | call_count | call_time | all,
Res :: trace_info_return().
-trace_info(_PidOrFunc, _Item) ->
+trace_info(_PidPortFuncEvent, _Item) ->
erlang:nif_error(undefined).
%% trunc/1
@@ -2130,7 +2161,7 @@ process_flag(_Flag, _Value) ->
{message_queue_data, MQD :: message_queue_data()} |
{priority, Level :: priority_level()} |
{reductions, Number :: non_neg_integer()} |
- {registered_name, Atom :: atom()} |
+ {registered_name, [] | (Atom :: atom())} |
{sequential_trace_token, [] | (SequentialTraceToken :: term())} |
{stack_size, Size :: non_neg_integer()} |
{status, Status :: exiting | garbage_collecting | waiting | running | runnable | suspended} |
@@ -2226,9 +2257,9 @@ spawn_opt(_Tuple) ->
Input :: non_neg_integer(),
Output :: non_neg_integer();
(microstate_accounting) -> [MSAcc_Thread] | undefined when
- MSAcc_Thread :: #{ type => MSAcc_Thread_Type,
- id => MSAcc_Thread_Id,
- counters => MSAcc_Counters},
+ MSAcc_Thread :: #{ type := MSAcc_Thread_Type,
+ id := MSAcc_Thread_Id,
+ counters := MSAcc_Counters},
MSAcc_Thread_Type :: scheduler | async | aux,
MSAcc_Thread_Id :: non_neg_integer(),
MSAcc_Counters :: #{ MSAcc_Thread_State => non_neg_integer() },
@@ -2319,7 +2350,7 @@ subtract(_,_) ->
OldState :: preliminary | final | volatile;
%% These are deliberately not documented
(internal_cpu_topology, term()) -> term();
- (sequential_tracer, pid() | port() | false) -> pid() | port() | false;
+ (sequential_tracer, pid() | port() | {module(), term()} | false) -> pid() | port() | false;
(1,0) -> true.
system_flag(_Flag, _Value) ->
@@ -2350,29 +2381,63 @@ tl(_List) ->
[{[term()] | '_' ,[term()],[term()]}].
-spec erlang:trace_pattern(MFA, MatchSpec) -> non_neg_integer() when
- MFA :: trace_pattern_mfa(),
+ MFA :: trace_pattern_mfa() | send | 'receive',
MatchSpec :: (MatchSpecList :: trace_match_spec())
| boolean()
| restart
| pause.
-trace_pattern(_MFA, _MatchSpec) ->
- erlang:nif_error(undefined).
+trace_pattern(MFA, MatchSpec) ->
+ try erts_internal:trace_pattern(MFA, MatchSpec, []) of
+ Res -> Res
+ catch E:R ->
+ {_, [_ | CST]} = erlang:process_info(
+ erlang:self(), current_stacktrace),
+ erlang:raise(
+ E, R, [{?MODULE, trace_pattern, [MFA, MatchSpec], []} | CST])
+ end.
-type trace_pattern_flag() ::
global | local |
meta | {meta, Pid :: pid()} |
+ {meta, TracerModule :: module(), TracerState :: term()} |
call_count |
call_time.
--spec erlang:trace_pattern(MFA, MatchSpec, FlagList) -> non_neg_integer() when
+-spec erlang:trace_pattern(send, MatchSpec, []) -> non_neg_integer() when
+ MatchSpec :: (MatchSpecList :: trace_match_spec())
+ | boolean();
+ ('receive', MatchSpec, []) -> non_neg_integer() when
+ MatchSpec :: (MatchSpecList :: trace_match_spec())
+ | boolean();
+ (MFA, MatchSpec, FlagList) -> non_neg_integer() when
MFA :: trace_pattern_mfa(),
MatchSpec :: (MatchSpecList :: trace_match_spec())
| boolean()
| restart
| pause,
FlagList :: [ trace_pattern_flag() ].
-trace_pattern(_MFA, _MatchSpec, _FlagList) ->
- erlang:nif_error(undefined).
+trace_pattern(MFA, MatchSpec, FlagList) ->
+ %% Make sure that we have loaded the tracer module
+ case lists:keyfind(meta, 1, FlagList) of
+ {meta, Module, State} when erlang:is_atom(Module) ->
+ case erlang:module_loaded(Module) of
+ false ->
+ Module:enabled(trace_status, erlang:self(), State);
+ true ->
+ ok
+ end;
+ _ ->
+ ignore
+ end,
+
+ try erts_internal:trace_pattern(MFA, MatchSpec, FlagList) of
+ Res -> Res
+ catch E:R ->
+ {_, [_ | CST]} = erlang:process_info(
+ erlang:self(), current_stacktrace),
+ erlang:raise(
+ E, R, [{?MODULE, trace_pattern, [MFA, MatchSpec, FlagList], []} | CST])
+ end.
%% Shadowed by erl_bif_types: erlang:tuple_to_list/1
-spec tuple_to_list(Tuple) -> [term()] when