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') 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 From c99fb79cb21a1e3fcc170cd9745df34c919a7b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 29 Feb 2016 17:39:37 +0100 Subject: runtime_tools: Add lttng 'garbage_collection' tracing --- lib/runtime_tools/c_src/dyntrace.c | 128 ++++++++++++++----------------- lib/runtime_tools/c_src/dyntrace_lttng.h | 106 +++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 72 deletions(-) create mode 100644 lib/runtime_tools/c_src/dyntrace_lttng.h (limited to 'lib') diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index e0309e53e3..6344f6ed90 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -29,7 +29,13 @@ #include "sys.h" #include "dtrace-wrapper.h" #if defined(USE_DYNAMIC_TRACE) && (defined(USE_DTRACE) || defined(USE_SYSTEMTAP)) -#define HAVE_USE_DTRACE 1 +# define HAVE_USE_DTRACE 1 +#endif +#if defined(USE_LTTNG) +# define HAVE_USE_LTTNG 1 +# define TRACEPOINT_DEFINE +# define TRACEPOINT_CREATE_PROBES +# include "dyntrace_lttng.h" #endif void dtrace_nifenv_str(ErlNifEnv *env, char *process_buf); @@ -94,6 +100,12 @@ static ERL_NIF_TERM atom_trace; static ERL_NIF_TERM atom_remove; static ERL_NIF_TERM atom_discard; +/* gc atoms */ + +static ERL_NIF_TERM atom_gc_start; +static ERL_NIF_TERM atom_gc_end; + + static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { atom_true = enif_make_atom(env,"true"); @@ -107,6 +119,9 @@ 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"); + atom_gc_start = enif_make_atom(env,"gc_start"); + atom_gc_end = enif_make_atom(env,"gc_end"); + return 0; } @@ -160,25 +175,21 @@ static ERL_NIF_TERM enabled(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) } return atom_trace; -#else +#elif HAVE_USE_LTTNG + /* 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 + return atom_remove; } 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; @@ -219,57 +230,33 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 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 +#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; +} +static ERL_NIF_TERM trace_garbage_collection(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]); - - if (argc == 6) { - arg2 = buff + BUFF_SIZE - sz; - sz -= erts_snprintf(arg2, sz, "%T", argv[4]); - } else - args2 = NULL; +#elif HAVE_USE_LTTNG + lttng_decl_procbuf(pid); - erlang_trace(p, event, state, arg1, arg2); + lttng_pid_to_str(argv[2], pid); + if (argv[0] == atom_gc_start) { + LTTNG2(gc_minor_start, pid, 0); + } else if (argv[0] == atom_gc_end) { + LTTNG2(gc_minor_end, pid, 0); + } 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; @@ -278,13 +265,6 @@ static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL 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; @@ -325,6 +305,12 @@ static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM a 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; } @@ -332,13 +318,6 @@ static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM a 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; @@ -379,19 +358,18 @@ static ERL_NIF_TERM trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv 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 +#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; +} + +static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ #ifdef HAVE_USE_DTRACE #define BUFF_SIZE 1024 size_t sz = BUFF_SIZE; @@ -432,6 +410,12 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg 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; } diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h new file mode 100644 index 0000000000..e4482675bf --- /dev/null +++ b/lib/runtime_tools/c_src/dyntrace_lttng.h @@ -0,0 +1,106 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2016. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * %CopyrightEnd% + */ + +#undef TRACEPOINT_PROVIDER +#define TRACEPOINT_PROVIDER com_ericsson_dyntrace + +#if !defined(DYNTRACE_LTTNG_H) || defined(TRACEPOINT_HEADER_MULTI_READ) +#define DYNTRACE_LTTNG_H + +#include + +/* include a special LTTNG_DO for do_tracepoint ? */ +#define LTTNG1(Name, Arg1) \ + tracepoint(com_ericsson_dyntrace, Name, (Arg1)) + +#define LTTNG2(Name, Arg1, Arg2) \ + tracepoint(com_ericsson_dyntrace, Name, (Arg1), (Arg2)) + +#define LTTNG3(Name, Arg1, Arg2, Arg3) \ + tracepoint(com_ericsson_dyntrace, Name, (Arg1), (Arg2), (Arg3)) + +#define LTTNG4(Name, Arg1, Arg2, Arg3, Arg4) \ + tracepoint(com_ericsson_dyntrace, Name, (Arg1), (Arg2), (Arg3), (Arg4)) + +#define LTTNG5(Name, Arg1, Arg2, Arg3, Arg4, Arg5) \ + tracepoint(com_ericsson_dyntrace, Name, (Arg1), (Arg2), (Arg3), (Arg4), (Arg5)) + + +/* Process Memory */ + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + gc_minor_start, + TP_ARGS( + char*, p, + int, need + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_integer(int, need, need) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + gc_minor_end, + TP_ARGS( + char*, p, + int, reclaimed + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_integer(int, reclaimed, reclaimed) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + gc_major_start, + TP_ARGS( + char*, p, + int, need + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_integer(int, need, need) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + gc_major_end, + TP_ARGS( + char*, p, + int, reclaimed + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_integer(int, reclaimed, reclaimed) + ) +) + +#endif /* DYNTRACE_LTTNG_H */ + +#undef TRACEPOINT_INCLUDE +#define TRACEPOINT_INCLUDE "./dyntrace_lttng.h" + +/* This part must be outside protection */ +#include -- cgit v1.2.3 From 8b9b4e8bffe087752463287457330803e69a1c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 2 Mar 2016 16:22:11 +0100 Subject: runtime_tools: Add lttng 'procs' tracing --- lib/runtime_tools/c_src/dyntrace.c | 94 ++++++++++++++++++++++++++++---- lib/runtime_tools/c_src/dyntrace_lttng.h | 89 +++++++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 6344f6ed90..3da003f281 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -105,6 +105,17 @@ static ERL_NIF_TERM atom_discard; static ERL_NIF_TERM atom_gc_start; static ERL_NIF_TERM atom_gc_end; +/* process atoms */ + +static ERL_NIF_TERM atom_spawn; +static ERL_NIF_TERM atom_exit; +static ERL_NIF_TERM atom_register; +static ERL_NIF_TERM atom_unregister; +static ERL_NIF_TERM atom_link; +static ERL_NIF_TERM atom_unlink; +static ERL_NIF_TERM atom_getting_linked; +static ERL_NIF_TERM atom_getting_unlinked; + static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { @@ -119,9 +130,22 @@ 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"); + /* gc */ + atom_gc_start = enif_make_atom(env,"gc_start"); atom_gc_end = enif_make_atom(env,"gc_end"); + /* process 'proc' */ + + atom_spawn = enif_make_atom(env,"spawn"); + atom_exit = enif_make_atom(env,"exit"); + atom_register = enif_make_atom(env,"register"); + atom_unregister = enif_make_atom(env,"unregister"); + atom_link = enif_make_atom(env,"link"); + atom_unlink = enif_make_atom(env,"unlink"); + atom_getting_unlinked = enif_make_atom(env,"getting_unlinked"); + atom_getting_linked = enif_make_atom(env,"getting_linked"); + return 0; } @@ -176,13 +200,6 @@ static ERL_NIF_TERM enabled(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return atom_trace; #elif HAVE_USE_LTTNG - /* - 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; #endif return atom_remove; @@ -239,6 +256,8 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) #endif return atom_ok; } + + static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { #ifdef HAVE_USE_DTRACE @@ -411,10 +430,63 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg } #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]); + lttng_decl_procbuf(pid); + lttng_decl_procbuf(to); + + lttng_pid_to_str(argv[2], pid); + + /* spawn */ + if (argv[0] == atom_spawn) { + char undef[] = "undefined"; + const ERL_NIF_TERM* tuple; + int arity; + unsigned int len; + lttng_decl_mfabuf(mfa); + + lttng_pid_to_str(argv[3], to); + + if (enif_get_tuple(env, argv[4], &arity, &tuple)) { + enif_get_list_length(env, tuple[2], &len); + lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); + LTTNG3(process_spawn, to, pid, mfa); + } else { + LTTNG3(process_spawn, to, pid, undef); + } + + /* register */ + } else if (argv[0] == atom_register) { + char name[LTTNG_BUFFER_SZ]; + erts_snprintf(name, LTTNG_BUFFER_SZ, "%T", argv[3]); + LTTNG3(process_register, pid, name, "register"); + } else if (argv[0] == atom_unregister) { + char name[LTTNG_BUFFER_SZ]; + erts_snprintf(name, LTTNG_BUFFER_SZ, "%T", argv[3]); + LTTNG3(process_register, pid, name, "unregister"); + /* link */ + } else if (argv[0] == atom_link) { + lttng_pid_to_str(argv[3], to); + LTTNG3(process_link, pid, to, "link"); + /* link */ + } else if (argv[0] == atom_unlink) { + lttng_pid_to_str(argv[3], to); + LTTNG3(process_link, pid, to, "unlink"); + } else if (argv[0] == atom_getting_linked) { + lttng_pid_to_str(argv[3], to); + LTTNG3(process_link, to, pid, "link"); + } else if (argv[0] == atom_getting_unlinked) { + lttng_pid_to_str(argv[3], to); + LTTNG3(process_link, to, pid, "unlink"); + /* exit */ + } else if (argv[0] == atom_exit) { + 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, "trace:\r\n"); + for (i = 0; i < argc; i++) { + erts_fprintf(stderr, " %T\r\n", argv[i]); + } } #endif return atom_ok; diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h index e4482675bf..c2fd003d48 100644 --- a/lib/runtime_tools/c_src/dyntrace_lttng.h +++ b/lib/runtime_tools/c_src/dyntrace_lttng.h @@ -26,7 +26,6 @@ #include -/* include a special LTTNG_DO for do_tracepoint ? */ #define LTTNG1(Name, Arg1) \ tracepoint(com_ericsson_dyntrace, Name, (Arg1)) @@ -42,6 +41,94 @@ #define LTTNG5(Name, Arg1, Arg2, Arg3, Arg4, Arg5) \ tracepoint(com_ericsson_dyntrace, Name, (Arg1), (Arg2), (Arg3), (Arg4), (Arg5)) +#define LTTNG_BUFFER_SZ (256) +#define LTTNG_PROC_BUFFER_SZ (16) +#define LTTNG_PORT_BUFFER_SZ (20) +#define LTTNG_MFA_BUFFER_SZ (256) + +#define lttng_decl_procbuf(Name) \ + char Name[LTTNG_PROC_BUFFER_SZ] + +#define lttng_decl_portbuf(Name) \ + char Name[LTTNG_PORT_BUFFER_SZ] + +#define lttng_decl_mfabuf(Name) \ + char Name[LTTNG_MFA_BUFFER_SZ] + +#define lttng_pid_to_str(pid, name) \ + erts_snprintf(name, LTTNG_PROC_BUFFER_SZ, "%T", (pid)) + +#define lttng_portid_to_str(pid, name) \ + erts_snprintf(name, LTTNG_PORT_BUFFER_SZ, "%T", (pid)) + +#define lttng_proc_to_str(p, name) \ + lttng_pid_to_str(((p) ? (p)->common.id : ERTS_INVALID_PID), name) + +#define lttng_port_to_str(p, name) \ + lttng_portid_to_str(((p) ? (p)->common.id : ERTS_INVALID_PORT), name) + +#define lttng_mfa_to_str(m,f,a, Name) \ + erts_snprintf(Name, LTTNG_MFA_BUFFER_SZ, "%T:%T/%lu", (Eterm)(m), (Eterm)(f), (Uint)(a)) + +/* Process scheduling */ + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + process_spawn, + TP_ARGS( + char*, p, + char*, parent, + char*, mfa + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_string(parent, parent) + ctf_string(entry, mfa) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + process_link, + TP_ARGS( + char*, from, + char*, to, + char*, type + ), + TP_FIELDS( + ctf_string(from, from) + ctf_string(to, to) + ctf_string(type, type) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + process_exit, + TP_ARGS( + char*, p, + char*, reason + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_string(reason, reason) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + process_register, + TP_ARGS( + char*, pid, + char*, name, + char*, type + ), + TP_FIELDS( + ctf_string(pid, pid) + ctf_string(name, name) + ctf_string(type, type) + ) +) /* Process Memory */ -- cgit v1.2.3 From b36c6d949916e1d7b0f6bee17004c012e6a36112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 2 Mar 2016 16:46:04 +0100 Subject: runtime_tools: Add lttng 'running' tracing --- lib/runtime_tools/c_src/dyntrace.c | 60 +++++++++++++++++++++++++++++--- lib/runtime_tools/c_src/dyntrace_lttng.h | 17 +++++++++ lib/runtime_tools/src/dyntrace.erl | 5 +++ 3 files changed, 78 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 3da003f281..4abe4f80ac 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -69,6 +69,7 @@ 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[]); static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_running(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[]); @@ -82,6 +83,7 @@ static ErlNifFunc nif_funcs[] = { {"trace", 5, trace}, {"trace", 6, trace}, {"trace_procs", 6, trace_procs}, + {"trace_running", 6, trace_running}, {"trace_send", 6, trace_send}, {"trace_receive", 6, trace_receive}, {"trace_garbage_collection", 6, trace_garbage_collection} @@ -105,7 +107,7 @@ static ERL_NIF_TERM atom_discard; static ERL_NIF_TERM atom_gc_start; static ERL_NIF_TERM atom_gc_end; -/* process atoms */ +/* process 'procs' */ static ERL_NIF_TERM atom_spawn; static ERL_NIF_TERM atom_exit; @@ -116,6 +118,14 @@ static ERL_NIF_TERM atom_unlink; static ERL_NIF_TERM atom_getting_linked; static ERL_NIF_TERM atom_getting_unlinked; +/* process 'running' and 'exiting' */ + +static ERL_NIF_TERM atom_in; +static ERL_NIF_TERM atom_out; +static ERL_NIF_TERM atom_in_exiting; +static ERL_NIF_TERM atom_out_exiting; +static ERL_NIF_TERM atom_out_exited; + static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { @@ -146,6 +156,14 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_getting_unlinked = enif_make_atom(env,"getting_unlinked"); atom_getting_linked = enif_make_atom(env,"getting_linked"); + /* process 'running' and 'exiting' */ + + atom_in = enif_make_atom(env,"in"); + atom_out = enif_make_atom(env,"out"); + atom_in_exiting = enif_make_atom(env,"in_exiting"); + atom_out_exiting = enif_make_atom(env,"out_exiting"); + atom_out_exited = enif_make_atom(env,"out_exited"); + return 0; } @@ -326,7 +344,7 @@ static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM a } #elif HAVE_USE_LTTNG int i; - erts_fprintf(stderr, "trace:\r\n"); + erts_fprintf(stderr, "receive trace:\r\n"); for (i = 0; i < argc; i++) { erts_fprintf(stderr, " %T\r\n", argv[i]); } @@ -466,7 +484,6 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg } else if (argv[0] == atom_link) { lttng_pid_to_str(argv[3], to); LTTNG3(process_link, pid, to, "link"); - /* link */ } else if (argv[0] == atom_unlink) { lttng_pid_to_str(argv[3], to); LTTNG3(process_link, pid, to, "unlink"); @@ -483,7 +500,7 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg LTTNG2(process_exit, pid, reason); } else { int i; - erts_fprintf(stderr, "trace:\r\n"); + erts_fprintf(stderr, "proc trace:\r\n"); for (i = 0; i < argc; i++) { erts_fprintf(stderr, " %T\r\n", argv[i]); } @@ -492,3 +509,38 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg return atom_ok; } +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"; + int arity; + + lttng_pid_to_str(argv[2], pid); + lttng_decl_mfabuf(mfa); + + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { + int val; + enif_get_int(env, tuple[2], &val); + lttng_mfa_to_str(tuple[0], tuple[1], val, mfa); + mfastr = mfa; + } + + /* running */ + if (argv[0] == atom_in) { + LTTNG3(process_scheduled, pid, mfastr, "in"); + } else if (argv[0] == atom_out) { + LTTNG3(process_scheduled, pid, mfastr, "out"); + /* exiting */ + } else if (argv[0] == atom_in_exiting) { + LTTNG3(process_scheduled, pid, mfastr, "in_exiting"); + } else if (argv[0] == atom_out_exiting) { + LTTNG3(process_scheduled, pid, mfastr, "out_exiting"); + } else if (argv[0] == atom_out_exited) { + LTTNG3(process_scheduled, pid, mfastr, "out_exited"); + } +#endif + return atom_ok; +} diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h index c2fd003d48..1271f7516a 100644 --- a/lib/runtime_tools/c_src/dyntrace_lttng.h +++ b/lib/runtime_tools/c_src/dyntrace_lttng.h @@ -130,6 +130,23 @@ TRACEPOINT_EVENT( ) ) +/* Scheduled */ + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + process_scheduled, + TP_ARGS( + char*, p, + char*, mfa, + char*, type + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_string(entry, mfa) + ctf_string(type, type) + ) +) + /* Process Memory */ TRACEPOINT_EVENT( diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl index 6822f51549..aef4d9fab0 100644 --- a/lib/runtime_tools/src/dyntrace.erl +++ b/lib/runtime_tools/src/dyntrace.erl @@ -45,6 +45,7 @@ trace/5, trace/6, trace_procs/6, + trace_running/6, trace_send/6, trace_receive/6, trace_garbage_collection/6 @@ -145,6 +146,10 @@ trace(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts trace_procs(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). + +trace_running(_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) -> -- cgit v1.2.3 From d4c938686562d3c5ccf6a34aafeef6460b9b88f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 3 Mar 2016 14:03:45 +0100 Subject: runtime_tools: Add lttng 'send' and 'receive' tracing --- lib/runtime_tools/c_src/dyntrace.c | 132 ++++++++++++------------------- lib/runtime_tools/c_src/dyntrace_lttng.h | 30 +++++++ 2 files changed, 79 insertions(+), 83 deletions(-) (limited to 'lib') diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 4abe4f80ac..0be72848e6 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -126,6 +126,12 @@ static ERL_NIF_TERM atom_in_exiting; static ERL_NIF_TERM atom_out_exiting; static ERL_NIF_TERM atom_out_exited; +/* process messages 'send' and 'receive' */ + +static ERL_NIF_TERM atom_send; +static ERL_NIF_TERM atom_receive; +static ERL_NIF_TERM atom_send_to_non_existing_process; + static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { @@ -164,6 +170,12 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_out_exiting = enif_make_atom(env,"out_exiting"); atom_out_exited = enif_make_atom(env,"out_exited"); + /* process messages 'send' and 'receive' */ + + atom_send = enif_make_atom(env,"send"); + atom_receive = enif_make_atom(env,"receive"); + atom_send_to_non_existing_process = enif_make_atom(env,"send_to_non_existing_process"); + return 0; } @@ -300,106 +312,60 @@ static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL } -static ERL_NIF_TERM trace_receive(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM trace_send(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]); +#elif HAVE_USE_LTTNG + lttng_decl_procbuf(pid); + lttng_pid_to_str(argv[2], pid); - if (enif_is_pid(argv[2]) || enif_is_port(argv[2])) - dtrace_pid_str(argv[2], p); - else - p = NULL; + if (argv[0] == atom_send) { + lttng_decl_procbuf(to); + char msg[LTTNG_BUFFER_SZ]; - arg1 = buff + BUFF_SIZE - sz; - sz -= erts_snprintf(arg1, sz, "%T", argv[3]); + lttng_pid_to_str(argv[4], to); + erts_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); - if (argc == 6) { - arg2 = buff + BUFF_SIZE - sz; - sz -= erts_snprintf(arg2, sz, "%T", argv[4]); - } else - args2 = NULL; + LTTNG3(message_send, pid, to, msg); + } else if (argv[0] == atom_send_to_non_existing_process) { + lttng_decl_procbuf(to); + char msg[LTTNG_BUFFER_SZ]; - erlang_trace(p, event, state, arg1, arg2); + lttng_pid_to_str(argv[4], to); + erts_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]); + /* mark it as non existing ? */ - } -#elif HAVE_USE_LTTNG - int i; - erts_fprintf(stderr, "receive trace:\r\n"); - for (i = 0; i < argc; i++) { - erts_fprintf(stderr, " %T\r\n", argv[i]); + 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 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[]) { #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; +#elif HAVE_USE_LTTNG + if (argv[0] == atom_receive) { + lttng_decl_procbuf(pid); + char msg[LTTNG_BUFFER_SZ]; - arg1 = buff + BUFF_SIZE - sz; - sz -= erts_snprintf(arg1, sz, "%T", argv[3]); + lttng_pid_to_str(argv[2], pid); + erts_snprintf(msg, LTTNG_BUFFER_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); - - } -#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]); + 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; diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h index 1271f7516a..03cf8a27c1 100644 --- a/lib/runtime_tools/c_src/dyntrace_lttng.h +++ b/lib/runtime_tools/c_src/dyntrace_lttng.h @@ -147,6 +147,36 @@ TRACEPOINT_EVENT( ) ) +/* Process messages */ + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + message_send, + TP_ARGS( + char*, sender, + char*, receiver, + char*, msg + ), + TP_FIELDS( + ctf_string(from, sender) + ctf_string(to, receiver) + ctf_string(message, msg) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + message_receive, + TP_ARGS( + char*, receiver, + char*, msg + ), + TP_FIELDS( + ctf_string(to, receiver) + ctf_string(message, msg) + ) +) + /* Process Memory */ TRACEPOINT_EVENT( -- cgit v1.2.3 From cc290266f06458c8009182167418ef9f1e21a794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 3 Mar 2016 15:14:03 +0100 Subject: runtime_tools: Add lttng 'ports' tracing --- lib/runtime_tools/c_src/dyntrace.c | 58 ++++++++++++++++++++++++++++++++ lib/runtime_tools/c_src/dyntrace_lttng.h | 47 ++++++++++++++++++++++++++ lib/runtime_tools/src/dyntrace.erl | 6 ++++ 3 files changed, 111 insertions(+) (limited to 'lib') diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 0be72848e6..43d61266cc 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -69,6 +69,7 @@ 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[]); 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[]); 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[]); @@ -83,6 +84,7 @@ static ErlNifFunc nif_funcs[] = { {"trace", 5, trace}, {"trace", 6, trace}, {"trace_procs", 6, trace_procs}, + {"trace_ports", 6, trace_ports}, {"trace_running", 6, trace_running}, {"trace_send", 6, trace_send}, {"trace_receive", 6, trace_receive}, @@ -132,6 +134,10 @@ static ERL_NIF_TERM atom_send; static ERL_NIF_TERM atom_receive; static ERL_NIF_TERM atom_send_to_non_existing_process; +/* ports 'ports' */ + +static ERL_NIF_TERM atom_open; +static ERL_NIF_TERM atom_closed; static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { @@ -176,6 +182,11 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_receive = enif_make_atom(env,"receive"); atom_send_to_non_existing_process = enif_make_atom(env,"send_to_non_existing_process"); + /* ports 'ports' */ + + atom_open = enif_make_atom(env,"open"); + atom_closed = enif_make_atom(env,"closed"); + return 0; } @@ -475,6 +486,53 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg return atom_ok; } +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); + + lttng_portid_to_str(argv[2], port); + + /* open and closed */ + if (argv[0] == atom_open) { + char driver[LTTNG_BUFFER_SZ]; + lttng_decl_procbuf(pid); + lttng_pid_to_str(argv[3], pid); + + erts_snprintf(driver, LTTNG_BUFFER_SZ, "%T", argv[4]); + LTTNG3(port_open, pid, driver, port); + } else if (argv[0] == atom_closed) { + char reason[LTTNG_BUFFER_SZ]; + erts_snprintf(reason, LTTNG_BUFFER_SZ, "%T", argv[3]); + + LTTNG2(port_exit, port, reason); + /* link */ + } else if (argv[0] == atom_link) { + lttng_pid_to_str(argv[3], to); + LTTNG3(port_link, port, to, "link"); + } else if (argv[0] == atom_unlink) { + lttng_pid_to_str(argv[3], to); + LTTNG3(port_link, port, to, "unlink"); + } else if (argv[0] == atom_getting_linked) { + lttng_pid_to_str(argv[3], to); + LTTNG3(port_link, to, port, "link"); + } 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 trace_running(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { #ifdef HAVE_USE_DTRACE diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h index 03cf8a27c1..2e0b921621 100644 --- a/lib/runtime_tools/c_src/dyntrace_lttng.h +++ b/lib/runtime_tools/c_src/dyntrace_lttng.h @@ -147,6 +147,53 @@ TRACEPOINT_EVENT( ) ) +/* Ports */ + + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + port_open, + TP_ARGS( + char*, pid, + char*, driver, + char*, port + ), + TP_FIELDS( + ctf_string(pid, pid) + ctf_string(driver, driver) + ctf_string(port, port) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + port_exit, + TP_ARGS( + char*, port, + char*, reason + ), + TP_FIELDS( + ctf_string(port, port) + ctf_string(reason, reason) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + port_link, + TP_ARGS( + char*, from, + char*, to, + char*, type + ), + TP_FIELDS( + ctf_string(from, from) + ctf_string(to, to) + ctf_string(type, type) + ) +) + + /* Process messages */ TRACEPOINT_EVENT( diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl index aef4d9fab0..44c5e36242 100644 --- a/lib/runtime_tools/src/dyntrace.erl +++ b/lib/runtime_tools/src/dyntrace.erl @@ -45,6 +45,7 @@ trace/5, trace/6, trace_procs/6, + trace_ports/6, trace_running/6, trace_send/6, trace_receive/6, @@ -147,13 +148,18 @@ trace(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts trace_procs(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). +trace_ports(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + trace_running(_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). -- cgit v1.2.3 From f5fa3ac80d2f7fcd11ac3e702c29df5ef6c204db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 3 Mar 2016 17:13:32 +0100 Subject: runtime_tools: Add lttng 'call' tracing --- lib/runtime_tools/c_src/dyntrace.c | 85 +++++++++++++++++++++++++++++++- lib/runtime_tools/c_src/dyntrace_lttng.h | 46 +++++++++++++++++ lib/runtime_tools/src/dyntrace.erl | 4 ++ 3 files changed, 134 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 43d61266cc..a22b546cdd 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -71,6 +71,7 @@ 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_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[]); +static ERL_NIF_TERM trace_call(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[]); @@ -86,6 +87,7 @@ static ErlNifFunc nif_funcs[] = { {"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} @@ -139,6 +141,12 @@ static ERL_NIF_TERM atom_send_to_non_existing_process; static ERL_NIF_TERM atom_open; static ERL_NIF_TERM atom_closed; +/* 'call' */ + +static ERL_NIF_TERM atom_call; +static ERL_NIF_TERM atom_return_from; +static ERL_NIF_TERM atom_exception_from; + static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { atom_true = enif_make_atom(env,"true"); @@ -187,6 +195,12 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_open = enif_make_atom(env,"open"); atom_closed = enif_make_atom(env,"closed"); + /* 'call' */ + + 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"); + return 0; } @@ -322,6 +336,71 @@ static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL return atom_ok; } +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"; + + lttng_pid_to_str(argv[2], pid); + + if (argv[0] == atom_call) { + const ERL_NIF_TERM* tuple; + int arity; + lttng_decl_mfabuf(mfa); + + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { + if (enif_is_list(env, tuple[2])) { + enif_get_list_length(env, tuple[2], &len); + } else { + enif_get_uint(env, tuple[2], &len); + } + lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); + LTTNG3(function_call, pid, mfa, 0); + } else { + LTTNG3(function_call, pid, undef, 0); + } + } else if (argv[0] == atom_return_from) { + const ERL_NIF_TERM* tuple; + int arity; + lttng_decl_mfabuf(mfa); + + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { + enif_get_uint(env, tuple[2], &len); + lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); + LTTNG3(function_return, pid, mfa, 0); + } else { + LTTNG3(function_return, pid, undef, 0); + } + } else if (argv[0] == atom_exception_from) { + const ERL_NIF_TERM* tuple; + int arity; + lttng_decl_mfabuf(mfa); + char class[LTTNG_BUFFER_SZ]; + + enif_get_tuple(env, argv[4], &arity, &tuple); + erts_snprintf(class, LTTNG_BUFFER_SZ, "%T", tuple[0]); + + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { + enif_get_uint(env, tuple[2], &len); + lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); + LTTNG3(function_exception, pid, mfa, class); + } 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 trace_send(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { @@ -441,7 +520,11 @@ static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg lttng_pid_to_str(argv[3], to); if (enif_get_tuple(env, argv[4], &arity, &tuple)) { - enif_get_list_length(env, tuple[2], &len); + if (enif_is_list(env, tuple[2])) { + enif_get_list_length(env, tuple[2], &len); + } else { + enif_get_uint(env, tuple[2], &len); + } lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); LTTNG3(process_spawn, to, pid, mfa); } else { diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h index 2e0b921621..265af5729f 100644 --- a/lib/runtime_tools/c_src/dyntrace_lttng.h +++ b/lib/runtime_tools/c_src/dyntrace_lttng.h @@ -193,6 +193,52 @@ TRACEPOINT_EVENT( ) ) +/* Call tracing */ + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + function_call, + TP_ARGS( + char*, pid, + char*, mfa, + unsigned int, depth + ), + TP_FIELDS( + ctf_string(pid, pid) + ctf_string(entry, mfa) + ctf_integer(unsigned int, depth, depth) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + function_return, + TP_ARGS( + char*, pid, + char*, mfa, + unsigned int, depth + ), + TP_FIELDS( + ctf_string(pid, pid) + ctf_string(entry, mfa) + ctf_integer(unsigned int, depth, depth) + ) +) + +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + function_exception, + TP_ARGS( + char*, pid, + char*, mfa, + char*, type + ), + TP_FIELDS( + ctf_string(pid, pid) + ctf_string(entry, mfa) + ctf_string(class, type) + ) +) /* Process messages */ diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl index 44c5e36242..f776b601cb 100644 --- a/lib/runtime_tools/src/dyntrace.erl +++ b/lib/runtime_tools/src/dyntrace.erl @@ -47,6 +47,7 @@ trace_procs/6, trace_ports/6, trace_running/6, + trace_call/6, trace_send/6, trace_receive/6, trace_garbage_collection/6 @@ -154,6 +155,9 @@ trace_ports(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, trace_running(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). +trace_call(_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). -- cgit v1.2.3 From 2580fd9edf0ebb293cf472740102b57d82d2f287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 7 Mar 2016 16:32:25 +0100 Subject: runtime_tools: Update lttng garbage collection trace --- lib/runtime_tools/c_src/dyntrace.c | 65 +++++++++++++++++++++++++------- lib/runtime_tools/c_src/dyntrace_lttng.h | 32 ++++++++++++---- 2 files changed, 75 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index a22b546cdd..9db26a6c4c 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -108,8 +108,13 @@ static ERL_NIF_TERM atom_discard; /* gc atoms */ -static ERL_NIF_TERM atom_gc_start; -static ERL_NIF_TERM atom_gc_end; +static ERL_NIF_TERM atom_gc_minor_start; +static ERL_NIF_TERM atom_gc_minor_end; +static ERL_NIF_TERM atom_gc_major_start; +static ERL_NIF_TERM atom_gc_major_end; + +static ERL_NIF_TERM atom_old_heap_block_size; /* for debug */ +static ERL_NIF_TERM atom_heap_block_size; /* for debug */ /* process 'procs' */ @@ -162,8 +167,13 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) /* gc */ - atom_gc_start = enif_make_atom(env,"gc_start"); - atom_gc_end = enif_make_atom(env,"gc_end"); + atom_gc_minor_start = enif_make_atom(env,"gc_minor_start"); + atom_gc_minor_end = enif_make_atom(env,"gc_minor_end"); + atom_gc_major_start = enif_make_atom(env,"gc_major_start"); + atom_gc_major_end = enif_make_atom(env,"gc_major_end"); + + atom_old_heap_block_size = enif_make_atom(env,"old_heap_block_size"); + atom_heap_block_size = enif_make_atom(env,"heap_block_size"); /* process 'proc' */ @@ -318,19 +328,46 @@ static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL #ifdef HAVE_USE_DTRACE #elif HAVE_USE_LTTNG lttng_decl_procbuf(pid); + ERL_NIF_TERM gci, tup; + const ERL_NIF_TERM *vals; + int arity; + unsigned long ohbsz, nhbsz, size; + + ASSERT(argc == 6); + + /* Assume gc info order does not change */ + gci = argv[3]; + + /* get reclaimed or need */ + enif_get_list_cell(env, gci, &tup, &gci); + enif_get_tuple(env, tup, &arity, &vals); + ASSERT(arity == 2); + enif_get_ulong(env, vals[1], &size); + + /* get old heap block size */ + enif_get_list_cell(env, gci, &tup, &gci); + enif_get_tuple(env, tup, &arity, &vals); + ASSERT(arity == 2); + ASSERT(vals[0] == atom_old_heap_block_size); + enif_get_ulong(env, vals[1], &ohbsz); + + /* get new heap block size */ + enif_get_list_cell(env, gci, &tup, &gci); + enif_get_tuple(env, tup, &arity, &vals); + ASSERT(arity == 2); + ASSERT(vals[0] == atom_heap_block_size); + enif_get_ulong(env, vals[1], &nhbsz); lttng_pid_to_str(argv[2], pid); - if (argv[0] == atom_gc_start) { - LTTNG2(gc_minor_start, pid, 0); - } else if (argv[0] == atom_gc_end) { - LTTNG2(gc_minor_end, pid, 0); - } else { - int i; - erts_fprintf(stderr, "trace send:\r\n"); - for (i = 0; i < argc; i++) { - erts_fprintf(stderr, " %T\r\n", argv[i]); - } + if (argv[0] == atom_gc_minor_start) { + LTTNG4(gc_minor_start, pid, size, nhbsz, ohbsz); + } else if (argv[0] == atom_gc_minor_end) { + LTTNG4(gc_minor_end, pid, size, nhbsz, ohbsz); + } else if (argv[0] == atom_gc_major_start) { + LTTNG4(gc_major_start, pid, size, nhbsz, ohbsz); + } else if (argv[0] == atom_gc_major_end) { + LTTNG4(gc_major_end, pid, size, nhbsz, ohbsz); } #endif return atom_ok; diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h index 265af5729f..3044cf0948 100644 --- a/lib/runtime_tools/c_src/dyntrace_lttng.h +++ b/lib/runtime_tools/c_src/dyntrace_lttng.h @@ -277,11 +277,15 @@ TRACEPOINT_EVENT( gc_minor_start, TP_ARGS( char*, p, - int, need + unsigned long, need, + unsigned long, nh, + unsigned long, oh ), TP_FIELDS( ctf_string(pid, p) - ctf_integer(int, need, need) + ctf_integer(unsigned long, need, need) + ctf_integer(unsigned long, heap, nh) + ctf_integer(unsigned long, old_heap, oh) ) ) @@ -290,11 +294,15 @@ TRACEPOINT_EVENT( gc_minor_end, TP_ARGS( char*, p, - int, reclaimed + unsigned long, reclaimed, + unsigned long, nh, + unsigned long, oh ), TP_FIELDS( ctf_string(pid, p) - ctf_integer(int, reclaimed, reclaimed) + ctf_integer(unsigned long, reclaimed, reclaimed) + ctf_integer(unsigned long, heap, nh) + ctf_integer(unsigned long, old_heap, oh) ) ) @@ -303,11 +311,15 @@ TRACEPOINT_EVENT( gc_major_start, TP_ARGS( char*, p, - int, need + unsigned long, need, + unsigned long, nh, + unsigned long, oh ), TP_FIELDS( ctf_string(pid, p) - ctf_integer(int, need, need) + ctf_integer(unsigned long, need, need) + ctf_integer(unsigned long, heap, nh) + ctf_integer(unsigned long, old_heap, oh) ) ) @@ -316,11 +328,15 @@ TRACEPOINT_EVENT( gc_major_end, TP_ARGS( char*, p, - int, reclaimed + unsigned long, reclaimed, + unsigned long, nh, + unsigned long, oh ), TP_FIELDS( ctf_string(pid, p) - ctf_integer(int, reclaimed, reclaimed) + ctf_integer(unsigned long, reclaimed, reclaimed) + ctf_integer(unsigned long, heap, nh) + ctf_integer(unsigned long, old_heap, oh) ) ) -- cgit v1.2.3 From 262d3d9291d5dcd2530d5a0d3170e9dc0345a002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 17 Mar 2016 18:21:09 +0100 Subject: 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 --- lib/runtime_tools/c_src/dyntrace.c | 232 ++++++++++++++++++------------- lib/runtime_tools/c_src/dyntrace_lttng.h | 3 + lib/runtime_tools/src/dyntrace.erl | 43 +++++- 3 files changed, 171 insertions(+), 107 deletions(-) (limited to 'lib') 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 %%% -- cgit v1.2.3 From a80b7eeb9927309cdbc68296ca9892486a3a8707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 20 Apr 2016 11:47:16 +0200 Subject: runtime_tools: Extend 'trace' and 'enabled' tracer callbacks Adds the following capabilities to dyntrace * enabled_running_ports/3 * enabled_running_procs/3 changed from enabled_running/3 * trace_running_ports/6 * trace_running_procs/6 changed from trace_running/6 --- lib/runtime_tools/c_src/dyntrace.c | 56 +++++++++++++++++++++++++++----- lib/runtime_tools/c_src/dyntrace_lttng.h | 15 +++++++++ lib/runtime_tools/src/dyntrace.erl | 16 ++++++--- 3 files changed, 74 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 58a20691f7..773a5f67ec 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -72,7 +72,8 @@ 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[]); +static ERL_NIF_TERM trace_running_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace_running_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM trace_call(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[]); @@ -80,7 +81,8 @@ static ERL_NIF_TERM trace_garbage_collection(ErlNifEnv* env, int argc, const ERL 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_running_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM enabled_running_ports(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[]); @@ -96,14 +98,16 @@ static ErlNifFunc nif_funcs[] = { #ifdef HAVE_USE_LTTNG {"trace_procs", 6, trace_procs}, {"trace_ports", 6, trace_ports}, - {"trace_running", 6, trace_running}, + {"trace_running_procs", 6, trace_running_procs}, + {"trace_running_ports", 6, trace_running_ports}, {"trace_call", 6, trace_call}, {"trace_send", 6, trace_send}, {"trace_receive", 6, trace_receive}, {"trace_garbage_collection", 6, trace_garbage_collection}, {"enabled_procs", 3, enabled_procs}, {"enabled_ports", 3, enabled_ports}, - {"enabled_running", 3, enabled_running}, + {"enabled_running_procs", 3, enabled_running_procs}, + {"enabled_running_ports", 3, enabled_running_ports}, {"enabled_call", 3, enabled_call}, {"enabled_send", 3, enabled_send}, {"enabled_receive", 3, enabled_receive}, @@ -677,7 +681,7 @@ static ERL_NIF_TERM trace_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg return atom_ok; } -static ERL_NIF_TERM enabled_running(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM enabled_running_procs(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ASSERT(argc == 3); @@ -687,15 +691,15 @@ static ERL_NIF_TERM enabled_running(ErlNifEnv *env, int argc, const ERL_NIF_TERM return atom_discard; } -static ERL_NIF_TERM trace_running(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM trace_running_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { lttng_decl_procbuf(pid); const ERL_NIF_TERM* tuple; char *mfastr = "undefined"; int arity; + lttng_decl_mfabuf(mfa); lttng_pid_to_str(argv[2], pid); - lttng_decl_mfabuf(mfa); if (enif_get_tuple(env, argv[3], &arity, &tuple)) { int val; @@ -703,8 +707,7 @@ static ERL_NIF_TERM trace_running(ErlNifEnv* env, int argc, const ERL_NIF_TERM a lttng_mfa_to_str(tuple[0], tuple[1], val, mfa); mfastr = mfa; } - - /* running */ + /* running processes */ if (argv[0] == atom_in) { LTTNG3(process_scheduled, pid, mfastr, "in"); } else if (argv[0] == atom_out) { @@ -717,6 +720,41 @@ 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"); } + + return atom_ok; +} + +static ERL_NIF_TERM enabled_running_ports(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + ASSERT(argc == 3); + + if (LTTNG_ENABLED(port_scheduled)) + return atom_trace; + + return atom_discard; +} + +static ERL_NIF_TERM trace_running_ports(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + lttng_decl_procbuf(pid); + lttng_decl_mfabuf(where); + + lttng_portid_to_str(argv[2], pid); + erts_snprintf(where, LTTNG_BUFFER_SZ, "%T", argv[3]); + + /* running ports */ + if (argv[0] == atom_in) { + LTTNG3(port_scheduled, pid, where, "in"); + } else if (argv[0] == atom_out) { + LTTNG3(port_scheduled, pid, where, "out"); + /* exiting */ + } else if (argv[0] == atom_in_exiting) { + LTTNG3(port_scheduled, pid, where, "in_exiting"); + } else if (argv[0] == atom_out_exiting) { + LTTNG3(port_scheduled, pid, where, "out_exiting"); + } else if (argv[0] == atom_out_exited) { + LTTNG3(port_scheduled, pid, where, "out_exited"); + } 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 541a6c16e8..3550a1cab5 100644 --- a/lib/runtime_tools/c_src/dyntrace_lttng.h +++ b/lib/runtime_tools/c_src/dyntrace_lttng.h @@ -196,6 +196,21 @@ TRACEPOINT_EVENT( ) ) +TRACEPOINT_EVENT( + com_ericsson_dyntrace, + port_scheduled, + TP_ARGS( + char*, p, + char*, op, + char*, type + ), + TP_FIELDS( + ctf_string(pid, p) + ctf_string(entry, op) + ctf_string(type, type) + ) +) + /* Call tracing */ TRACEPOINT_EVENT( diff --git a/lib/runtime_tools/src/dyntrace.erl b/lib/runtime_tools/src/dyntrace.erl index 8a449e5749..28e6d67d96 100644 --- a/lib/runtime_tools/src/dyntrace.erl +++ b/lib/runtime_tools/src/dyntrace.erl @@ -45,7 +45,8 @@ trace/6, trace_procs/6, trace_ports/6, - trace_running/6, + trace_running_procs/6, + trace_running_ports/6, trace_call/6, trace_send/6, trace_receive/6, @@ -53,7 +54,8 @@ -export([enabled_procs/3, enabled_ports/3, - enabled_running/3, + enabled_running_procs/3, + enabled_running_ports/3, enabled_call/3, enabled_send/3, enabled_receive/3, @@ -157,7 +159,10 @@ trace_procs(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, trace_ports(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). -trace_running(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> +trace_running_procs(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> + erlang:nif_error(nif_not_loaded). + +trace_running_ports(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> erlang:nif_error(nif_not_loaded). trace_call(_TraceTag, _TracerState, _Tracee, _FirstTraceTerm, _SecondTraceTerm, _Opts) -> @@ -181,7 +186,10 @@ enabled_procs(_TraceTag, _TracerState, _Tracee) -> enabled_ports(_TraceTag, _TracerState, _Tracee) -> erlang:nif_error(nif_not_loaded). -enabled_running(_TraceTag, _TracerState, _Tracee) -> +enabled_running_procs(_TraceTag, _TracerState, _Tracee) -> + erlang:nif_error(nif_not_loaded). + +enabled_running_ports(_TraceTag, _TracerState, _Tracee) -> erlang:nif_error(nif_not_loaded). enabled_call(_TraceTag, _TracerState, _Tracee) -> -- cgit v1.2.3 From 30bdb63be449ac92c98e35cf1d2ec7729981f5b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 18 Apr 2016 14:46:54 +0200 Subject: runtime_tools: Add lttng dyntrace tests --- lib/runtime_tools/test/Makefile | 1 + lib/runtime_tools/test/dyntrace_lttng_SUITE.erl | 293 ++++++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 lib/runtime_tools/test/dyntrace_lttng_SUITE.erl (limited to 'lib') diff --git a/lib/runtime_tools/test/Makefile b/lib/runtime_tools/test/Makefile index 432a361468..61377ea09e 100644 --- a/lib/runtime_tools/test/Makefile +++ b/lib/runtime_tools/test/Makefile @@ -4,6 +4,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk MODULES = \ dyntrace_SUITE \ + dyntrace_lttng_SUITE \ runtime_tools_SUITE \ system_information_SUITE \ dbg_SUITE \ diff --git a/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl b/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl new file mode 100644 index 0000000000..185819f348 --- /dev/null +++ b/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl @@ -0,0 +1,293 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% +-module(dyntrace_lttng_SUITE). +-include_lib("common_test/include/ct.hrl"). + +-export([all/0, suite/0]). +-export([init_per_suite/1, end_per_suite/1]). +-export([init_per_testcase/2, end_per_testcase/2]). + +%% Test cases +-export([t_lttng_list/1, + t_procs/1, + t_ports/1, + t_running_process/1, + t_running_port/1, + t_call/1, + t_send/1, + t_receive/1, + t_garbage_collection/1]). + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {seconds, 10}}]. + +all() -> + [t_lttng_list, + t_procs, + t_ports, + t_running_process, + t_running_port, + t_call, + t_send, + t_receive, + t_garbage_collection]. + + + +init_per_suite(Config) -> + case erlang:system_info(dynamic_trace) of + lttng -> + ensure_lttng_stopped("--all"), + Config; + _ -> + {skip, "No LTTng configured on system."} + end. + +end_per_suite(_Config) -> + ensure_lttng_stopped("--all"), + ok. + +init_per_testcase(Case, Config) -> + %% ensure loaded + _ = dyntrace:module_info(), + Name = atom_to_list(Case), + ok = ensure_lttng_started(Name, Config), + [{session, Name}|Config]. + +end_per_testcase(Case, _Config) -> + Name = atom_to_list(Case), + ok = ensure_lttng_stopped(Name), + ok. + +%% tracepoints +%% +%% com_ericsson_dyntrace:gc_major_end +%% com_ericsson_dyntrace:gc_major_start +%% com_ericsson_dyntrace:gc_minor_end +%% com_ericsson_dyntrace:gc_minor_start +%% com_ericsson_dyntrace:message_receive +%% com_ericsson_dyntrace:message_send +%% -com_ericsson_dyntrace:message_queued +%% com_ericsson_dyntrace:function_exception +%% com_ericsson_dyntrace:function_return +%% com_ericsson_dyntrace:function_call +%% com_ericsson_dyntrace:port_link +%% com_ericsson_dyntrace:port_exit +%% com_ericsson_dyntrace:port_open +%% com_ericsson_dyntrace:process_scheduled +%% com_ericsson_dyntrace:process_register +%% com_ericsson_dyntrace:process_exit +%% com_ericsson_dyntrace:process_link +%% com_ericsson_dyntrace:process_spawn +%% +%% Testcases +%% + +t_lttng_list(_Config) -> + {ok, _} = cmd("lttng list -u"), + ok. + +t_procs(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:process_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},procs]), + + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + timer:sleep(1000), + + _ = erlang:trace(all, false, [procs]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("com_ericsson_dyntrace:process_spawn", Res), + ok = check_tracepoint("com_ericsson_dyntrace:process_link", Res), + ok = check_tracepoint("com_ericsson_dyntrace:process_exit", Res), + ok = check_tracepoint("com_ericsson_dyntrace:process_register", Res), + ok. + +t_ports(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:port_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},ports]), + + _ = os:cmd("ls"), + + _ = erlang:trace(all, false, [{tracer, dyntrace, []},ports]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("com_ericsson_dyntrace:port_open", Res), + ok = check_tracepoint("com_ericsson_dyntrace:port_link", Res), + ok = check_tracepoint("com_ericsson_dyntrace:port_exit", Res), + ok. + +t_running_process(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:process_scheduled", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},running]), + + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + timer:sleep(1000), + + _ = erlang:trace(all, false, [running]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("com_ericsson_dyntrace:process_scheduled", Res), + ok. + +t_running_port(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:port_scheduled", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},running_ports]), + + _ = os:cmd("ls"), + _ = os:cmd("ls"), + + _ = erlang:trace(all, false, [running_ports]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("com_ericsson_dyntrace:port_scheduled", Res), + ok. + + +t_call(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:function_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []}, call]), + _ = erlang:trace_pattern({?MODULE, '_', '_'}, [{'_',[],[{exception_trace}]}], [local]), + + DontLink = spawn(fun() -> foo_clause_exception(nope) end), + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + + timer:sleep(10), + undefined = erlang:process_info(DontLink), + + _ = erlang:trace_pattern({?MODULE, '_', '_'}, false, [local]), + _ = erlang:trace(all, false, [call]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("com_ericsson_dyntrace:function_call", Res), + ok = check_tracepoint("com_ericsson_dyntrace:function_return", Res), + ok = check_tracepoint("com_ericsson_dyntrace:function_exception", Res), + ok. + +t_send(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:message_send", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},send]), + + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + _ = os:cmd("ls"), + timer:sleep(10), + + _ = erlang:trace(all, false, [send]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("com_ericsson_dyntrace:message_send", Res), + ok. + +t_receive(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:message_receive", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},'receive']), + + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + timer:sleep(10), + _ = erlang:trace(all, false, ['receive']), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("com_ericsson_dyntrace:message_receive", Res), + ok. + +t_garbage_collection(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:gc_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},garbage_collection]), + + Pid = spawn_link(fun() -> gcfier() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + timer:sleep(10), + _ = erlang:trace(all, false, [garbage_collection]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("com_ericsson_dyntrace:gc_major_start", Res), + ok = check_tracepoint("com_ericsson_dyntrace:gc_major_end", Res), + ok = check_tracepoint("com_ericsson_dyntrace:gc_minor_start", Res), + ok = check_tracepoint("com_ericsson_dyntrace:gc_minor_end", Res), + ok. + +%% aux + +gcfier() -> + receive + {Pid, ok} -> + _ = lists:reverse(lists:seq(1,10000)), + true = erlang:garbage_collect(), + Pid ! {self(), ok} + end. + + +waiter() -> + true = register(?MODULE, self()), + receive + {Pid, ok} -> + Child = spawn(fun() -> receive ok -> ok end end), + link(Child), + unlink(Child), + _ = lists:seq(1,1000), + Child ! ok, + true = unregister(?MODULE), + Pid ! {self(),ok} + end. + +foo_clause_exception({1,2}) -> badness. + +%% lttng +lttng_stop_and_view(Config) -> + Path = proplists:get_value(priv_dir, Config), + Name = proplists:get_value(session, Config), + {ok,_} = cmd("lttng stop " ++ Name), + {ok,Res} = cmd("lttng view " ++ Name ++ " --trace-path=" ++ Path), + Res. + +check_tracepoint(TP, Data) -> + case re:run(Data, TP, [global]) of + {match, _} -> ok; + _ -> notfound + end. + +lttng_start_event(Event, Config) -> + Name = proplists:get_value(session, Config), + {ok, _} = cmd("lttng enable-event -u " ++ Event ++ " --session=" ++ Name), + {ok, _} = cmd("lttng start " ++ Name), + ok. + +ensure_lttng_started(Name, Config) -> + Out = case proplists:get_value(priv_dir, Config) of + undefined -> []; + Path -> "--output="++Path++" " + end, + {ok,_} = cmd("lttng create " ++ Out ++ Name), + ok. + +ensure_lttng_stopped(Name) -> + {ok,_} = cmd("lttng stop"), + {ok,_} = cmd("lttng destroy " ++ Name), + ok. + +cmd(Cmd) -> + io:format("<< ~ts~n", [Cmd]), + Res = os:cmd(Cmd), + io:format(">> ~ts~n", [Res]), + {ok,Res}. -- cgit v1.2.3 From fe7289591703d5eb151a74a01a278f38497529d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 20 Apr 2016 20:34:34 +0200 Subject: runtime_tools: Add 'return_to' for call tracing --- lib/runtime_tools/c_src/dyntrace.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'lib') diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 773a5f67ec..3d940ecd54 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -177,6 +177,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_return_to; static ERL_NIF_TERM atom_exception_from; #endif @@ -239,6 +240,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_return_to = enif_make_atom(env,"return_to"); atom_exception_from = enif_make_atom(env,"exception_from"); #endif @@ -454,6 +456,18 @@ static ERL_NIF_TERM trace_call(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv int arity; lttng_decl_mfabuf(mfa); + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { + enif_get_uint(env, tuple[2], &len); + lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); + LTTNG3(function_return, pid, mfa, 0); + } else { + LTTNG3(function_return, pid, undef, 0); + } + } else if (argv[0] == atom_return_to) { + const ERL_NIF_TERM* tuple; + int arity; + lttng_decl_mfabuf(mfa); + if (enif_get_tuple(env, argv[3], &arity, &tuple)) { enif_get_uint(env, tuple[2], &len); lttng_mfa_to_str(tuple[0], tuple[1], len, mfa); -- cgit v1.2.3 From 4169ddb041eb85afd89d4ad0929c8fa9e88fb14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 20 Apr 2016 20:35:43 +0200 Subject: runtime_tools: Update dyntrace_lttng_SUITE tests --- lib/runtime_tools/test/dyntrace_lttng_SUITE.erl | 92 +++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl b/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl index 185819f348..e6c147b003 100644 --- a/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl +++ b/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl @@ -31,9 +31,12 @@ t_running_process/1, t_running_port/1, t_call/1, + t_call_return_to/1, + t_call_silent/1, t_send/1, t_receive/1, - t_garbage_collection/1]). + t_garbage_collection/1, + t_all/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -46,10 +49,12 @@ all() -> t_running_process, t_running_port, t_call, + t_call_return_to, + t_call_silent, t_send, t_receive, - t_garbage_collection]. - + t_garbage_collection, + t_all]. init_per_suite(Config) -> @@ -92,6 +97,7 @@ end_per_testcase(Case, _Config) -> %% com_ericsson_dyntrace:port_link %% com_ericsson_dyntrace:port_exit %% com_ericsson_dyntrace:port_open +%% com_ericsson_dyntrace:port_scheduled %% com_ericsson_dyntrace:process_scheduled %% com_ericsson_dyntrace:process_register %% com_ericsson_dyntrace:process_exit @@ -198,6 +204,46 @@ t_send(Config) when is_list(Config) -> ok = check_tracepoint("com_ericsson_dyntrace:message_send", Res), ok. +t_call_return_to(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:function_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []}, call, return_to]), + _ = erlang:trace_pattern({lists, '_', '_'}, true, [local]), + _ = erlang:trace_pattern({?MODULE, '_', '_'}, true, [local]), + + Pid = spawn_link(fun() -> gcfier(10) end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + timer:sleep(10), + + _ = erlang:trace_pattern({?MODULE, '_', '_'}, false, [local]), + _ = erlang:trace_pattern({lists, '_', '_'}, false, [local]), + _ = erlang:trace(all, false, [call,return_to]), + Res = lttng_stop_and_view(Config), + ok = check_tracepoint("com_ericsson_dyntrace:function_call", Res), + ok. + +t_call_silent(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:function_*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []}, call, silent]), + _ = erlang:trace_pattern({?MODULE, '_', '_'}, [{'_',[],[{exception_trace}]}], [local]), + + DontLink = spawn(fun() -> foo_clause_exception(nope) end), + Pid = spawn_link(fun() -> waiter() end), + Pid ! {self(), ok}, + ok = receive {Pid,ok} -> ok end, + + timer:sleep(10), + undefined = erlang:process_info(DontLink), + + _ = erlang:trace_pattern({?MODULE, '_', '_'}, false, [local]), + _ = erlang:trace(all, false, [call]), + Res = lttng_stop_and_view(Config), + notfound = check_tracepoint("com_ericsson_dyntrace:function_call", Res), + notfound = check_tracepoint("com_ericsson_dyntrace:function_return", Res), + notfound = check_tracepoint("com_ericsson_dyntrace:function_exception", Res), + ok. + + t_receive(Config) when is_list(Config) -> ok = lttng_start_event("com_ericsson_dyntrace:message_receive", Config), _ = erlang:trace(new, true, [{tracer, dyntrace, []},'receive']), @@ -227,12 +273,50 @@ t_garbage_collection(Config) when is_list(Config) -> ok = check_tracepoint("com_ericsson_dyntrace:gc_minor_end", Res), ok. +t_all(Config) when is_list(Config) -> + ok = lttng_start_event("com_ericsson_dyntrace:*", Config), + _ = erlang:trace(new, true, [{tracer, dyntrace, []},all]), + + Pid1 = spawn_link(fun() -> waiter() end), + Pid1 ! {self(), ok}, + ok = receive {Pid1,ok} -> ok end, + + Pid2 = spawn_link(fun() -> gcfier() end), + Pid2 ! {self(), ok}, + ok = receive {Pid2,ok} -> ok end, + _ = os:cmd("ls"), + _ = os:cmd("ls"), + timer:sleep(10), + + _ = erlang:trace(all, false, [all]), + Res = lttng_stop_and_view(Config), + + ok = check_tracepoint("com_ericsson_dyntrace:process_spawn", Res), + ok = check_tracepoint("com_ericsson_dyntrace:process_link", Res), + ok = check_tracepoint("com_ericsson_dyntrace:process_exit", Res), + ok = check_tracepoint("com_ericsson_dyntrace:process_register", Res), + ok = check_tracepoint("com_ericsson_dyntrace:port_open", Res), + ok = check_tracepoint("com_ericsson_dyntrace:port_link", Res), + ok = check_tracepoint("com_ericsson_dyntrace:port_exit", Res), + ok = check_tracepoint("com_ericsson_dyntrace:process_scheduled", Res), + ok = check_tracepoint("com_ericsson_dyntrace:port_scheduled", Res), + ok = check_tracepoint("com_ericsson_dyntrace:message_send", Res), + ok = check_tracepoint("com_ericsson_dyntrace:message_receive", Res), + ok = check_tracepoint("com_ericsson_dyntrace:gc_major_start", Res), + ok = check_tracepoint("com_ericsson_dyntrace:gc_major_end", Res), + ok = check_tracepoint("com_ericsson_dyntrace:gc_minor_start", Res), + ok = check_tracepoint("com_ericsson_dyntrace:gc_minor_end", Res), + ok. + + %% aux gcfier() -> + gcfier(10000). +gcfier(N) -> receive {Pid, ok} -> - _ = lists:reverse(lists:seq(1,10000)), + _ = lists:reverse(lists:seq(1,N)), true = erlang:garbage_collect(), Pid ! {self(), ok} end. -- cgit v1.2.3 From 2a646e161e5b73ad6984df8dc2fcb8fdba2e0df7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Fri, 22 Apr 2016 17:06:33 +0200 Subject: tools: Update fprof with new gc traces --- lib/tools/src/fprof.erl | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl index f9da748fef..b21eedc625 100644 --- a/lib/tools/src/fprof.erl +++ b/lib/tools/src/fprof.erl @@ -1629,15 +1629,24 @@ trace_handler({trace_ts, Pid, in, {_M, _F, Args} = MFArgs, TS} = Trace, TS; %% %% gc_start -trace_handler({trace_ts, Pid, gc_start, _Func, TS} = Trace, - Table, _, Dump) -> +trace_handler({trace_ts, Pid, gc_minor_start, _Func, TS} = Trace, Table, _, Dump) -> + dump_stack(Dump, get(Pid), Trace), + trace_gc_start(Table, Pid, TS), + TS; + +trace_handler({trace_ts, Pid, gc_major_start, _Func, TS} = Trace, Table, _, Dump) -> dump_stack(Dump, get(Pid), Trace), trace_gc_start(Table, Pid, TS), TS; + %% %% gc_end -trace_handler({trace_ts, Pid, gc_end, _Func, TS} = Trace, - Table, _, Dump) -> +trace_handler({trace_ts, Pid, gc_minor_end, _Func, TS} = Trace, Table, _, Dump) -> + dump_stack(Dump, get(Pid), Trace), + trace_gc_end(Table, Pid, TS), + TS; + +trace_handler({trace_ts, Pid, gc_major_end, _Func, TS} = Trace, Table, _, Dump) -> dump_stack(Dump, get(Pid), Trace), trace_gc_end(Table, Pid, TS), TS; -- cgit v1.2.3 From 429e53911a35aebb3d62f38d2246119df9aaa4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Fri, 22 Apr 2016 17:06:52 +0200 Subject: tools: Update fprof tests --- lib/tools/test/fprof_SUITE.erl | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/tools/test/fprof_SUITE.erl b/lib/tools/test/fprof_SUITE.erl index e18d384b52..affb45b7a6 100644 --- a/lib/tools/test/fprof_SUITE.erl +++ b/lib/tools/test/fprof_SUITE.erl @@ -949,8 +949,8 @@ handle_trace({trace_ts,Pid,return_to,MFA,TS},P) -> end, put({Pid,last_ts},TS), P; -handle_trace({trace_ts,Pid,gc_start,_,TS},P) -> - ?dbg("~p",[{{gc_start,Pid},get(Pid)}]), +handle_trace({trace_ts,Pid,gc_minor_start,_,TS},P) -> + ?dbg("~p",[{{gc_minor_start,Pid},get(Pid)}]), case get(Pid) of [suspend|_] = Stack -> T = ts_sub(TS,get({Pid,last_ts})), @@ -970,8 +970,40 @@ handle_trace({trace_ts,Pid,gc_start,_,TS},P) -> end, put({Pid,last_ts},TS), P; -handle_trace({trace_ts,Pid,gc_end,_,TS},P) -> - ?dbg("~p",[{{gc_end,Pid},get(Pid)}]), +handle_trace({trace_ts,Pid,gc_major_start,_,TS},P) -> + ?dbg("~p",[{{gc_minor_start,Pid},get(Pid)}]), + case get(Pid) of + [suspend|_] = Stack -> + T = ts_sub(TS,get({Pid,last_ts})), + insert(Pid,garbage_collect), + update_acc(Pid,Stack,T), + put(Pid,[garbage_collect|Stack]); + [CallingMFA|_] = Stack -> + T = ts_sub(TS,get({Pid,last_ts})), + insert(Pid,garbage_collect), + update_own(Pid,CallingMFA,T), + update_acc(Pid,Stack,T), + put(Pid,[garbage_collect|Stack]); + undefined -> + put(first_ts,TS), + put(Pid,[garbage_collect]), + insert(Pid,garbage_collect) + end, + put({Pid,last_ts},TS), + P; +handle_trace({trace_ts,Pid,gc_minor_end,_,TS},P) -> + ?dbg("~p",[{{gc_minor_end,Pid},get(Pid)}]), + T = ts_sub(TS,get({Pid,last_ts})), + case get(Pid) of + [garbage_collect|RestOfStack] = Stack -> + update_own(Pid,garbage_collect,T), + update_acc(Pid,Stack,T), + put(Pid,RestOfStack) + end, + put({Pid,last_ts},TS), + P; +handle_trace({trace_ts,Pid,gc_major_end,_,TS},P) -> + ?dbg("~p",[{{gc_major_end,Pid},get(Pid)}]), T = ts_sub(TS,get({Pid,last_ts})), case get(Pid) of [garbage_collect|RestOfStack] = Stack -> -- cgit v1.2.3 From 303777ddcbf59ab892cb649621b9df8adfe714aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 25 Apr 2016 11:51:33 +0200 Subject: runtime_tools: Fix Dtrace build --- lib/runtime_tools/c_src/dyntrace.c | 55 +++----------------------------------- 1 file changed, 3 insertions(+), 52 deletions(-) (limited to 'lib') diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c index 3d940ecd54..0178d95efb 100644 --- a/lib/runtime_tools/c_src/dyntrace.c +++ b/lib/runtime_tools/c_src/dyntrace.c @@ -128,6 +128,7 @@ static ERL_NIF_TERM atom_badarg; static ERL_NIF_TERM atom_ok; static ERL_NIF_TERM atom_trace; +static ERL_NIF_TERM atom_seq_trace; static ERL_NIF_TERM atom_remove; static ERL_NIF_TERM atom_discard; @@ -191,6 +192,7 @@ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_ok = enif_make_atom(env,"ok"); atom_trace = enif_make_atom(env,"trace"); + atom_seq_trace = enif_make_atom(env,"seq_trace"); atom_remove = enif_make_atom(env,"remove"); atom_discard = enif_make_atom(env,"discard"); @@ -285,19 +287,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[]) { -#ifdef HAVE_USE_DTRACE - ErlNifPid to; +#ifdef HAVE_USE_LTTNG 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; -#elif HAVE_USE_LTTNG return atom_trace; #endif return atom_remove; @@ -305,46 +296,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 - 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; } -- cgit v1.2.3 From 535aec73c5af7c7e2f48f29ad35d2319d91b9c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 27 Apr 2016 18:55:43 +0200 Subject: runtime_tools: User's guide to LTTng and dyntrace --- lib/runtime_tools/doc/src/LTTng.xml | 245 ++++++++++++++++++++++++++++++++++++ lib/runtime_tools/doc/src/Makefile | 2 +- lib/runtime_tools/doc/src/part.xml | 1 + 3 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 lib/runtime_tools/doc/src/LTTng.xml (limited to 'lib') diff --git a/lib/runtime_tools/doc/src/LTTng.xml b/lib/runtime_tools/doc/src/LTTng.xml new file mode 100644 index 0000000000..eab1848e88 --- /dev/null +++ b/lib/runtime_tools/doc/src/LTTng.xml @@ -0,0 +1,245 @@ + + + +
+ + 20162016 + Ericsson AB. All Rights Reserved. + + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + LTTng and Erlang/OTP + + + + + + 2016-04-27 + + LTTng.xml +
+ +
+ Introduction +

