diff options
Diffstat (limited to 'lib/dtrace/src/dtrace.erl')
-rw-r--r-- | lib/dtrace/src/dtrace.erl | 247 |
1 files changed, 0 insertions, 247 deletions
diff --git a/lib/dtrace/src/dtrace.erl b/lib/dtrace/src/dtrace.erl deleted file mode 100644 index 71a1a3480e..0000000000 --- a/lib/dtrace/src/dtrace.erl +++ /dev/null @@ -1,247 +0,0 @@ --module(dtrace). - -%%% @doc The DTrace interface module -%%% -%%% This DTrace interface module, with the corresponding NIFs, should -%%% work on any operating system platform where user-space DTrace -%%% probes are supported. -%%% -%%% Use the `dtrace:init()' function to load the NIF shared library and -%%% to initialize library's private state. -%%% -%%% It is recommended that you use the `dtrace:p()' function to add -%%% DTrace probes to your Erlang code. This function can accept up to -%%% four integer arguments and four string arguments; the integer -%%% argument(s) must come before any string argument. For example: -%%% ``` -%%% 1> dtrace:put_tag("GGOOOAAALL!!!!!"). -%%% true -%%% 2> dtrace:init(). -%%% ok -%%% -%%% % % % Enable the DTrace probe using the 'dtrace' command. -%%% -%%% 3> dtrace:p(7, 8, 9, "one", "four"). -%%% true -%%% ''' -%%% -%%% Output from the example D script `user-probe.d' looks like: -%%% ``` -%%% <0.34.0> GGOOOAAALL!!!!! 7 8 9 0 'one' 'four' '' '' -%%% ''' -%%% -%%% If the expected type of variable is not present, e.g. integer when -%%% integer() is expected, or an I/O list when iolist() is expected, -%%% then the driver will ignore the user's input and use a default -%%% value of 0 or NULL, respectively. - --export([init/0, available/0, - user_trace_s1/1, % TODO: unify with pid & tag args like user_trace_i4s4 - p/0, p/1, p/2, p/3, p/4, p/5, p/6, p/7, p/8]). --export([put_utag/1, get_utag/0, get_utag_data/0, spread_utag/1, restore_utag/1]). - --export([scaff/0]). % Development only --export([user_trace_i4s4/9]). % Know what you're doing! - --type probe_arg() :: integer() | iolist(). --type int_p_arg() :: integer() | iolist() | undef. -%% The *_maybe() types use atom() instead of a stricter 'undef' -%% because user_trace_i4s4/9 is exposed to the outside world, and -%% because the driver will allow any atom to be used as a "not -%% present" indication, we'll allow any atom in the types. --type integer_maybe() :: integer() | atom(). --type iolist_maybe() :: iolist() | atom(). - --spec init() -> ok | {error, {term(), term()}}. - -init() -> - PrivDir = code:priv_dir(dtrace), - Lib = filename:join([PrivDir, "lib", "dtrace"]), - erlang:load_nif(Lib, 0). - -%%% -%%% NIF placeholders -%%% - --spec available() -> true | false. - -available() -> - erlang:nif_error(nif_not_loaded). - --spec user_trace_s1(iolist()) -> true | false | error | badarg. - -user_trace_s1(_Message) -> - erlang:nif_error(nif_not_loaded). - --spec user_trace_i4s4(iolist(), - integer_maybe(), integer_maybe(), - integer_maybe(), integer_maybe(), - iolist_maybe(), iolist_maybe(), - iolist_maybe(), iolist_maybe()) -> - true | false | error | badarg. - -user_trace_i4s4(_, _, _, _, _, _, _, _, _) -> - erlang:nif_error(nif_not_loaded). - -%%% -%%% Erlang support functions -%%% - --spec p() -> true | false | error | badarg. - -p() -> - user_trace_int(undef, undef, undef, undef, undef, undef, undef, undef). - --spec p(probe_arg()) -> true | false | error | badarg. - -p(I1) when is_integer(I1) -> - user_trace_int(I1, undef, undef, undef, undef, undef, undef, undef); -p(S1) -> - user_trace_int(undef, undef, undef, undef, S1, undef, undef, undef). - --spec p(probe_arg(), probe_arg()) -> true | false | error | badarg. - -p(I1, I2) when is_integer(I1), is_integer(I2) -> - user_trace_int(I1, I2, undef, undef, undef, undef, undef, undef); -p(I1, S1) when is_integer(I1) -> - user_trace_int(I1, undef, undef, undef, S1, undef, undef, undef); -p(S1, S2) -> - user_trace_int(undef, undef, undef, undef, S1, S2, undef, undef). - --spec p(probe_arg(), probe_arg(), probe_arg()) -> true | false | error | badarg. - -p(I1, I2, I3) when is_integer(I1), is_integer(I2), is_integer(I3) -> - user_trace_int(I1, I2, I3, undef, undef, undef, undef, undef); -p(I1, I2, S1) when is_integer(I1), is_integer(I2) -> - user_trace_int(I1, I2, undef, undef, S1, undef, undef, undef); -p(I1, S1, S2) when is_integer(I1) -> - user_trace_int(I1, undef, undef, undef, S1, S2, undef, undef); -p(S1, S2, S3) -> - user_trace_int(undef, undef, undef, undef, S1, S2, S3, undef). - --spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg()) -> - true | false | error | badarg. - -p(I1, I2, I3, I4) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) -> - user_trace_int(I1, I2, I3, I4, undef, undef, undef, undef); -p(I1, I2, I3, S1) when is_integer(I1), is_integer(I2), is_integer(I3) -> - user_trace_int(I1, I2, I3, undef, S1, undef, undef, undef); -p(I1, I2, S1, S2) when is_integer(I1), is_integer(I2) -> - user_trace_int(I1, I2, undef, undef, S1, S2, undef, undef); -p(I1, S1, S2, S3) when is_integer(I1) -> - user_trace_int(I1, undef, undef, undef, S1, S2, S3, undef); -p(S1, S2, S3, S4) -> - user_trace_int(undef, undef, undef, undef, S1, S2, S3, S4). - --spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), - probe_arg()) -> - true | false | error | badarg. - -p(I1, I2, I3, I4, S1) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) -> - user_trace_int(I1, I2, I3, I4, S1, undef, undef, undef); -p(I1, I2, I3, S1, S2) when is_integer(I1), is_integer(I2), is_integer(I3) -> - user_trace_int(I1, I2, I3, undef, S1, S2, undef, undef); -p(I1, I2, S1, S2, S3) when is_integer(I1), is_integer(I2) -> - user_trace_int(I1, I2, undef, undef, S1, S2, S3, undef); -p(I1, S1, S2, S3, S4) when is_integer(I1) -> - user_trace_int(I1, undef, undef, undef, S1, S2, S3, S4). - --spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), - probe_arg(), probe_arg()) -> - true | false | error | badarg. - -p(I1, I2, I3, I4, S1, S2) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) -> - user_trace_int(I1, I2, I3, I4, S1, S2, undef, undef); -p(I1, I2, I3, S1, S2, S3) when is_integer(I1), is_integer(I2), is_integer(I3) -> - user_trace_int(I1, I2, I3, undef, S1, S2, S3, undef); -p(I1, I2, S1, S2, S3, S4) when is_integer(I1), is_integer(I2) -> - user_trace_int(I1, I2, undef, undef, S1, S2, S3, S4). - --spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), - probe_arg(), probe_arg(), probe_arg()) -> - true | false | error | badarg. - -p(I1, I2, I3, I4, S1, S2, S3) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) -> - user_trace_int(I1, I2, I3, I4, S1, S2, S3, undef); -p(I1, I2, I3, S1, S2, S3, S4) when is_integer(I1), is_integer(I2), is_integer(I3) -> - user_trace_int(I1, I2, I3, undef, S1, S2, S3, S4). - --spec p(probe_arg(), probe_arg(), probe_arg(), probe_arg(), - probe_arg(), probe_arg(), probe_arg(), probe_arg()) -> - true | false | error | badarg. - -p(I1, I2, I3, I4, S1, S2, S3, S4) when is_integer(I1), is_integer(I2), is_integer(I3), is_integer(I4) -> - user_trace_int(I1, I2, I3, I4, S1, S2, S3, S4). - --spec user_trace_int(int_p_arg(), int_p_arg(), int_p_arg(), int_p_arg(), - int_p_arg(), int_p_arg(), int_p_arg(), int_p_arg()) -> - true | false | error | badarg. - -user_trace_int(I1, I2, I3, I4, S1, S2, S3, S4) -> - UTag = get_utag(), - try - user_trace_i4s4(UTag, I1, I2, I3, I4, S1, S2, S3, S4) - catch - error:nif_not_loaded -> - false - end. - --spec put_utag(undefined | iodata()) -> binary() | undefined. -put_utag(Data) -> - erlang:put_utag(unicode:characters_to_binary(Data)). - --spec get_utag() -> binary() | undefined. -get_utag() -> - erlang:get_utag(). - --spec get_utag_data() -> binary() | undefined. -%% Gets utag if set, otherwise the spread utag data from last incoming message -get_utag_data() -> - erlang:get_utag_data(). - --spec spread_utag(boolean()) -> true | {non_neg_integer(), binary() | []}. -%% Makes the utag behave as a sequential trace token, will spread with messages to be picked up by someone using -%% get_utag_data or get_drv_utag_data. -spread_utag(B) -> - erlang:spread_utag(B). - --spec restore_utag(true | {non_neg_integer(), binary() | []}) -> true. -restore_utag(T) -> - erlang:restore_utag(T). - - -%% Scaffolding to write tedious code: quick brute force and not 100% correct. - -scaff_int_args(N) -> - L = lists:sublist(["I1", "I2", "I3", "I4"], N), - [string:join(L, ", ")]. - -scaff_int_guards(N) -> - L = lists:sublist(["is_integer(I1)", "is_integer(I2)", "is_integer(I3)", - "is_integer(I4)"], N), - lists:flatten(string:join(L, ", ")). - -scaff_char_args(N) -> - L = lists:sublist(["S1", "S2", "S3", "S4"], N), - [string:join(L, ", ")]. - -scaff_fill(N) -> - [string:join(lists:duplicate(N, "undef"), ", ")]. - -scaff() -> - L = [begin - IntArgs = scaff_int_args(N_int), - IntGuards = scaff_int_guards(N_int), - IntFill = scaff_fill(4 - N_int), - CharArgs = scaff_char_args(N_char), - CharFill = scaff_fill(4 - N_char), - InArgs = string:join(IntArgs ++ CharArgs, ", "), - OutArgs = string:join(IntArgs ++ IntFill ++ CharArgs ++ CharFill, - ", "), - {N_int + N_char, - lists:flatten([io_lib:format("p(~s) when ~s ->\n", - [InArgs, IntGuards]), - io_lib:format(" user_trace_int(~s);\n", [OutArgs]) - ])} - end || N_int <- [0,1,2,3,4], N_char <- [0,1,2,3,4]], - [io:format("%%~p\n~s", [N, Str]) || {N, Str} <- lists:sort(L)]. |