aboutsummaryrefslogtreecommitdiffstats
path: root/lib/runtime_tools/c_src/dyntrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/runtime_tools/c_src/dyntrace.c')
-rw-r--r--lib/runtime_tools/c_src/dyntrace.c637
1 files changed, 623 insertions, 14 deletions
diff --git a/lib/runtime_tools/c_src/dyntrace.c b/lib/runtime_tools/c_src/dyntrace.c
index eef03afd1c..3d2de9c21c 100644
--- a/lib/runtime_tools/c_src/dyntrace.c
+++ b/lib/runtime_tools/c_src/dyntrace.c
@@ -1,18 +1,19 @@
/*
* %CopyrightBegin%
*
- * Copyright Scott Lystig Fritchie 2011-2012. All Rights Reserved.
+ * Copyright Scott Lystig Fritchie 2011-2016. All Rights Reserved.
*
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
+ * 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
*
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
+ * 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%
*/
@@ -28,10 +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
-#ifdef HAVE_USE_DTRACE
-#include "dtrace_user.h"
+#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);
@@ -62,11 +66,55 @@ 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[]);
+
+#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_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[]);
+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_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[]);
+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}
+ {"user_trace_n", 10, user_trace_n},
+#ifdef HAVE_USE_LTTNG
+ {"trace_procs", 5, trace_procs},
+ {"trace_ports", 5, trace_ports},
+ {"trace_running_procs", 5, trace_running_procs},
+ {"trace_running_ports", 5, trace_running_ports},
+ {"trace_call", 5, trace_call},
+ {"trace_send", 5, trace_send},
+ {"trace_receive", 5, trace_receive},
+ {"trace_garbage_collection", 5, trace_garbage_collection},
+ {"enabled_procs", 3, enabled_procs},
+ {"enabled_ports", 3, enabled_ports},
+ {"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},
+ {"enabled_garbage_collection", 3, enabled_garbage_collection},
+#endif
+ {"enabled", 3, enabled},
+ {"trace", 5, trace}
};
ERL_NIF_INIT(dyntrace, nif_funcs, load, NULL, NULL, NULL)
@@ -74,19 +122,131 @@ ERL_NIF_INIT(dyntrace, nif_funcs, load, NULL, NULL, NULL)
static ERL_NIF_TERM atom_true;
static ERL_NIF_TERM atom_false;
static ERL_NIF_TERM atom_error;
+static ERL_NIF_TERM atom_extra;
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_seq_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;
+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' */
+
+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;
+
+/* 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;
+
+/* 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;
+
+/* ports 'ports' */
+
+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_return_to;
+static ERL_NIF_TERM atom_exception_from;
+#endif
+
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
atom_true = enif_make_atom(env,"true");
atom_false = enif_make_atom(env,"false");
atom_error = enif_make_atom(env,"error");
+ atom_extra = enif_make_atom(env,"extra");
atom_not_available = enif_make_atom(env,"not_available");
atom_badarg = enif_make_atom(env,"badarg");
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");
+
+#ifdef HAVE_USE_LTTNG
+
+ /* gc */
+
+ 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' */
+
+ 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");
+
+ /* 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");
+
+ /* 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");
+
+ /* ports 'ports' */
+
+ 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_return_to = enif_make_atom(env,"return_to");
+ atom_exception_from = enif_make_atom(env,"exception_from");
+#endif
+
return 0;
}
@@ -125,3 +285,452 @@ 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_LTTNG
+ ASSERT(argc == 3);
+ return atom_trace;
+#endif
+ return atom_remove;
+}
+
+static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ 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[])
+{
+ lttng_decl_procbuf(pid);
+ ERL_NIF_TERM gci, tup;
+ const ERL_NIF_TERM *vals;
+ int arity;
+ unsigned long ohbsz, nhbsz, size;
+
+ ASSERT(argc == 5);
+
+ /* 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_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);
+ }
+ 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[])
+{
+ 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_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);
+ 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;
+ ERL_NIF_TERM extra;
+ int arity;
+ lttng_decl_mfabuf(mfa);
+ char class[LTTNG_BUFFER_SZ];
+
+ enif_get_map_value(env, argv[4], atom_extra, &extra);
+ enif_get_tuple(env, extra, &arity, &tuple);
+ enif_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);
+ }
+ }
+ 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[])
+{
+ ERL_NIF_TERM extra;
+ lttng_decl_procbuf(pid);
+ lttng_pid_to_str(argv[2], pid);
+
+ enif_get_map_value(env, argv[4], atom_extra, &extra);
+
+ if (argv[0] == atom_send) {
+ lttng_decl_procbuf(to);
+ char msg[LTTNG_BUFFER_SZ];
+
+ lttng_pid_to_str(extra, to);
+ enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]);
+
+ 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];
+
+ lttng_pid_to_str(extra, to);
+ enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]);
+ /* mark it as non existing ? */
+
+ LTTNG3(message_send, pid, to, msg);
+ }
+ 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[])
+{
+ if (argv[0] == atom_receive) {
+ lttng_decl_procbuf(pid);
+ char msg[LTTNG_BUFFER_SZ];
+
+ lttng_pid_to_str(argv[2], pid);
+ enif_snprintf(msg, LTTNG_BUFFER_SZ, "%T", argv[3]);
+
+ LTTNG2(message_receive, pid, msg);
+ }
+ return atom_ok;
+}
+
+static ERL_NIF_TERM enabled_procs(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{
+ ASSERT(argc == 3);
+
+ 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;
+ }
+
+ return atom_discard;
+}
+
+static ERL_NIF_TERM trace_procs(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ lttng_decl_procbuf(pid);
+ lttng_decl_procbuf(to);
+
+ lttng_pid_to_str(argv[2], pid);
+
+ /* spawn */
+ if (argv[0] == atom_spawn) {
+ ERL_NIF_TERM extra;
+ char undef[] = "undefined";
+ const ERL_NIF_TERM* tuple;
+ int arity;
+ unsigned int len;
+ lttng_decl_mfabuf(mfa);
+
+ lttng_pid_to_str(argv[3], to);
+
+ enif_get_map_value(env, argv[4], atom_extra, &extra);
+
+ if (enif_get_tuple(env, extra, &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(process_spawn, to, pid, mfa);
+ } else {
+ LTTNG3(process_spawn, to, pid, undef);
+ }
+
+ /* register */
+ } else if (argv[0] == atom_register) {
+ char name[LTTNG_BUFFER_SZ];
+ enif_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];
+ enif_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");
+ } 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];
+ enif_snprintf(reason, LTTNG_BUFFER_SZ, "%T", argv[3]);
+ LTTNG2(process_exit, pid, reason);
+ }
+ 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[])
+{
+ lttng_decl_portbuf(port);
+ lttng_decl_procbuf(to);
+
+ lttng_portid_to_str(argv[2], port);
+
+ /* open and closed */
+ if (argv[0] == atom_open) {
+ ERL_NIF_TERM extra;
+ char driver[LTTNG_BUFFER_SZ];
+ lttng_decl_procbuf(pid);
+ lttng_pid_to_str(argv[3], pid);
+ enif_get_map_value(env, argv[4], atom_extra, &extra);
+
+ enif_snprintf(driver, LTTNG_BUFFER_SZ, "%T", extra);
+ LTTNG3(port_open, pid, driver, port);
+ } else if (argv[0] == atom_closed) {
+ char reason[LTTNG_BUFFER_SZ];
+ enif_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");
+ }
+ return atom_ok;
+}
+
+static ERL_NIF_TERM enabled_running_procs(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_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);
+
+ 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 processes */
+ 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");
+ }
+
+ 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);
+ enif_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