aboutsummaryrefslogtreecommitdiffstats
path: root/lib/runtime_tools
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2016-02-18 16:21:30 +0100
committerBjörn-Egil Dahlberg <[email protected]>2016-04-19 13:32:27 +0200
commit11e8e1e38bba355c2996d766b7d2893e441c1211 (patch)
tree015d55c19876a7eb14b8fdc08d6c7d55dd2388bf /lib/runtime_tools
parent58c0f8de7a27a659fe2b534a86752f67da1af998 (diff)
downloadotp-11e8e1e38bba355c2996d766b7d2893e441c1211.tar.gz
otp-11e8e1e38bba355c2996d766b7d2893e441c1211.tar.bz2
otp-11e8e1e38bba355c2996d766b7d2893e441c1211.zip
runtime_tools: Initial lttng tracing framework
Diffstat (limited to 'lib/runtime_tools')
-rw-r--r--lib/runtime_tools/c_src/Makefile.in2
-rw-r--r--lib/runtime_tools/c_src/dyntrace.c313
-rw-r--r--lib/runtime_tools/src/dyntrace.erl27
3 files changed, 341 insertions, 1 deletions
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
%%%