From 11e8e1e38bba355c2996d766b7d2893e441c1211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 18 Feb 2016 16:21:30 +0100 Subject: runtime_tools: Initial lttng tracing framework --- lib/runtime_tools/c_src/Makefile.in | 2 +- lib/runtime_tools/c_src/dyntrace.c | 313 ++++++++++++++++++++++++++++++++++++ lib/runtime_tools/src/dyntrace.erl | 27 ++++ 3 files changed, 341 insertions(+), 1 deletion(-) (limited to 'lib/runtime_tools') diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in index 70b48daf97..4530a83aee 100644 --- a/lib/runtime_tools/c_src/Makefile.in +++ b/lib/runtime_tools/c_src/Makefile.in @@ -91,7 +91,7 @@ $(OBJDIR): $(LIBDIR): -@mkdir -p $(LIBDIR) -$(OBJDIR)/%$(TYPEMARKER).o: %.c +$(OBJDIR)/%$(TYPEMARKER).o: %.c dyntrace_lttng.h $(V_CC) -c -o $@ $(ALL_CFLAGS) $< $(LIBDIR)/%$(TYPEMARKER).@DED_EXT@: $(OBJDIR)/%$(TYPEMARKER).o diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 0ef8eaf4d3..e0309e53e3 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -60,11 +60,25 @@ static ERL_NIF_TERM user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM a static ERL_NIF_TERM user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); + static ErlNifFunc nif_funcs[] = { {"available", 0, available}, {"user_trace_s1", 1, user_trace_s1}, {"user_trace_i4s4", 9, user_trace_i4s4}, {"user_trace_n", 10, user_trace_n} + {"enabled", 3, enabled}, + {"trace", 5, trace}, + {"trace", 6, trace}, + {"trace_procs", 6, trace_procs}, + {"trace_send", 6, trace_send}, + {"trace_receive", 6, trace_receive}, + {"trace_garbage_collection", 6, trace_garbage_collection} }; ERL_NIF_INIT(dyntrace, nif_funcs, load, NULL, NULL, NULL) @@ -76,6 +90,10 @@ static ERL_NIF_TERM atom_not_available; static ERL_NIF_TERM atom_badarg; static ERL_NIF_TERM atom_ok; +static ERL_NIF_TERM atom_trace; +static ERL_NIF_TERM atom_remove; +static ERL_NIF_TERM atom_discard; + static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { atom_true = enif_make_atom(env,"true"); @@ -85,6 +103,10 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_badarg = enif_make_atom(env,"badarg"); atom_ok = enif_make_atom(env,"ok"); + atom_trace = enif_make_atom(env,"trace"); + atom_remove = enif_make_atom(env,"remove"); + atom_discard = enif_make_atom(env,"discard"); + return 0; } @@ -123,3 +145,294 @@ static ERL_NIF_TERM user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar return atom_error; #endif } + +static ERL_NIF_TERM enabled(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ +#ifdef HAVE_USE_DTRACE + ErlNifPid to; + ASSERT(argc == 3); + /* Only generate trace events when probe is enabled */ + if (argv[0] == atom_seq_trace) { + if (!erlang_trace_seq_enabled()) + return atom_discard; + } else if (!erlang_trace_enabled()) { + return atom_discard; + } + + return atom_trace; +#else + int i; + erts_fprintf(stderr, "enabled:\r\n"); + for (i = 0; i < argc; i++) { + erts_fprintf(stderr, " %T\r\n", argv[i]); + } + return atom_trace; + return atom_remove; +#endif +} + +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + int i; + erts_fprintf(stderr, "trace:\r\n"); + for (i = 0; i < argc; i++) { + erts_fprintf(stderr, " %T\r\n", argv[i]); + } + +#ifdef HAVE_USE_DTRACE +#define BUFF_SIZE 1024 + size_t sz = BUFF_SIZE; + char buff[BUFF_SIZE]; + ASSERT(argc == 6); + + if (argv[0] == atom_seq_trace) { + if (erlang_trace_seq_enabled()) { + char *label = buff, + *seq_info = buff + BUFF_SIZE/4; + erts_snprintf(label, 1*BUFF_SIZE/4, "%T", argv[2]); + erts_snprintf(seq_info, 3*BUFF_SIZE/4, "%T", argv[3]); + erlang_trace_seq(label, seq_info); + } + } else { + char *event, p[DTRACE_TERM_BUF_SIZE], state, arg1, arg2, arg3; + + event = buff + BUFF_SIZE - sz; + sz -= enif_get_atom(env, argv[0], event, sz, ERL_NIF_LATIN1); + + state = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(state, sz, "%T", argv[1]); + + if (enif_is_pid(argv[2]) || enif_is_port(argv[2])) + dtrace_pid_str(argv[2], p); + else + p = NULL; + + arg1 = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(arg1, sz, "%T", argv[3]); + + if (argc == 6) { + arg2 = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(arg2, sz, "%T", argv[4]); + } else + args2 = NULL; + + erlang_trace(p, event, state, arg1, arg2); + + } +#endif + return atom_ok; +} +static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#ifdef HARDDEBUG + int i; + erts_fprintf(stderr, "trace:\r\n"); + for (i = 0; i < argc; i++) { + erts_fprintf(stderr, " %T\r\n", argv[i]); + } +#endif +#ifdef HAVE_USE_DTRACE +#define BUFF_SIZE 1024 + size_t sz = BUFF_SIZE; + char buff[BUFF_SIZE]; + ASSERT(argc == 6); + + if (argv[0] == atom_seq_trace) { + if (erlang_trace_seq_enabled()) { + char *label = buff, + *seq_info = buff + BUFF_SIZE/4; + erts_snprintf(label, 1*BUFF_SIZE/4, "%T", argv[2]); + erts_snprintf(seq_info, 3*BUFF_SIZE/4, "%T", argv[3]); + erlang_trace_seq(label, seq_info); + } + } else { + char *event, p[DTRACE_TERM_BUF_SIZE], state, arg1, arg2, arg3; + + event = buff + BUFF_SIZE - sz; + sz -= enif_get_atom(env, argv[0], event, sz, ERL_NIF_LATIN1); + + state = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(state, sz, "%T", argv[1]); + + if (enif_is_pid(argv[2]) || enif_is_port(argv[2])) + dtrace_pid_str(argv[2], p); + else + p = NULL; + + arg1 = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(arg1, sz, "%T", argv[3]); + + if (argc == 6) { + arg2 = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(arg2, sz, "%T", argv[4]); + } else + args2 = NULL; + + erlang_trace(p, event, state, arg1, arg2); + + } +#endif + return atom_ok; +} + + +static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#ifdef HARDDEBUG + int i; + erts_fprintf(stderr, "trace:\r\n"); + for (i = 0; i < argc; i++) { + erts_fprintf(stderr, " %T\r\n", argv[i]); + } +#endif +#ifdef HAVE_USE_DTRACE +#define BUFF_SIZE 1024 + size_t sz = BUFF_SIZE; + char buff[BUFF_SIZE]; + ASSERT(argc == 6); + + if (argv[0] == atom_seq_trace) { + if (erlang_trace_seq_enabled()) { + char *label = buff, + *seq_info = buff + BUFF_SIZE/4; + erts_snprintf(label, 1*BUFF_SIZE/4, "%T", argv[2]); + erts_snprintf(seq_info, 3*BUFF_SIZE/4, "%T", argv[3]); + erlang_trace_seq(label, seq_info); + } + } else { + char *event, p[DTRACE_TERM_BUF_SIZE], state, arg1, arg2, arg3; + + event = buff + BUFF_SIZE - sz; + sz -= enif_get_atom(env, argv[0], event, sz, ERL_NIF_LATIN1); + + state = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(state, sz, "%T", argv[1]); + + if (enif_is_pid(argv[2]) || enif_is_port(argv[2])) + dtrace_pid_str(argv[2], p); + else + p = NULL; + + arg1 = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(arg1, sz, "%T", argv[3]); + + if (argc == 6) { + arg2 = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(arg2, sz, "%T", argv[4]); + } else + args2 = NULL; + + erlang_trace(p, event, state, arg1, arg2); + + } +#endif + return atom_ok; +} + + +static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#ifdef HARDDEBUG + int i; + erts_fprintf(stderr, "trace:\r\n"); + for (i = 0; i < argc; i++) { + erts_fprintf(stderr, " %T\r\n", argv[i]); + } +#endif +#ifdef HAVE_USE_DTRACE +#define BUFF_SIZE 1024 + size_t sz = BUFF_SIZE; + char buff[BUFF_SIZE]; + ASSERT(argc == 6); + + if (argv[0] == atom_seq_trace) { + if (erlang_trace_seq_enabled()) { + char *label = buff, + *seq_info = buff + BUFF_SIZE/4; + erts_snprintf(label, 1*BUFF_SIZE/4, "%T", argv[2]); + erts_snprintf(seq_info, 3*BUFF_SIZE/4, "%T", argv[3]); + erlang_trace_seq(label, seq_info); + } + } else { + char *event, p[DTRACE_TERM_BUF_SIZE], state, arg1, arg2, arg3; + + event = buff + BUFF_SIZE - sz; + sz -= enif_get_atom(env, argv[0], event, sz, ERL_NIF_LATIN1); + + state = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(state, sz, "%T", argv[1]); + + if (enif_is_pid(argv[2]) || enif_is_port(argv[2])) + dtrace_pid_str(argv[2], p); + else + p = NULL; + + arg1 = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(arg1, sz, "%T", argv[3]); + + if (argc == 6) { + arg2 = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(arg2, sz, "%T", argv[4]); + } else + args2 = NULL; + + erlang_trace(p, event, state, arg1, arg2); + + } +#endif + return atom_ok; +} + +static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#ifdef HARDDEBUG + int i; + erts_fprintf(stderr, "trace:\r\n"); + for (i = 0; i < argc; i++) { + erts_fprintf(stderr, " %T\r\n", argv[i]); + } +#endif +#ifdef HAVE_USE_DTRACE +#define BUFF_SIZE 1024 + size_t sz = BUFF_SIZE; + char buff[BUFF_SIZE]; + ASSERT(argc == 6); + + if (argv[0] == atom_seq_trace) { + if (erlang_trace_seq_enabled()) { + char *label = buff, + *seq_info = buff + BUFF_SIZE/4; + erts_snprintf(label, 1*BUFF_SIZE/4, "%T", argv[2]); + erts_snprintf(seq_info, 3*BUFF_SIZE/4, "%T", argv[3]); + erlang_trace_seq(label, seq_info); + } + } else { + char *event, p[DTRACE_TERM_BUF_SIZE], state, arg1, arg2, arg3; + + event = buff + BUFF_SIZE - sz; + sz -= enif_get_atom(env, argv[0], event, sz, ERL_NIF_LATIN1); + + state = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(state, sz, "%T", argv[1]); + + if (enif_is_pid(argv[2]) || enif_is_port(argv[2])) + dtrace_pid_str(argv[2], p); + else + p = NULL; + + arg1 = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(arg1, sz, "%T", argv[3]); + + if (argc == 6) { + arg2 = buff + BUFF_SIZE - sz; + sz -= erts_snprintf(arg2, sz, "%T", argv[4]); + } else + args2 = NULL; + + erlang_trace(p, event, state, arg1, arg2); + + } +#endif + return atom_ok; +} + diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl index f7dbef6929..6822f51549 100644 --- a/lib/runtime_tools/src/dyntrace.erl +++ b/lib/runtime_tools/src/dyntrace.erl @@ -41,6 +41,15 @@ pn/1, pn/2, pn/3, pn/4, pn/5, pn/6, pn/7, pn/8, pn/9]). -export([put_tag/1, get_tag/0, get_tag_data/0, spread_tag/1, restore_tag/1]). +-export([enabled/3, + trace/5, + trace/6, + trace_procs/6, + trace_send/6, + trace_receive/6, + trace_garbage_collection/6 + ]). + -export([user_trace_i4s4/9]). % Know what you're doing! -on_load(on_load/0). @@ -125,6 +134,24 @@ user_trace_i4s4(_, _, _, _, _, _, _, _, _) -> user_trace_n(_, _, _, _, _, _, _, _, _, _) -> erlang:nif_error(nif_not_loaded). +enabled(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + +trace(_TracerState, _Label, _SeqTraceInfo, _, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace_procs(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). +trace_send(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). +trace_receive(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). +trace_garbage_collection(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + %%% %%% Erlang support functions %%% -- cgit v1.2.3