The Linux Trace Toolkit: next generation is an open source system software package + for correlated tracing of the Linux kernel, user applications and libraries.

+

For more information, please visit http://lttng.org

+
+ +
+ Building Erlang/OTP with LTTng support +

+ Configure and build Erlang with LTTng support: +

+

For LTTng to work properly with Erlang/OTP you need + the following packages installed:

+ + +

LTTng-tools: a command line interface to control tracing sessions.

+

LTTng-UST: user space tracing library.

+
+ +

On Ubuntu this can be installed via aptitude:

+ + $ sudo aptitude install lttng-tools liblttng-ust-dev +

See Installing LTTng + for more information on how to install LTTng on your system.

+ +

After LTTng is properly installed on the system Erlang/OTP can be built with LTTng support.

+ + +$ ./configure --with-dynamic-trace=lttng +$ make +
+ +
+ Dyntrace Tracepoints +

All tracepoints are in the domain of com_ericsson_dyntrace

+

All Erlang types are the string equivalent in LTTng.

+ +

process_spawn

+ + pid : string :: Process ID. Ex. "<0.131.0>" + parent : string :: Process ID. Ex. "<0.131.0>" + entry : string :: Code Location. Ex. "lists:sort/1" + +

Example:

+

process_spawn: { cpu_id = 3 }, { pid = "<0.131.0>", parent = "<0.130.0>", entry = "erlang:apply/2" }

