diff options
Diffstat (limited to 'lib/kernel/src/seq_trace.erl')
-rw-r--r-- | lib/kernel/src/seq_trace.erl | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/lib/kernel/src/seq_trace.erl b/lib/kernel/src/seq_trace.erl new file mode 100644 index 0000000000..78c3040f21 --- /dev/null +++ b/lib/kernel/src/seq_trace.erl @@ -0,0 +1,126 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(seq_trace). + +-define(SEQ_TRACE_SEND, 1). %(1 << 0) +-define(SEQ_TRACE_RECEIVE, 2). %(1 << 1) +-define(SEQ_TRACE_PRINT, 4). %(1 << 2) +-define(SEQ_TRACE_TIMESTAMP, 8). %(1 << 3) + +-export([set_token/1, + set_token/2, + get_token/0, + get_token/1, + print/1, + print/2, + reset_trace/0, + set_system_tracer/1, + get_system_tracer/0]). + +%%--------------------------------------------------------------------------- + +-type flag() :: 'send' | 'receive' | 'print' | 'timestamp'. +-type component() :: 'label' | 'serial' | flag(). +-type value() :: non_neg_integer() + | {non_neg_integer(), non_neg_integer()} + | boolean(). +-type token_pair() :: {component(), value()}. + +%%--------------------------------------------------------------------------- + +-type token() :: [] | {integer(), boolean(), _, _, _}. +-spec set_token(token()) -> token() | 'ok'. + +set_token([]) -> + erlang:seq_trace(sequential_trace_token,[]); +set_token({Flags,Label,Serial,_From,Lastcnt}) -> + F = decode_flags(Flags), + set_token2([{label,Label},{serial,{Lastcnt, Serial}} | F]). + +%% We limit the label type to always be a small integer because erl_interface +%% expects that, the BIF can however "unofficially" handle atoms as well, and +%% atoms can be used if only Erlang nodes are involved + +-spec set_token(component(), value()) -> token_pair(). + +set_token(Type, Val) -> + erlang:seq_trace(Type, Val). + +-spec get_token() -> term(). + +get_token() -> + element(2,process_info(self(),sequential_trace_token)). + +-spec get_token(component()) -> token_pair(). + +get_token(Type) -> + erlang:seq_trace_info(Type). + +-spec print(term()) -> 'ok'. + +print(Term) -> + erlang:seq_trace_print(Term), + ok. + +-spec print(integer(), term()) -> 'ok'. + +print(Label, Term) when is_atom(Label) -> + erlang:error(badarg, [Label, Term]); +print(Label, Term) -> + erlang:seq_trace_print(Label, Term), + ok. + +-spec reset_trace() -> 'true'. + +reset_trace() -> + erlang:system_flag(1, 0). + +%% reset_trace(Pid) -> % this might be a useful function too + +-type tracer() :: pid() | port() | 'false'. + +-spec set_system_tracer(tracer()) -> tracer(). + +set_system_tracer(Pid) -> + erlang:system_flag(sequential_tracer, Pid). + +-spec get_system_tracer() -> tracer(). + +get_system_tracer() -> + element(2, erlang:system_info(sequential_tracer)). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% internal help functions +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +set_token2([{Type,Val}|T]) -> + erlang:seq_trace(Type, Val), + set_token2(T); +set_token2([]) -> + ok. + +decode_flags(Flags) -> + Print = (Flags band ?SEQ_TRACE_PRINT) > 0, + Send = (Flags band ?SEQ_TRACE_SEND) > 0, + Rec = (Flags band ?SEQ_TRACE_RECEIVE) > 0, + Ts = (Flags band ?SEQ_TRACE_TIMESTAMP) > 0, + [{print,Print},{send,Send},{'receive',Rec},{timestamp,Ts}]. |