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 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