+ +

process_link

+ + to : string :: Process ID or Port ID. Ex. "<0.131.0>" + from : string :: Process ID or Port ID. Ex. "<0.131.0>" + type : string :: "link" | "unlink" + +

Example:

+

process_link: { cpu_id = 3 }, { from = "<0.130.0>", to = "<0.131.0>", type = "link" }

+ + +

process_exit

+ + pid : string :: Process ID. Ex. "<0.131.0>" + reason : string :: Exit reason. Ex. "normal" + +

Example:

+

process_exit: { cpu_id = 3 }, { pid = "<0.130.0>", reason = "normal" }

+ +

process_register

+ + pid : string :: Process ID. Ex. "<0.131.0>" + name : string :: Registered name. Ex. "error_logger" + type : string :: "register" | "unregister" + +

Example:

+

process_register: { cpu_id = 0 }, { pid = "<0.128.0>", name = "dyntrace_lttng_SUITE" type = "register" }

+ +

process_scheduled

+ + pid : string :: Process ID. Ex. "<0.131.0>" + entry : string :: Code Location. Ex. "lists:sort/1" + type : string :: "in" | "out" | "in_exiting" | "out_exiting" | "out_exited" + + +

Example:

+

process_scheduled: { cpu_id = 0 }, { pid = "<0.136.0>", entry = "erlang:apply/2", type = "in" }

