aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.dtrace.md37
-rw-r--r--erts/emulator/Makefile.in6
-rw-r--r--erts/emulator/beam/beam_emu.c85
-rw-r--r--erts/emulator/beam/dist.c16
-rw-r--r--erts/emulator/beam/dtrace-wrapper.h9
-rw-r--r--erts/emulator/beam/erl_async.c10
-rw-r--r--erts/emulator/beam/erl_gc.c1
-rw-r--r--erts/emulator/beam/erl_message.c12
-rw-r--r--erts/emulator/beam/global.h69
-rw-r--r--erts/emulator/drivers/common/efile_drv.c26
-rw-r--r--erts/lib_src/common/erl_printf.c2
-rw-r--r--erts/preloaded/ebin/prim_file.beambin46840 -> 46736 bytes
-rw-r--r--erts/preloaded/src/prim_file.erl22
-rw-r--r--lib/dtrace/c_src/Makefile2
-rw-r--r--lib/dtrace/c_src/Makefile.in15
-rw-r--r--lib/dtrace/c_src/dtrace.c16
-rw-r--r--lib/dtrace/examples/dist.d14
-rw-r--r--lib/dtrace/examples/port1.d8
-rw-r--r--lib/dtrace/examples/process-scheduling.d2
-rw-r--r--lib/dtrace/src/dtrace.erl38
-rw-r--r--lib/kernel/src/file.erl8
-rw-r--r--lib/kernel/src/file_server.erl6
22 files changed, 216 insertions, 188 deletions
diff --git a/README.dtrace.md b/README.dtrace.md
index 71023dfe69..bbff233ed9 100644
--- a/README.dtrace.md
+++ b/README.dtrace.md
@@ -27,27 +27,17 @@ Goals
Supported platforms
-------------------
-The autoconf procedure is supported, I believe, for OS X/Snow Leopard
-and OpenSolaris/64-bit. Just add the `--enable-dtrace` option your
-command to run the `configure` script.
-
-The code has been only very lightly tested on OS X. It ought to
-compile on a Solaris 10 or OpenSolaris machine, but no promises yet.
-
-The autoconf stuff is ugly right now. It could use some cleaning up.
-For example:
-
-* After editing the `erlang_dtrace.d` file, you need to re-run the
-* top-level "configure" script in order to update `erlang_dtrace.h`.
-* `make clean` will remove `erlang_dtrace.h`. A build will fail
- unless the top-level "configure" script is re-run to re-create that
- file.
-* The `erlang_dtrace.h` file's location should probably be moved to an
- OTP platform-specific build dir, for example,
- `path/to/somewhere/i386-apple-darwin10.8.0`
-* There are probably some other build by-products that are also being
- put into the "wrong" directory, for example, `erlang_dtrace.o` for
- Solaris platforms.
+* OS X 10.6.x / Snow Leopard. It should also work for 10.7 / Lion,
+ but I haven't personally tested it.
+* Solaris 10. I have done limited testing on Solaris 11 and
+ OpenIndiana release 151a, and both appear to work.
+* FreeBSD 9.0, though please see the "FreeBSD 9.0 Release Notes"
+ section below!
+* Linux via SystemTap compatibility. Please see the file
+ `README.systemtap.md` for more details.
+
+Just add the `--enable-dtrace` option to your command when you run the
+`configure` script.
Contributions
-------------
@@ -61,9 +51,12 @@ To build from scratch, use this recipe. If you're an experienced Git
user and wish to add my repository as a remote repository, be my
guest. Just resume the recipe at command #4.
+NOTE: The `dtrace-experiment+michal2` branch is used for changes that
+can be applied to both R14B and R15 releases.
+
% git clone git://github.com/slfritchie/otp.git
% cd otp
- % git checkout -b dtrace-experiment origin/dtrace-experiment
+ % git checkout -b dtrace-experiment+michal2 origin/dtrace-experiment+michal2
% env ERL_TOP=`pwd` ./otp_build autoconf
% env ERL_TOP=`pwd` ./configure --enable-dtrace + whatever args you need
% env ERL_TOP=`pwd` make
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index 3fb0964810..d8fad98de2 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -486,7 +486,11 @@ endif
endif
ifdef DTRACE_ENABLED
-GENERATE += $(TARGET)/erlang_dtrace.h
+# global.h causes problems by including dtrace-wrapper.h which includes
+# the autogenerated erlang_dtrace.h ... so make erlang_dtrace.h very early.
+generate: $(TARGET)/erlang_dtrace.h $(GENERATE)
+else
+generate: $(GENERATE)
endif
ifdef HIPE_ENABLED
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index d0beccfda2..1dbe2cad00 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -41,8 +41,6 @@
#include "hipe_mode_switch.h"
#include "hipe_bif1.h"
#endif
-
-#include <assert.h>
#include "dtrace-wrapper.h"
/* #define HARDDEBUG 1 */
@@ -1053,72 +1051,6 @@ init_emulator(void)
# define REG_tmp_arg2
#endif
-ERTS_INLINE void
-dtrace_proc_str(Process *process, char *process_buf)
-{
- dtrace_pid_str(process->id, process_buf);
-}
-
-ERTS_INLINE void
-dtrace_pid_str(Eterm pid, char *process_buf)
-{
- snprintf(process_buf, DTRACE_TERM_BUF_SIZE, "<%lu.%lu.%lu>",
- pid_channel_no(pid),
- pid_number(pid),
- pid_serial(pid));
-}
-
-ERTS_INLINE void
-dtrace_port_str(Port *port, char *port_buf)
-{
- snprintf(port_buf, DTRACE_TERM_BUF_SIZE, "#Port<%lu.%lu>",
- port_channel_no(port->id),
- port_number(port->id));
-}
-
-ERTS_INLINE void
-dtrace_drvport_str(ErlDrvPort drvport, char *port_buf)
-{
- Port *port = erts_drvport2port(drvport);
-
- snprintf(port_buf, DTRACE_TERM_BUF_SIZE, "#Port<%lu.%lu>",
- port_channel_no(port->id),
- port_number(port->id));
-}
-
-ERTS_INLINE void
-dtrace_fun_decode(Process *process,
- Eterm module, Eterm function, int arity,
- char *process_buf, char *mfa_buf)
-{
- char funbuf[DTRACE_TERM_BUF_SIZE];
- char *funptr = funbuf;
- char *p = NULL;
-
- if (process_buf) {
- dtrace_proc_str(process, process_buf);
- }
-
- erts_snprintf(funbuf, sizeof(funbuf), "%T", function);
- /*
- * I'm not quite sure how these function names are synthesized,
- * but they almost always seem to be in the form of
- * '-name/arity-fun-0-' so I'm chopping them up when it's -fun-0-
- * (which seems to be the toplevel)
- */
- if (funbuf[0] == '\'' && funbuf[1] == '-'
- && strlen(funbuf) > 3 && funbuf[strlen(funbuf) - 3] == '0') {
- p = strchr(funbuf, '/');
- if (p) {
- *p = 0;
- }
- funptr += 2;
- }
-
- erts_snprintf(mfa_buf, DTRACE_TERM_BUF_SIZE, "%T:%s/%d",
- module, funptr, arity);
-}
-
#ifdef HAVE_DTRACE
#define DTRACE_CALL(p, m, f, a) \
@@ -1190,6 +1122,16 @@ dtrace_fun_decode(Process *process,
#endif /* HAVE_DTRACE */
+void
+dtrace_drvport_str(ErlDrvPort drvport, char *port_buf)
+{
+ Port *port = erts_drvport2port(drvport);
+
+ erts_snprintf(port_buf, DTRACE_TERM_BUF_SIZE, "#Port<%lu.%lu>",
+ port_channel_no(port->id),
+ port_number(port->id));
+}
+
/*
* process_main() is called twice:
* The first call performs some initialisation, including exporting
@@ -1376,7 +1318,8 @@ void process_main(void)
(Eterm)fptr[1], (Uint)fptr[2],
NULL, fun_buf);
} else {
- snprintf(fun_buf, sizeof(fun_buf), "<unknown/%p>", next);
+ erts_snprintf(fun_buf, sizeof(fun_buf),
+ "<unknown/%p>", next);
}
}
@@ -1970,7 +1913,9 @@ void process_main(void)
if (DTRACE_ENABLED(message_receive)) {
Eterm token2 = NIL;
DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
- Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_label) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_serial) = 0;
dtrace_proc_str(c_p, receiver_name);
token2 = SEQ_TRACE_TOKEN(c_p);
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 6f6b04d278..ba55a1918a 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -741,8 +741,10 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message)
Eterm token = NIL;
Process *sender = dsdp->proc;
int res;
- Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0;
- Uint msize = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_label) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_serial) = 0;
+ ERTS_DECLARE_DUMMY(Uint msize) = 0;
DTRACE_CHARBUF(node_name, 64);
DTRACE_CHARBUF(sender_name, 64);
DTRACE_CHARBUF(receiver_name, 64);
@@ -788,8 +790,10 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message)
Eterm token = NIL;
Process *sender = dsdp->proc;
int res;
- Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0;
- Uint32 msize = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_label) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_serial) = 0;
+ ERTS_DECLARE_DUMMY(Uint32 msize) = 0;
DTRACE_CHARBUF(node_name, 64);
DTRACE_CHARBUF(sender_name, 64);
DTRACE_CHARBUF(receiver_name, 128);
@@ -838,7 +842,9 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote,
DeclareTmpHeapNoproc(ctl_heap,6);
int res;
Process *sender = dsdp->proc;
- Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_label) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_serial) = 0;
DTRACE_CHARBUF(node_name, 64);
DTRACE_CHARBUF(sender_name, 64);
DTRACE_CHARBUF(remote_name, 128);
diff --git a/erts/emulator/beam/dtrace-wrapper.h b/erts/emulator/beam/dtrace-wrapper.h
index f93871bd25..b633058e90 100644
--- a/erts/emulator/beam/dtrace-wrapper.h
+++ b/erts/emulator/beam/dtrace-wrapper.h
@@ -23,15 +23,6 @@
#define DTRACE_TERM_BUF_SIZE 256
-#ifndef DTRACE_DRIVER_SKIP_FUNC_DECLARATIONS
-inline void dtrace_proc_str(Process *process, char *process_buf);
-inline void dtrace_pid_str(Eterm pid, char *process_buf);
-inline void dtrace_port_str(Port *port, char *port_buf);
-inline void dtrace_fun_decode(Process *process,
- Eterm module, Eterm function, int arity,
- char *process_buf, char *mfa_buf);
-#endif
-
/*
* Some varieties of SystemTap macros do not like statically-sized
* char[N] buffers. (For example, CentOS 6's macros.)
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c
index 72dcc99f4f..b8cb3c6cc4 100644
--- a/erts/emulator/beam/erl_async.c
+++ b/erts/emulator/beam/erl_async.c
@@ -253,8 +253,7 @@ erts_get_async_ready_queue(Uint sched_id)
static ERTS_INLINE void async_add(ErtsAsync *a, ErtsAsyncQ* q)
{
- /* DTRACE TODO: Get the queue length from erts_thr_q_enqueue() */
- int len = -1;
+ int len;
if (is_internal_port(a->port)) {
#if ERTS_USE_ASYNC_READY_Q
@@ -275,6 +274,8 @@ static ERTS_INLINE void async_add(ErtsAsync *a, ErtsAsyncQ* q)
DTRACE_CHARBUF(port_str, 16);
erts_snprintf(port_str, sizeof(port_str), "%T", a->port);
+ /* DTRACE TODO: Get the queue length from erts_thr_q_enqueue() ? */
+ len = -1;
DTRACE2(aio_pool_add, port_str, len);
}
gcc_optimizer_hack++;
@@ -288,8 +289,7 @@ static ERTS_INLINE ErtsAsync *async_get(ErtsThrQ_t *q,
int saved_fin_deq = 0;
ErtsThrQFinDeQ_t fin_deq;
#endif
- /* DTRACE TODO: Get the queue length from erts_thr_q_dequeue() somehow? */
- int len = -1;
+ int len;
while (1) {
ErtsAsync *a = (ErtsAsync *) erts_thr_q_dequeue(q);
@@ -305,6 +305,8 @@ static ERTS_INLINE ErtsAsync *async_get(ErtsThrQ_t *q,
DTRACE_CHARBUF(port_str, 16);
erts_snprintf(port_str, sizeof(port_str), "%T", a->port);
+ /* DTRACE TODO: Get the length from erts_thr_q_dequeue() ? */
+ len = -1;
DTRACE2(aio_pool_get, port_str, len);
}
return a;
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index 858ae32ad5..679a3645ba 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -2055,7 +2055,6 @@ shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj)
Uint heap_size = HEAP_TOP(p) - HEAP_START(p);
Sint offs;
Uint stack_size = p->hend - p->stop;
- char pidbuf[DTRACE_TERM_BUF_SIZE];
ASSERT(new_sz < p->heap_sz);
sys_memmove(p->heap + new_sz - stack_size, p->stop, stack_size *
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 8489353c9e..786d6ac52c 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -336,7 +336,9 @@ erts_queue_dist_message(Process *rcvr,
Eterm token)
{
ErlMessage* mp;
- Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_label) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_serial) = 0;
#ifdef ERTS_SMP
ErtsProcLocks need_locks;
#endif
@@ -495,7 +497,9 @@ erts_queue_message(Process* receiver,
if (DTRACE_ENABLED(message_queued)) {
DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
- Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_label) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_serial) = 0;
dtrace_proc_str(receiver, receiver_name);
if (seq_trace_token != NIL && is_tuple(seq_trace_token)) {
@@ -822,7 +826,9 @@ erts_send_message(Process* sender,
Eterm token = NIL;
DTRACE_CHARBUF(sender_name, 64);
DTRACE_CHARBUF(receiver_name, 64);
- Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_label) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0;
+ ERTS_DECLARE_DUMMY(Sint tok_serial) = 0;
BM_STOP_TIMER(system);
BM_MESSAGE(message,sender,receiver);
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 6f6263d160..7f12004b43 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1072,13 +1072,6 @@ void process_main(void);
Eterm build_stacktrace(Process* c_p, Eterm exc);
Eterm expand_error_value(Process* c_p, Uint freason, Eterm Value);
void erts_save_stacktrace(Process* p, struct StackTrace* s, int depth);
-ERTS_INLINE void dtrace_proc_str(Process *process, char *process_buf);
-ERTS_INLINE void dtrace_pid_str(Eterm pid, char *process_buf);
-ERTS_INLINE void dtrace_port_str(Port *port, char *port_buf);
-ERTS_INLINE void dtrace_drvport_str(ErlDrvPort port, char *port_buf);
-ERTS_INLINE void dtrace_fun_decode(Process *process,
- Eterm module, Eterm function, int arity,
- char *process_buf, char *mfa_buf);
/* erl_init.c */
@@ -1981,4 +1974,66 @@ erts_alloc_message_heap(Uint size,
# define UseTmpHeapNoproc(Size) /* Nothing */
# define UnUseTmpHeapNoproc(Size) /* Nothing */
#endif /* HEAP_ON_C_STACK */
+
+#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+
+#include "dtrace-wrapper.h"
+
+ERTS_GLB_INLINE void
+dtrace_pid_str(Eterm pid, char *process_buf)
+{
+ erts_snprintf(process_buf, DTRACE_TERM_BUF_SIZE, "<%lu.%lu.%lu>",
+ pid_channel_no(pid),
+ pid_number(pid),
+ pid_serial(pid));
+}
+
+ERTS_GLB_INLINE void
+dtrace_proc_str(Process *process, char *process_buf)
+{
+ dtrace_pid_str(process->id, process_buf);
+}
+
+ERTS_GLB_INLINE void
+dtrace_port_str(Port *port, char *port_buf)
+{
+ erts_snprintf(port_buf, DTRACE_TERM_BUF_SIZE, "#Port<%lu.%lu>",
+ port_channel_no(port->id),
+ port_number(port->id));
+}
+
+ERTS_GLB_INLINE void
+dtrace_fun_decode(Process *process,
+ Eterm module, Eterm function, int arity,
+ char *process_buf, char *mfa_buf)
+{
+ char funbuf[DTRACE_TERM_BUF_SIZE];
+ char *funptr = funbuf;
+ char *p = NULL;
+
+ if (process_buf) {
+ dtrace_proc_str(process, process_buf);
+ }
+
+ erts_snprintf(funbuf, sizeof(funbuf), "%T", function);
+ /*
+ * I'm not quite sure how these function names are synthesized,
+ * but they almost always seem to be in the form of
+ * '-name/arity-fun-0-' so I'm chopping them up when it's -fun-0-
+ * (which seems to be the toplevel)
+ */
+ if (funbuf[0] == '\'' && funbuf[1] == '-'
+ && strlen(funbuf) > 3 && funbuf[strlen(funbuf) - 3] == '0') {
+ p = strchr(funbuf, '/');
+ if (p) {
+ *p = 0;
+ }
+ funptr += 2;
+ }
+
+ erts_snprintf(mfa_buf, DTRACE_TERM_BUF_SIZE, "%T:%s/%d",
+ module, funptr, arity);
+}
+#endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
+
#endif /* !__GLOBAL_H__ */
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index b72f95792c..293f024e45 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -112,7 +112,6 @@
#include "erl_threads.h"
#include "zlib.h"
#include "gzio.h"
-#define DTRACE_DRIVER_SKIP_FUNC_DECLARATIONS
#include "dtrace-wrapper.h"
#include <ctype.h>
#include <sys/types.h>
@@ -126,6 +125,8 @@ static unsigned gcc_optimizer_hack = 0;
#ifdef HAVE_DTRACE
+#define DTRACE_EFILE_BUFSIZ 128
+
#define DTRACE_INVOKE_SETUP(op) \
do { DTRACE3(efile_drv_int_entry, d->sched_i1, d->sched_i2, op); } while (0)
#define DTRACE_INVOKE_SETUP_BY_NAME(op) \
@@ -149,6 +150,7 @@ typedef struct {
dt_private *get_dt_private(int);
#else /* HAVE_DTRACE */
typedef struct {
+ char dummy; /* Unused except to quiet some compilers */
} dt_private;
#define DTRACE_INVOKE_SETUP(op) do {} while (0)
@@ -429,7 +431,7 @@ struct t_data
#ifdef HAVE_DTRACE
int sched_i1;
Uint64 sched_i2;
- char sched_utag[128+1];
+ char sched_utag[DTRACE_EFILE_BUFSIZ+1];
#else
char sched_utag[1];
#endif
@@ -2196,12 +2198,12 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data)
int sched_i1 = d->sched_i1, sched_i2 = d->sched_i2, command = d->command,
result_ok = d->result_ok,
posix_errno = d->result_ok ? 0 : d->errInfo.posix_errno;
- DTRACE_CHARBUF(sched_utag, 128+1);
+ DTRACE_CHARBUF(sched_utag, DTRACE_EFILE_BUFSIZ+1);
sched_utag[0] = '\0';
if (DTRACE_ENABLED(efile_drv_return)) {
- strncpy(sched_utag, d->sched_utag, sizeof(sched_utag) - 1);
- sched_utag[sizeof(sched_utag) - 1] = '\0';
+ strncpy(sched_utag, d->sched_utag, DTRACE_EFILE_BUFSIZ);
+ sched_utag[DTRACE_EFILE_BUFSIZ] = '\0';
}
#endif /* HAVE_DTRACE */
@@ -2488,8 +2490,12 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
char* name; /* Points to the filename in buf. */
int command;
struct t_data *d = NULL;
- char *dt_utag = NULL, *dt_s1 = NULL, *dt_s2 = NULL;
- Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0, dt_i4 = 0;
+ ERTS_DECLARE_DUMMY(char *dt_utag) = NULL;
+ char *dt_s1 = NULL, *dt_s2 = NULL;
+ ERTS_DECLARE_DUMMY(Sint64 dt_i1) = 0;
+ ERTS_DECLARE_DUMMY(Sint64 dt_i2) = 0;
+ ERTS_DECLARE_DUMMY(Sint64 dt_i3) = 0;
+ ERTS_DECLARE_DUMMY(Sint64 dt_i4) = 0;
#ifdef HAVE_DTRACE
dt_private *dt_priv = get_dt_private(0);
#endif /* HAVE_DTRACE */
@@ -3015,8 +3021,10 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
int p, q;
int err;
struct t_data *d = NULL;
- Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0, dt_i4 = 0;
- char *dt_utag = NULL, *dt_s1 = NULL;
+ Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0;
+ ERTS_DECLARE_DUMMY(Sint64 dt_i4) = 0;
+ char *dt_utag = NULL;
+ ERTS_DECLARE_DUMMY(char *dt_s1) = NULL;
#ifdef HAVE_DTRACE
dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base);
#else
diff --git a/erts/lib_src/common/erl_printf.c b/erts/lib_src/common/erl_printf.c
index afb9c0abb7..399c83384e 100644
--- a/erts/lib_src/common/erl_printf.c
+++ b/erts/lib_src/common/erl_printf.c
@@ -173,10 +173,10 @@ typedef struct {
static int
write_sn(void *vwsnap, char* buf, size_t len)
{
+ int rv = 0;
write_sn_arg_t *wsnap = (write_sn_arg_t *) vwsnap;
ASSERT(wsnap);
ASSERT(len > 0);
- int rv = 0;
if (wsnap->len > 0) {
size_t sz = len;
if (sz >= wsnap->len)
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index 9d6c47ffc1..6778fe353c 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 5c9cad3a2c..46ce3ab1a4 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -1493,19 +1493,15 @@ to_seconds({_,_} = Datetime, universal) ->
to_seconds({_,_} = Datetime, local) ->
erlang:universaltime_to_posixtime(erlang:localtime_to_universaltime(Datetime)).
-%% TODO: Duplicate code!
get_dtrace_utag() ->
- case get(dtrace_utag) of
- X when is_list(X) ->
- X;
- _ ->
- ""
+ %% We cannot call dtrace:get_utag() because this is prim_file.erl.
+ %% We must reimplement it here.
+ case get('_dtrace_utag_@_@') of
+ undefined ->
+ <<>>;
+ X ->
+ X
end.
-%% TODO: Measure if it's worth checking (re:run()?) for NUL byte first?
-enc_utag([0|Cs]) ->
- enc_utag(Cs);
-enc_utag([C|Cs]) ->
- [C|enc_utag(Cs)];
-enc_utag([]) ->
- [0].
+enc_utag(UTag) ->
+ [UTag, 0].
diff --git a/lib/dtrace/c_src/Makefile b/lib/dtrace/c_src/Makefile
index f3320bb766..a65491d45d 100644
--- a/lib/dtrace/c_src/Makefile
+++ b/lib/dtrace/c_src/Makefile
@@ -1,4 +1,4 @@
#
-# Invoke with GNU make or clearmake -C gnu.
+# Invoke with GNU make
#
include $(ERL_TOP)/make/run_make.mk
diff --git a/lib/dtrace/c_src/Makefile.in b/lib/dtrace/c_src/Makefile.in
index ed13684a95..831ce5ce75 100644
--- a/lib/dtrace/c_src/Makefile.in
+++ b/lib/dtrace/c_src/Makefile.in
@@ -72,7 +72,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/dtrace-$(VSN)
# ----------------------------------------------------
# Misc Macros
# ----------------------------------------------------
-OBJS = $(OBJDIR)/dtrace$(TYPEMARKER).o
+before_DTrace_OBJS = $(OBJDIR)/dtrace$(TYPEMARKER).o
## NIF_MAKEFILE = $(PRIVDIR)/Makefile
# Higher-level makefiles says that we can only compile on UNIX flavors
@@ -100,18 +100,17 @@ else
DTRACE_USER_HEADER=
endif
+DTRACE_OBJS =
ifdef DTRACE_ENABLED_2STEP
-OBJS += $(OBJDIR)/dtrace_user.o
-$(OBJDIR)/dtrace_user.o: $(OBJS) $(OBJDIR)/dtrace_user.h
- touch $(OBJDIR)/erlang_dtrace.c
- $(CC) $(CFLAGS) -c -o $@ $(OBJDIR)/erlang_dtrace.c
- # The object file created above is immediately clobbered below.
- # But creating it above avoids chicken-and-egg problem with OBJS
+DTRACE_OBJS += $(OBJDIR)/dtrace_user.o
+$(OBJDIR)/dtrace_user.o: $(before_DTrace_OBJS) $(OBJDIR)/dtrace_user.h
dtrace -G -C \
-s ./dtrace_user.d \
- -o $@ $(OBJS)
+ -o $@ $(before_DTrace_OBJS)
endif
+OBJS = $(before_DTrace_OBJS) $(DTRACE_OBJS)
+
$(OBJDIR):
-@mkdir -p $(OBJDIR)
diff --git a/lib/dtrace/c_src/dtrace.c b/lib/dtrace/c_src/dtrace.c
index c9d25ece9c..90bb39a4b8 100644
--- a/lib/dtrace/c_src/dtrace.c
+++ b/lib/dtrace/c_src/dtrace.c
@@ -25,7 +25,6 @@
#include "erl_nif.h"
#include "config.h"
#include "sys.h"
-#define DTRACE_DRIVER_SKIP_FUNC_DECLARATIONS
#include "dtrace-wrapper.h"
#ifdef HAVE_DTRACE
#include "dtrace_user.h"
@@ -144,8 +143,7 @@ static ERL_NIF_TERM user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM
if (DTRACE_ENABLED(user_trace_i4s4)) {
dtrace_nifenv_str(env, procbuf);
- get_string_maybe(env, argv[0], &utbuf,
- user_tagbuf, sizeof(user_tagbuf)-1);
+ get_string_maybe(env, argv[0], &utbuf, user_tagbuf, MESSAGE_BUFSIZ);
if (! enif_get_int64(env, argv[1], &i1))
i1 = 0;
if (! enif_get_int64(env, argv[2], &i2))
@@ -154,14 +152,10 @@ static ERL_NIF_TERM user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM
i3 = 0;
if (! enif_get_int64(env, argv[4], &i4))
i4 = 0;
- get_string_maybe(env, argv[5], &mbuf1,
- messagebuf1, sizeof(messagebuf1)-1);
- get_string_maybe(env, argv[6], &mbuf2,
- messagebuf2, sizeof(messagebuf2)-1);
- get_string_maybe(env, argv[7], &mbuf3,
- messagebuf3, sizeof(messagebuf3)-1);
- get_string_maybe(env, argv[8], &mbuf4,
- messagebuf4, sizeof(messagebuf4)-1);
+ get_string_maybe(env, argv[5], &mbuf1, messagebuf1, MESSAGE_BUFSIZ);
+ get_string_maybe(env, argv[6], &mbuf2, messagebuf2, MESSAGE_BUFSIZ);
+ get_string_maybe(env, argv[7], &mbuf3, messagebuf3, MESSAGE_BUFSIZ);
+ get_string_maybe(env, argv[8], &mbuf4, messagebuf4, MESSAGE_BUFSIZ);
DTRACE10(user_trace_i4s4, procbuf, utbuf,
i1, i2, i3, i4, mbuf1, mbuf2, mbuf3, mbuf4);
return atom_true;
diff --git a/lib/dtrace/examples/dist.d b/lib/dtrace/examples/dist.d
index f37c827f14..550e10d363 100644
--- a/lib/dtrace/examples/dist.d
+++ b/lib/dtrace/examples/dist.d
@@ -30,13 +30,13 @@ erlang*:::dist-port_busy
{
printf("dist port_busy: node %s, port %s, remote_node %s, blocked pid %s\n",
copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), copyinstr(arg3));
- blocked_procs[copyinstr(arg3)] = timestamp;
-}
-
-erlang*:::dist-port_busy
-{
- printf("dist port_busy: node %s, port %s, remote_node %s, blocked pid %s\n",
- copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), copyinstr(arg3));
+ /*
+ * For variable use advice, see:
+ * http://dtrace.org/blogs/brendan/2011/11/25/dtrace-variable-types/
+ *
+ * Howevever, it's quite possible for the blocked events to span
+ * threads, so we'll use globals.
+ */
blocked_procs[copyinstr(arg3)] = timestamp;
}
diff --git a/lib/dtrace/examples/port1.d b/lib/dtrace/examples/port1.d
index b82e783a14..204abbd3b8 100644
--- a/lib/dtrace/examples/port1.d
+++ b/lib/dtrace/examples/port1.d
@@ -99,10 +99,12 @@ erlang*:::port-command
erlang*:::port-control
{
- cmd = driver_map[copyinstr(arg2), arg3];
- cmd_str = (cmd == 0) ? "unknown" : cmd;
+ /* http://dtrace.org/blogs/brendan/2011/11/25/dtrace-variable-types/ */
+ this->cmd = driver_map[copyinstr(arg2), arg3];
+ this->cmd_str = (this->cmd == 0) ? "unknown" : this->cmd;
printf("port control pid %s port %s port name %s command %d %s\n",
- copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3, cmd_str);
+ copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3,
+ this->cmd_str);
}
/* port-exit is fired as a result of port_close() or exit signal */
diff --git a/lib/dtrace/examples/process-scheduling.d b/lib/dtrace/examples/process-scheduling.d
index 9e31da2774..79e9cc598c 100644
--- a/lib/dtrace/examples/process-scheduling.d
+++ b/lib/dtrace/examples/process-scheduling.d
@@ -31,5 +31,5 @@ erlang*:::process-unscheduled
erlang*:::process-hibernate
{
printf(" Hibernate pid %s resume mfa %s\n",
- copyinstr(arg0), copyinstr(arg1));
+ copyinstr(arg0), copyinstr(arg1));
}
diff --git a/lib/dtrace/src/dtrace.erl b/lib/dtrace/src/dtrace.erl
index 45addafc53..6951c03215 100644
--- a/lib/dtrace/src/dtrace.erl
+++ b/lib/dtrace/src/dtrace.erl
@@ -14,8 +14,8 @@
%%% four integer arguments and four string arguments; the integer
%%% argument(s) must come before any string argument. For example:
%%% ```
-%%% 1> put(dtrace_utag, "GGOOOAAALL!!!!!").
-%%% undefined
+%%% 1> dtrace:put_tag("GGOOOAAALL!!!!!").
+%%% true
%%% 2> dtrace:init().
%%% ok
%%%
@@ -35,9 +35,13 @@
%%% then the driver will ignore the user's input and use a default
%%% value of 0 or NULL, respectively.
+-define(DTRACE_UT_KEY, '_dtrace_utag_@_@'). % Match prim_file:get_dtrace_utag()!
+
-export([init/0, available/0,
user_trace_s1/1, % TODO: unify with pid & tag args like user_trace_i4s4
p/0, p/1, p/2, p/3, p/4, p/5, p/6, p/7, p/8]).
+-export([put_utag/1, get_utag/0]).
+
-export([scaff/0]). % Development only
-export([user_trace_i4s4/9]). % Know what you're doing!
@@ -68,7 +72,7 @@ available() ->
-spec user_trace_s1(iolist()) -> true | false | error | badarg.
-user_trace_s1(Message) ->
+user_trace_s1(_Message) ->
erlang:nif_error(nif_not_loaded).
-spec user_trace_i4s4(iolist(),
@@ -176,8 +180,32 @@ p(I1, I2, I3, I4, S1, S2, S3, S4) when is_integer(I1), is_integer(I2), is_intege
true | false | error | badarg.
user_trace_int(I1, I2, I3, I4, S1, S2, S3, S4) ->
- UTag = prim_file:get_dtrace_utag(),
- user_trace_i4s4(UTag, I1, I2, I3, I4, S1, S2, S3, S4).
+ UTag = get_utag(),
+ try
+ user_trace_i4s4(UTag, I1, I2, I3, I4, S1, S2, S3, S4)
+ catch
+ error:nif_not_loaded ->
+ false
+ end.
+
+-spec put_utag(undefined | iolist()) -> ok.
+
+put_utag(undefined) ->
+ put_utag(<<>>);
+put_utag(T) when is_binary(T) ->
+ put(?DTRACE_UT_KEY, T),
+ ok;
+put_utag(T) when is_list(T) ->
+ put(?DTRACE_UT_KEY, list_to_binary(T)),
+ ok.
+
+get_utag() ->
+ case get(?DTRACE_UT_KEY) of
+ undefined ->
+ <<>>;
+ X ->
+ X
+ end.
%% Scaffolding to write tedious code: quick brute force and not 100% correct.
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index a2e0d261ee..aecb9f7923 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -227,7 +227,7 @@ read_file_info(Name) ->
Reason :: posix() | badarg.
read_file_info(Name, Opts) when is_list(Opts) ->
- check_and_call(read_file_info, [file_name(Name), Opts]).
+ check_and_call(read_file_info, [file_name(Name), Opts, get_dtrace_utag()]).
-spec altname(Name :: name()) -> any().
@@ -249,7 +249,7 @@ read_link_info(Name) ->
Reason :: posix() | badarg.
read_link_info(Name, Opts) when is_list(Opts) ->
- check_and_call(read_link_info, [file_name(Name),Opts]).
+ check_and_call(read_link_info, [file_name(Name),Opts, get_dtrace_utag()]).
-spec read_link(Name) -> {ok, Filename} | {error, Reason} when
@@ -275,7 +275,7 @@ write_file_info(Name, Info = #file_info{}) ->
Reason :: posix() | badarg.
write_file_info(Name, Info = #file_info{}, Opts) when is_list(Opts) ->
- check_and_call(write_file_info, [file_name(Name), Info, Opts]).
+ check_and_call(write_file_info, [file_name(Name), Info, Opts, get_dtrace_utag()]).
-spec list_dir(Dir) -> {ok, Filenames} | {error, Reason} when
Dir :: name(),
@@ -1504,4 +1504,4 @@ wait_file_reply(From, Ref) ->
end.
get_dtrace_utag() ->
- prim_file:get_dtrace_utag().
+ dtrace:get_utag().
diff --git a/lib/kernel/src/file_server.erl b/lib/kernel/src/file_server.erl
index c917819508..82adc45795 100644
--- a/lib/kernel/src/file_server.erl
+++ b/lib/kernel/src/file_server.erl
@@ -146,7 +146,7 @@ handle_call({get_cwd, Name, DTraceUtag}, _From, Handle) ->
{reply, ?PRIM_FILE:get_cwd(Handle, Name, DTraceUtag), Handle};
handle_call({read_file_info, Name, DTraceUtag}, _From, Handle) ->
- {reply, ?PRIM_FILE:read_file_info(Handle, Name, DTraceUtag), Handle};
+ {reply, ?PRIM_FILE:read_file_info(Handle, Name, [], DTraceUtag), Handle};
handle_call({read_file_info, Name, Opts, DTraceUtag}, _From, Handle) ->
{reply, ?PRIM_FILE:read_file_info(Handle, Name, Opts, DTraceUtag), Handle};
@@ -154,12 +154,12 @@ handle_call({altname, Name, DTraceUtag}, _From, Handle) ->
{reply, ?PRIM_FILE:altname(Handle, Name, DTraceUtag), Handle};
handle_call({write_file_info, Name, Info, DTraceUtag}, _From, Handle) ->
- {reply, ?PRIM_FILE:write_file_info(Handle, Name, Info, DTraceUtag), Handle};
+ {reply, ?PRIM_FILE:write_file_info(Handle, Name, Info, [], DTraceUtag), Handle};
handle_call({write_file_info, Name, Info, Opts, DTraceUtag}, _From, Handle) ->
{reply, ?PRIM_FILE:write_file_info(Handle, Name, Info, Opts, DTraceUtag), Handle};
handle_call({read_link_info, Name, DTraceUtag}, _From, Handle) ->
- {reply, ?PRIM_FILE:read_link_info(Handle, Name, DTraceUtag), Handle};
+ {reply, ?PRIM_FILE:read_link_info(Handle, Name, [], DTraceUtag), Handle};
handle_call({read_link_info, Name, Opts, DTraceUtag}, _From, Handle) ->
{reply, ?PRIM_FILE:read_link_info(Handle, Name, Opts, DTraceUtag), Handle};