aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2016-03-17 18:21:09 +0100
committerBjörn-Egil Dahlberg <[email protected]>2016-04-29 18:31:35 +0200
commit262d3d9291d5dcd2530d5a0d3170e9dc0345a002 (patch)
tree82d111e2457979f5ea061e6c96f9d4a6d7d9ad8e
parenta4811133b70370e54162d256d61ef4c084e1f4fe (diff)
downloadotp-262d3d9291d5dcd2530d5a0d3170e9dc0345a002.tar.gz
otp-262d3d9291d5dcd2530d5a0d3170e9dc0345a002.tar.bz2
otp-262d3d9291d5dcd2530d5a0d3170e9dc0345a002.zip
runtime_tools: Extend 'enabled' tracer callbacks
Adds the following capabilities to dyntrace * enabled_procs/3 * enabled_ports/3 * enabled_running/3 * enabled_call/3 * enabled_send/3 * enabled_receive/3 * enabled_garbage_collection/3
-rw-r--r--lib/runtime_tools/c_src/dyntrace.c232
-rw-r--r--lib/runtime_tools/c_src/dyntrace_lttng.h3
-rw-r--r--lib/runtime_tools/src/dyntrace.erl43
3 files changed, 171 insertions, 107 deletions
diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c
index 9db26a6c4c..58a20691f7 100644
--- a/lib/runtime_tools/c_src/dyntrace.c
+++ b/lib/runtime_tools/c_src/dyntrace.c
@@ -68,6 +68,8 @@ static ERL_NIF_TERM user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
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[]);
+
+#ifdef HAVE_USE_LTTNG
static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM trace_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM trace_running(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -76,21 +78,40 @@ 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 ERL_NIF_TERM enabled_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM enabled_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM enabled_running(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM enabled_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM enabled_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM enabled_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM enabled_garbage_collection(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+#endif
+
+
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},
+ {"user_trace_n", 10, user_trace_n},
+#ifdef HAVE_USE_LTTNG
{"trace_procs", 6, trace_procs},
{"trace_ports", 6, trace_ports},
{"trace_running", 6, trace_running},
{"trace_call", 6, trace_call},
{"trace_send", 6, trace_send},
{"trace_receive", 6, trace_receive},
- {"trace_garbage_collection", 6, trace_garbage_collection}
+ {"trace_garbage_collection", 6, trace_garbage_collection},
+ {"enabled_procs", 3, enabled_procs},
+ {"enabled_ports", 3, enabled_ports},
+ {"enabled_running", 3, enabled_running},
+ {"enabled_call", 3, enabled_call},
+ {"enabled_send", 3, enabled_send},
+ {"enabled_receive", 3, enabled_receive},
+ {"enabled_garbage_collection", 3, enabled_garbage_collection},
+#endif
+ {"enabled", 3, enabled},
+ {"trace", 5, trace},
+ {"trace", 6, trace}
};
ERL_NIF_INIT(dyntrace, nif_funcs, load, NULL, NULL, NULL)
@@ -106,6 +127,8 @@ static ERL_NIF_TERM atom_trace;
static ERL_NIF_TERM atom_remove;
static ERL_NIF_TERM atom_discard;
+#ifdef HAVE_USE_LTTNG
+
/* gc atoms */
static ERL_NIF_TERM atom_gc_minor_start;
@@ -151,6 +174,7 @@ static ERL_NIF_TERM atom_closed;
static ERL_NIF_TERM atom_call;
static ERL_NIF_TERM atom_return_from;
static ERL_NIF_TERM atom_exception_from;
+#endif
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
@@ -165,6 +189,8 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_remove = enif_make_atom(env,"remove");
atom_discard = enif_make_atom(env,"discard");
+#ifdef HAVE_USE_LTTNG
+
/* gc */
atom_gc_minor_start = enif_make_atom(env,"gc_minor_start");
@@ -210,6 +236,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_call = enif_make_atom(env,"call");
atom_return_from = enif_make_atom(env,"return_from");
atom_exception_from = enif_make_atom(env,"exception_from");
+#endif
return 0;
}
@@ -273,7 +300,6 @@ 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[])
{
#ifdef HAVE_USE_DTRACE
-#define BUFF_SIZE 1024
size_t sz = BUFF_SIZE;
char buff[BUFF_SIZE];
ASSERT(argc == 6);
@@ -312,21 +338,30 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
erlang_trace(p, event, state, arg1, arg2);
}
-#elif HAVE_USE_LTTNG
- int i;
- erts_fprintf(stderr, "trace:\r\n");
- for (i = 0; i < argc; i++) {
- erts_fprintf(stderr, " %T\r\n", argv[i]);
- }
#endif
return atom_ok;
}
+#ifdef HAVE_USE_LTTNG
+static ERL_NIF_TERM enabled_garbage_collection(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{
+ ASSERT(argc == 3);
+
+ if (argv[0] == atom_gc_minor_start && LTTNG_ENABLED(gc_minor_start)) {
+ return atom_trace;
+ } else if (argv[0] == atom_gc_minor_end && LTTNG_ENABLED(gc_minor_end)) {
+ return atom_trace;
+ } else if (argv[0] == atom_gc_major_start && LTTNG_ENABLED(gc_major_start)) {
+ return atom_trace;
+ } else if (argv[0] == atom_gc_major_end && LTTNG_ENABLED(gc_major_end)) {
+ return atom_trace;
+ }
+
+ return atom_discard;
+}
static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
-#ifdef HAVE_USE_DTRACE
-#elif HAVE_USE_LTTNG
lttng_decl_procbuf(pid);
ERL_NIF_TERM gci, tup;
const ERL_NIF_TERM *vals;
@@ -369,14 +404,25 @@ static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL
} else if (argv[0] == atom_gc_major_end) {
LTTNG4(gc_major_end, pid, size, nhbsz, ohbsz);
}
-#endif
return atom_ok;
}
+static ERL_NIF_TERM enabled_call(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{
+ ASSERT(argc == 3);
+
+ if (argv[0] == atom_call && LTTNG_ENABLED(function_call))
+ return atom_trace;
+ else if (argv[0] == atom_return_from && LTTNG_ENABLED(function_return))
+ return atom_trace;
+ else if (argv[0] == atom_exception_from && LTTNG_ENABLED(function_exception))
+ return atom_trace;
+
+ return atom_discard;
+}
+
static ERL_NIF_TERM trace_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
-#ifdef HAVE_USE_DTRACE
-#elif HAVE_USE_LTTNG
lttng_decl_procbuf(pid);
unsigned int len;
char undef[] = "undefined";
@@ -427,22 +473,21 @@ static ERL_NIF_TERM trace_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
} else {
LTTNG3(function_exception, pid, undef, class);
}
- } else {
- int i;
- erts_fprintf(stderr, "trace call:\r\n");
- for (i = 0; i < argc; i++) {
- erts_fprintf(stderr, " %T\r\n", argv[i]);
- }
}
-#endif
return atom_ok;
}
+static ERL_NIF_TERM enabled_send(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{
+ ASSERT(argc == 3);
+ if (LTTNG_ENABLED(message_send))
+ return atom_trace;
+
+ return atom_discard;
+}
static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
-#ifdef HAVE_USE_DTRACE
-#elif HAVE_USE_LTTNG
lttng_decl_procbuf(pid);
lttng_pid_to_str(argv[2], pid);
@@ -463,22 +508,20 @@ static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
/* mark it as non existing ? */
LTTNG3(message_send, pid, to, msg);
- } else {
- int i;
- erts_fprintf(stderr, "trace send:\r\n");
- for (i = 0; i < argc; i++) {
- erts_fprintf(stderr, " %T\r\n", argv[i]);
- }
}
-#endif
return atom_ok;
}
+static ERL_NIF_TERM enabled_receive(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{
+ if (LTTNG_ENABLED(message_receive))
+ return atom_trace;
+
+ return atom_discard;
+}
static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
-#ifdef HAVE_USE_DTRACE
-#elif HAVE_USE_LTTNG
if (argv[0] == atom_receive) {
lttng_decl_procbuf(pid);
char msg[LTTNG_BUFFER_SZ];
@@ -487,60 +530,37 @@ static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
erts_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]);
LTTNG2(message_receive, pid, msg);
- } else {
- int i;
- erts_fprintf(stderr, "trace receive:\r\n");
- for (i = 0; i < argc; i++) {
- erts_fprintf(stderr, " %T\r\n", argv[i]);
- }
}
-#endif
return atom_ok;
}
-static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM enabled_procs(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
-#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]);
+ ASSERT(argc == 3);
- if (argc == 6) {
- arg2 = buff + BUFF_SIZE - sz;
- sz -= erts_snprintf(arg2, sz, "%T", argv[4]);
- } else
- args2 = NULL;
+ if (argv[0] == atom_spawn && LTTNG_ENABLED(process_spawn)) {
+ return atom_trace;
+ } else if (argv[0] == atom_register && LTTNG_ENABLED(process_register)) {
+ return atom_trace;
+ } else if (argv[0] == atom_unregister && LTTNG_ENABLED(process_register)) {
+ return atom_trace;
+ } else if (argv[0] == atom_link && LTTNG_ENABLED(process_link)) {
+ return atom_trace;
+ } else if (argv[0] == atom_unlink && LTTNG_ENABLED(process_link)) {
+ return atom_trace;
+ } else if (argv[0] == atom_getting_linked && LTTNG_ENABLED(process_link)) {
+ return atom_trace;
+ } else if (argv[0] == atom_getting_unlinked && LTTNG_ENABLED(process_link)) {
+ return atom_trace;
+ } else if (argv[0] == atom_exit && LTTNG_ENABLED(process_exit)) {
+ return atom_trace;
+ }
- erlang_trace(p, event, state, arg1, arg2);
+ return atom_discard;
+}
- }
-#elif HAVE_USE_LTTNG
+static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
lttng_decl_procbuf(pid);
lttng_decl_procbuf(to);
@@ -595,21 +615,33 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
char reason[LTTNG_BUFFER_SZ];
erts_snprintf(reason, LTTNG_BUFFER_SZ, "%T", argv[3]);
LTTNG2(process_exit, pid, reason);
- } else {
- int i;
- erts_fprintf(stderr, "proc trace:\r\n");
- for (i = 0; i < argc; i++) {
- erts_fprintf(stderr, " %T\r\n", argv[i]);
- }
}
-#endif
return atom_ok;
}
+static ERL_NIF_TERM enabled_ports(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{
+ ASSERT(argc == 3);
+
+ if (argv[0] == atom_open && LTTNG_ENABLED(port_open)) {
+ return atom_trace;
+ } else if (argv[0] == atom_link && LTTNG_ENABLED(port_link)) {
+ return atom_trace;
+ } else if (argv[0] == atom_unlink && LTTNG_ENABLED(port_link)) {
+ return atom_trace;
+ } else if (argv[0] == atom_getting_linked && LTTNG_ENABLED(port_link)) {
+ return atom_trace;
+ } else if (argv[0] == atom_getting_unlinked && LTTNG_ENABLED(port_link)) {
+ return atom_trace;
+ } else if (argv[0] == atom_closed && LTTNG_ENABLED(port_exit)) {
+ return atom_trace;
+ }
+
+ return atom_discard;
+}
+
static ERL_NIF_TERM trace_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
-#ifdef HAVE_USE_DTRACE
-#elif HAVE_USE_LTTNG
lttng_decl_portbuf(port);
lttng_decl_procbuf(to);
@@ -641,22 +673,22 @@ static ERL_NIF_TERM trace_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
} else if (argv[0] == atom_getting_unlinked) {
lttng_pid_to_str(argv[3], to);
LTTNG3(port_link, to, port, "unlink");
- } else {
- int i;
- erts_fprintf(stderr, "ports trace:\r\n");
- for (i = 0; i < argc; i++) {
- erts_fprintf(stderr, " %T\r\n", argv[i]);
- }
}
-#endif
return atom_ok;
}
+static ERL_NIF_TERM enabled_running(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{
+ ASSERT(argc == 3);
+
+ if (LTTNG_ENABLED(process_scheduled))
+ return atom_trace;
+
+ return atom_discard;
+}
static ERL_NIF_TERM trace_running(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
-#ifdef HAVE_USE_DTRACE
-#elif HAVE_USE_LTTNG
lttng_decl_procbuf(pid);
const ERL_NIF_TERM* tuple;
char *mfastr = "undefined";
@@ -685,6 +717,6 @@ static ERL_NIF_TERM trace_running(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
} else if (argv[0] == atom_out_exited) {
LTTNG3(process_scheduled, pid, mfastr, "out_exited");
}
-#endif
return atom_ok;
}
+#endif
diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h
index 3044cf0948..541a6c16e8 100644
--- a/lib/runtime_tools/c_src/dyntrace_lttng.h
+++ b/lib/runtime_tools/c_src/dyntrace_lttng.h
@@ -41,6 +41,9 @@
#define LTTNG5(Name, Arg1, Arg2, Arg3, Arg4, Arg5) \
tracepoint(com_ericsson_dyntrace, Name, (Arg1), (Arg2), (Arg3), (Arg4), (Arg5))
+#define LTTNG_ENABLED(Name) \
+ tracepoint_enabled(com_ericsson_dyntrace, Name)
+
#define LTTNG_BUFFER_SZ (256)
#define LTTNG_PROC_BUFFER_SZ (16)
#define LTTNG_PORT_BUFFER_SZ (20)
diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl
index f776b601cb..8a449e5749 100644
--- a/lib/runtime_tools/src/dyntrace.erl
+++ b/lib/runtime_tools/src/dyntrace.erl
@@ -41,8 +41,7 @@
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,
+-export([trace/5,
trace/6,
trace_procs/6,
trace_ports/6,
@@ -50,8 +49,17 @@
trace_call/6,
trace_send/6,
trace_receive/6,
- trace_garbage_collection/6
- ]).
+ trace_garbage_collection/6]).
+
+-export([enabled_procs/3,
+ enabled_ports/3,
+ enabled_running/3,
+ enabled_call/3,
+ enabled_send/3,
+ enabled_receive/3,
+ enabled_garbage_collection/3,
+ enabled/3]).
+
-export([user_trace_i4s4/9]). % Know what you're doing!
-on_load(on_load/0).
@@ -137,9 +145,6 @@ 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).
@@ -167,6 +172,30 @@ trace_receive(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTer
trace_garbage_collection(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) ->
erlang:nif_error(nif_not_loaded).
+enabled(_TraceTag, _TracerState, _Tracee) ->
+ erlang:nif_error(nif_not_loaded).
+
+enabled_procs(_TraceTag, _TracerState, _Tracee) ->
+ erlang:nif_error(nif_not_loaded).
+
+enabled_ports(_TraceTag, _TracerState, _Tracee) ->
+ erlang:nif_error(nif_not_loaded).
+
+enabled_running(_TraceTag, _TracerState, _Tracee) ->
+ erlang:nif_error(nif_not_loaded).
+
+enabled_call(_TraceTag, _TracerState, _Tracee) ->
+ erlang:nif_error(nif_not_loaded).
+
+enabled_send(_TraceTag, _TracerState, _Tracee) ->
+ erlang:nif_error(nif_not_loaded).
+
+enabled_receive(_TraceTag, _TracerState, _Tracee) ->
+ erlang:nif_error(nif_not_loaded).
+
+enabled_garbage_collection(_TraceTag, _TracerState, _Tracee) ->
+ erlang:nif_error(nif_not_loaded).
+
%%%
%%% Erlang support functions
%%%