+ + +

port_open

+ + pid : string :: Process ID. Ex. "<0.131.0>" + driver : string :: Driver name. Ex. "efile" + port : string :: Port ID. Ex. "#Port<0.1031>" + + +

Example:

+

port_open: { cpu_id = 5 }, { pid = "<0.131.0>", driver = "'/bin/sh -s unix:cmd'", port = "#Port<0.1887>" }

+ +

port_exit

+ + port : string :: Port ID. Ex. "#Port<0.1031>" + reason : string :: Exit reason. Ex. "normal" + +

Example:

+

port_exit: { cpu_id = 5 }, { port = "#Port<0.1887>", reason = "normal" }

+ +

port_link

+ + to : string :: Process ID. Ex. "<0.131.0>" + from : string :: Process ID. Ex. "<0.131.0>" + type : string :: "link" | "unlink" + +

Example:

+

port_link: { cpu_id = 5 }, { from = "#Port<0.1887>", to = "<0.131.0>", type = "unlink" }

+ +

port_scheduled

+ + port : string :: Port ID. Ex. "#Port<0.1031>" + entry : string :: Callback. Ex. "open" + type : string :: "in" | "out" | "in_exiting" | "out_exiting" | "out_exited" + + +

Example:

+

port_scheduled: { cpu_id = 5 }, { pid = "#Port<0.1905>", entry = "close", type = "out" }

+ +

function_call

+ + pid : string :: Process ID. Ex. "<0.131.0>" + entry : string :: Code Location. Ex. "lists:sort/1" + depth : integer :: Stack depth. Ex. 0 + +

Example:

+

function_call: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:'-t_call/1-fun-1-'/0", depth = 0 }

+ +

function_return

+ + pid : string :: Process ID. Ex. "<0.131.0>" + entry : string :: Code Location. Ex. "lists:sort/1" + depth : integer :: Stack depth. Ex. 0 + +

Example:

+

function_return: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:waiter/0", depth = 0 }

+ +

function_exception

+ + pid : string :: Process ID. Ex. "<0.131.0>" + entry : string :: Code Location. Ex. "lists:sort/1" + class : string :: Error reason. Ex. "error" + +

Example:

+

function_exception: { cpu_id = 5 }, { pid = "<0.144.0>", entry = "t:call_exc/1", class = "error" }

+ +

message_send

+ + from : string :: Process ID or Port ID. Ex. "<0.131.0>" + to : string :: Process ID or Port ID. Ex. "<0.131.0>" + message : string :: Message sent. Ex. "{<0.162.0>,ok}" + +

Example:

+

message_send: { cpu_id = 3 }, { from = "#Port<0.1938>", to = "<0.160.0>", message = "{#Port<0.1938>,eof}" }

+ +

message_receive

+ + to : string :: Process ID or Port ID. Ex. "<0.131.0>" + message : string :: Message received. Ex. "{<0.162.0>,ok}" + +

Example:

+

message_receive: { cpu_id = 7 }, { to = "<0.167.0>", message = "{<0.165.0>,ok}" }

+ +

gc_minor_start

+ + pid : string :: Process ID. Ex. "<0.131.0>" + need : integer :: Heap need. Ex. 2 + heap : integer :: Young heap word size. Ex. 233 + old_heap : integer :: Old heap word size. Ex. 233 + +

Example:

+

gc_minor_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 0, heap = 610, old_heap = 0 }

+ +

gc_minor_end

+ + pid : string :: Process ID. Ex. "<0.131.0>" + reclaimed : integer :: Heap reclaimed. Ex. 2 + heap : integer :: Young heap word size. Ex. 233 + old_heap : integer :: Old heap word size. Ex. 233 + +

Example:

+

gc_minor_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 120, heap = 1598, old_heap = 1598 }

+ +

gc_major_start

+ + pid : string :: Process ID. Ex. "<0.131.0>" + need : integer :: Heap need. Ex. 2 + heap : integer :: Young heap word size. Ex. 233 + old_heap : integer :: Old heap word size. Ex. 233 + +

Example:

+

gc_major_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 8, heap = 2586, old_heap = 1598 }

+ +

gc_major_end

+ + pid : string :: Process ID. Ex. "<0.131.0>" + reclaimed : integer :: Heap reclaimed. Ex. 2 + heap : integer :: Young heap word size. Ex. 233 + old_heap : integer :: Old heap word size. Ex. 233 + +

Example:

+

gc_major_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 240, heap = 4185, old_heap = 0 }

+ +
+ +
+ Examples +
+
diff --git a/lib/runtime_tools/doc/src/Makefile b/lib/runtime_tools/doc/src/Makefile index 0a590ff9ec..5ce40bb995 100644 --- a/lib/runtime_tools/doc/src/Makefile +++ b/lib/runtime_tools/doc/src/Makefile @@ -45,7 +45,7 @@ XML_REF3_FILES = dbg.xml dyntrace.xml erts_alloc_config.xml system_information.x XML_REF6_FILES = runtime_tools_app.xml XML_PART_FILES = part_notes.xml part_notes_history.xml part.xml -XML_CHAPTER_FILES = notes.xml notes_history.xml +XML_CHAPTER_FILES = notes.xml notes_history.xml LTTng.xml GENERATED_XML_FILES = DTRACE.xml SYSTEMTAP.xml diff --git a/lib/runtime_tools/doc/src/part.xml b/lib/runtime_tools/doc/src/part.xml index 14e8b71c83..34acf69fc8 100644 --- a/lib/runtime_tools/doc/src/part.xml +++ b/lib/runtime_tools/doc/src/part.xml @@ -34,6 +34,7 @@

Runtime Tools

+ -- cgit v1.2.3