From 0721ac40f91295bb3995f86966e5dd031028ca85 Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Thu, 17 Nov 2011 00:42:55 -0600 Subject: Add DTrace support for OS X, Solaris, and Linux (via SystemTap), 1/4 Since it's been quite a while since I've written C code, *and* I haven't done any significant hacking on the VM itself in years, it's quite likely that I haven't done things in 100% proper style. Or my co-collaborators Dustin Sallings (CouchBase) or Michal Ptaszek (Erlang Solutions). My intent for this patch is to start discussion and review of DTrace support for consideration for the R15 release. For additional background on the motivation for this work, please see the slides for the presentation at the Erlang User Conference 2011 in Stockholm: https://www.erlang-factory.com/upload/presentations/462/euc2011-draft2.pdf Changes relative to dtrace-review2 branch: * Fix errors in OTP test suite 'kernel' file_SUITE * Fix errors in OTP test suite 'kernel' prim_file_SUITE * Fix bad pointer bug in efile_drv.c flush_write() * Move the DTrace material from the top of `README.md` into a new file, `README.dtrace.md` Changes since last push to GitHub (relative to commit 5828a4fb28, which was the former `dtrace-review1` branch): * Rebased onto 14 Nov 2011's "master" branch * Recent changes to the async task queuing mechanism means that the async worker queue length is not available. A bogus value of -1 is hard-coded until there's a good way to peek into the new queue structure and find the queue length. * Small fixes based on review comments by Mikael Pettersson, Andrew Thompson, and Andreas Schultz. Add autoconf support: use "./configure --enable-dtrace" on all supported platforms: * OS X Snow Leopard or later * Solaris 10 or OpenSolaris * Linux, via SystemTap's DTrace compatibility packages * FreeBSD 9.0RC1. FreeBSD 8 and earlier do not have support for USDT, DTrace's User-land Statically Defined Tracing. See the file `erts/emulator/beam/erlang_dtrace.d` for the definition of all DTrace probes in the virtual machine so far. Example D scripts can be found in `lib/dtrace/examples`. Note that if you see the error message `{name of probe} does not match any probes`, then there is no Erlang VM process + DTrace probes running. To fix, start a DTrace-enabled VM or remove `-q` from the `dtrace` command line. The `lib/dtrace` directory contains a small code-only OTP application that contains code that allows Erlang code to trigger a DTrace probe. Dynamic creation & deletion of DTrace probes is not currently supported, so the `dtrace:p()` function is hacked to allow a variable number of arguments (up to four integers and up to four strings) to be used. See the comments at the top of `lib/dtrace/src/dtrace.c` for more detail. One feature that may be controversial is the notion I've introduced of a special process dictionary key that can be used by Erlang code to tag I/O operations for an application-specific purpose. Right now, that tag's name is `dtrace_utag`. The dictionary keys used by `sys` and other modules start with a dollar sign. Perhaps there is some convention (but not a dollar sign?) that this tag should use? The purpose of the process dictionary key is to allow the tag to be included in trace messages, e.g. for file I/O, without changing the API of the `file.erl` module's functions. For example, here's a use of the tag when calling the `file:rename/2` function: (bar@sbb2)1> put(dtrace_utag, "GGOOOAAALL!!!!!"). undefined (bar@sbb2)2> dtrace:init(). ok %% Now start both the `user-probe.d` and `efile_drv.d` D scripts %% found in the `lib/dtrace/examples` directory. (bar@sbb2)3> dtrace:p(7, 8, 9, "one", "four"). true %% The output from the `user-probe.d` script: <0.40.0> GGOOOAAALL!!!!! 7 8 9 0 'one' 'four' '' '' (bar@sbb2)4> file:rename("old-name", "new-name"). {error,enoent} %% The output from the `efile_drv.d` script: async I/O pool port #Port<0.59> queue len 1 async I/O pool port #Port<0.59> queue len 0 efile_drv enter tag={1,110} user tag GGOOOAAALL!!!!! | RENAME (12) | args: old-name new-name , 0 0 (port #Port<0.59>) async I/O worker tag={1,110} | RENAME (12) | efile_drv-int_entry async I/O worker tag={1,110} | RENAME (12) | efile_drv-int_return efile_drv return tag={1,110} user tag GGOOOAAALL!!!!! | RENAME (12) | errno 2 I'm not exactly happy with this choice of tagging, namely using `put(dtrace_utag, Tag::list())`. But this is an experiment, so we'll see how it goes. I can't imagine changing the API for all file.erl functions in order pass the tag explicitly. Some modules have some extensive (ab)use of the C preprocessor to reduce the amount of #ifdefs that clutter the code. In several places, I have not #ifdef'ed automatic variables because of clutter. For the same reason, there are a handful of cases where I added DTrace-related members to a struct definition without an #ifdef. I feel that the result is easier to read than earlier drafts where I did use many more `https://github.com/slfritchie/otp/tree/dtrace-experiment+michal2` if you're curious.) I expect there may be some debate about whether the bloat of the affected structs is worthwhile. I erred on adding stuff to structs, especially in the efile_drv.c driver, not having a full grasp on what was thread-safe and what was not ... so I erred on the side of caution. The efile_drv.c has a work-around for a crazy GCC optimization bug. Thank goodness for Google, I dunno how I would've found a work-around for this silly thing. Many thanks to Trond Norbye for writing clearly about the problem in a membase Git repo commit message. /* * A note on probe naming: if "__" appears in a provider probe * definition, then two things happen during compilation: * * 1. The "__" will turn into a hypen, "-", for the probe name. * 2. The "__" will turn into a single underscore, "_", for the * macro names and function definitions that the compiler and * C developers will see. * * We'll try to use the following naming convention. We're a bit * limited because, as a USDT probe, we can only specify the 4th part * of the probe name, e.g. erlang*:::mumble. The 2nd part of the * probe name is always going to be "beam" or "beam.smp", and the 3rd * part of the probe name will always be the name of the function * that's calling the probe. * * So, all probes will be have names defined in this file using the * convention category__name or category__sub_category__name. This * will translate to probe names of category-name or * category-sub_category-name. * * Each of "category", "sub_category", and "name" may have underscores * but may not have hyphens. */ Add tentative support for sequential tracing sending, queueing, and receiving a message. I don't believe I've fully covered all the major places where it would be useful to have the sequential trace token info in a probe -- guidance from the OTP team would be helpful, if there's time to do that kind of review. Add global variable `erts_this_node_sysname`. --- erts/emulator/Makefile.in | 25 +++++++- erts/emulator/beam/dtrace-wrapper.h | 118 +++++++++++++++++++++++++++++++++++ erts/emulator/beam/erl_driver.h | 2 + erts/emulator/beam/erl_node_tables.h | 1 + erts/emulator/beam/global.h | 7 +++ 5 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 erts/emulator/beam/dtrace-wrapper.h (limited to 'erts/emulator') diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index 279844adb2..3fb0964810 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -23,6 +23,8 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk ENABLE_ALLOC_TYPE_VARS = @ENABLE_ALLOC_TYPE_VARS@ HIPE_ENABLED=@HIPE_ENABLED@ +DTRACE_ENABLED=@DTRACE_ENABLED@ +DTRACE_ENABLED_2STEP=@DTRACE_ENABLED_2STEP@ LIBS = @LIBS@ Z_LIB=@Z_LIB@ NO_INLINE_FUNCTIONS=false @@ -483,6 +485,10 @@ GENERATE += $(HIPE_ASM) \ endif endif +ifdef DTRACE_ENABLED +GENERATE += $(TARGET)/erlang_dtrace.h +endif + ifdef HIPE_ENABLED OPCODE_TABLES += hipe/hipe_ops.tab endif @@ -590,6 +596,11 @@ $(TTF_DIR)/GENERATED: $(GENERATE) echo $? >$(TTF_DIR)/GENERATED endif +$(TARGET)/erlang_dtrace.h: beam/erlang_dtrace.d + dtrace -h -C -Ibeam -s $< -o ./erlang_dtrace.tmp + sed -e '/^#define[ ]*ERLANG_[A-Z0-9_]*(.*)/y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' ./erlang_dtrace.tmp > $@ + rm ./erlang_dtrace.tmp + # ---------------------------------------------------------------------- # Pattern rules # @@ -633,7 +644,6 @@ $(OBJDIR)/beam_emu.o: beam/beam_emu.c $(EMU_CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@ endif - $(OBJDIR)/%.o: beam/%.c $(CC) $(subst -O2, $(GEN_OPT_FLGS), $(CFLAGS)) $(INCLUDES) -c $< -o $@ @@ -833,7 +843,18 @@ endif BASE_OBJS = $(RUN_OBJS) $(EMU_OBJS) $(OS_OBJS) $(EXTRA_BASE_OBJS) -OBJS = $(BASE_OBJS) $(DRV_OBJS) +before_DTrace_OBJS = $(BASE_OBJS) $(DRV_OBJS) + +DTRACE_OBJS = +ifdef DTRACE_ENABLED_2STEP +DTRACE_OBJS = $(OBJDIR)/erlang_dtrace.o +$(OBJDIR)/erlang_dtrace.o: $(before_DTrace_OBJS) $(TARGET)/erlang_dtrace.h + dtrace -G -C -Ibeam \ + -s beam/erlang_dtrace.d \ + -o $@ $(before_DTrace_OBJS) +endif + +OBJS = $(before_DTrace_OBJS) $(DTRACE_OBJS) $(INIT_OBJS): $(TTF_DIR)/GENERATED $(OBJS): $(TTF_DIR)/GENERATED diff --git a/erts/emulator/beam/dtrace-wrapper.h b/erts/emulator/beam/dtrace-wrapper.h new file mode 100644 index 0000000000..f93871bd25 --- /dev/null +++ b/erts/emulator/beam/dtrace-wrapper.h @@ -0,0 +1,118 @@ +/* + * %CopyrightBegin% + * + * Copyright Dustin Sallings, Michal Ptaszek, Scott Lystig Fritchie 2011. + * 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/. + * + * 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. + * + * %CopyrightEnd% + */ + +#ifndef __DTRACE_WRAPPER_H +#define __DTRACE_WRAPPER_H + +#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.) + * So, we'll play a game to humor them. + * + * The code necessary to play nice with CentOS 6's SystemTap looks + * stupid to a C programmer's eyes, so we hide the ugliness with this + * macro, which expands: + * + * DTRACE_CHARBUF(proc_name, 64); + * + * to become: + * + * char proc_name_BUFFER[64], *proc_name = proc_name_BUFFER; + */ + +#define DTRACE_CHARBUF(name, size) \ + char name##_BUFFER[size], *name = name##_BUFFER + +#ifdef HAVE_DTRACE + +#include "erlang_dtrace.h" + +#define DTRACE_ENABLED(name) \ + erlang_##name##_enabled() +#define DTRACE0(name) \ + erlang_##name() +#define DTRACE1(name, a0) \ + erlang_##name(a0) +#define DTRACE2(name, a0, a1) \ + erlang_##name((a0), (a1)) +#define DTRACE3(name, a0, a1, a2) \ + erlang_##name((a0), (a1), (a2)) +#define DTRACE4(name, a0, a1, a2, a3) \ + erlang_##name((a0), (a1), (a2), (a3)) +#define DTRACE5(name, a0, a1, a2, a3, a4) \ + erlang_##name((a0), (a1), (a2), (a3), (a4)) +#define DTRACE6(name, a0, a1, a2, a3, a4, a5) \ + erlang_##name((a0), (a1), (a2), (a3), (a4), (a5)) +#define DTRACE7(name, a0, a1, a2, a3, a4, a5, a6) \ + erlang_##name((a0), (a1), (a2), (a3), (a4), (a5), (a6)) +#define DTRACE10(name, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ + erlang_##name((a0), (a1), (a2), (a3), (a4), (a5), (a6), (a7), (a8), (a9)) +#define DTRACE11(name, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ + erlang_##name((a0), (a1), (a2), (a3), (a4), (a5), (a6), (a7), (a8), (a9), (a10)) + +#if defined(_SDT_PROBE) && !defined(STAP_PROBE11) +/* SLF: This is Ubuntu 11-style SystemTap hackery */ +/* work arround for missing STAP macro */ +#define STAP_PROBE11(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) \ + _SDT_PROBE(provider, name, 11, \ + (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11)) +#define _SDT_ASM_OPERANDS_11(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) \ + _SDT_ASM_OPERANDS_10(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,arg10), \ + _SDT_ARG(11, arg11) +#endif + +#ifdef STAP_PROBE_ADDR +/* SLF: This is CentOS 5-style SystemTap hackery */ +/* SystemTap compat mode cannot support 11 args. We'll ignore the 11th */ +#define STAP_PROBE11(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11) \ + STAP_PROBE10(provider,probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9),(parm10)) +#endif /* STAP_PROBE_ADDR */ + +#else /* HAVE_DTRACE */ + +/* Render all macros to do nothing */ +#define DTRACE_ENABLED(name) 0 +#define DTRACE0(name) do {} while (0) +#define DTRACE1(name, a0) do {} while (0) +#define DTRACE2(name, a0, a1) do {} while (0) +#define DTRACE3(name, a0, a1, a2) do {} while (0) +#define DTRACE4(name, a0, a1, a2, a3) do {} while (0) +#define DTRACE5(name, a0, a1, a2, a3, a4) do {} while (0) +#define DTRACE6(name, a0, a1, a2, a3, a4, a5) do {} while (0) +#define DTRACE7(name, a0, a1, a2, a3, a4, a5, a6) do {} while (0) +#define DTRACE10(name, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ + do {} while (0) +#define DTRACE11(name, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ + do {} while (0) + +#endif /* HAVE_DTRACE */ + +#endif /* __DTRACE_WRAPPER_H */ diff --git a/erts/emulator/beam/erl_driver.h b/erts/emulator/beam/erl_driver.h index 7510f6b724..1ae9a211d7 100644 --- a/erts/emulator/beam/erl_driver.h +++ b/erts/emulator/beam/erl_driver.h @@ -649,6 +649,8 @@ EXTERN int erl_drv_getenv(char *key, char *value, size_t *value_size); #endif +/* also in global.h, but driver's can't include global.h */ +void dtrace_drvport_str(ErlDrvPort port, char *port_buf); diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h index b0a63ae035..8abb748a78 100644 --- a/erts/emulator/beam/erl_node_tables.h +++ b/erts/emulator/beam/erl_node_tables.h @@ -169,6 +169,7 @@ extern Sint erts_no_of_not_connected_dist_entries; extern DistEntry *erts_this_dist_entry; extern ErlNode *erts_this_node; +extern char erts_this_node_sysname[256]; /* must match erl_node_tables.c */ DistEntry *erts_channel_no_to_dist_entry(Uint); DistEntry *erts_sysname_to_connected_dist_entry(Eterm); diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 97d7f0e904..6f6263d160 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1072,6 +1072,13 @@ 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 */ -- cgit v1.2.3 From 2f532f889a6bd31f74122bd223277d7c609f7bdc Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Thu, 17 Nov 2011 00:45:50 -0600 Subject: Add DTrace support for OS X, Solaris, and Linux (via SystemTap), 3/4 Add probes to the virtual machine, except (mostly) the efile_drv.c driver and other file I/O-related source files. --- erts/emulator/beam/beam_emu.c | 228 +++++++++- erts/emulator/beam/copy.c | 9 + erts/emulator/beam/dist.c | 129 ++++++ erts/emulator/beam/erl_async.c | 26 ++ erts/emulator/beam/erl_bif_ddll.c | 2 + erts/emulator/beam/erl_bif_info.c | 3 + erts/emulator/beam/erl_bif_port.c | 27 ++ erts/emulator/beam/erl_gc.c | 46 +- erts/emulator/beam/erl_lock_check.c | 3 + erts/emulator/beam/erl_message.c | 74 +++- erts/emulator/beam/erl_nif.c | 6 + erts/emulator/beam/erl_node_tables.c | 9 + erts/emulator/beam/erl_node_tables.h | 2 +- erts/emulator/beam/erl_port_task.c | 18 +- erts/emulator/beam/erl_process.c | 38 +- erts/emulator/beam/erlang_dtrace.d | 716 ++++++++++++++++++++++++++++++++ erts/emulator/beam/io.c | 118 ++++++ erts/emulator/sys/common/erl_check_io.c | 8 + 18 files changed, 1456 insertions(+), 6 deletions(-) create mode 100644 erts/emulator/beam/erlang_dtrace.d (limited to 'erts/emulator') diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index c65b2be106..d0beccfda2 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -42,6 +42,9 @@ #include "hipe_bif1.h" #endif +#include +#include "dtrace-wrapper.h" + /* #define HARDDEBUG 1 */ #if defined(NO_JUMP_TABLE) @@ -1050,6 +1053,143 @@ 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) \ + if (DTRACE_ENABLED(function_entry)) { \ + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ + int depth = (STACK_START(p) - STACK_TOP(p)) \ + / sizeof(Eterm*); \ + dtrace_fun_decode(p, m, f, a, \ + process_name, mfa); \ + DTRACE3(function_entry, process_name, mfa, depth); \ + } + +#define DTRACE_RETURN(p, m, f, a) \ + if (DTRACE_ENABLED(function_return)) { \ + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ + int depth = (STACK_START(p) - STACK_TOP(p)) \ + / sizeof(Eterm*); \ + dtrace_fun_decode(p, m, f, a, \ + process_name, mfa); \ + DTRACE3(function_return, process_name, mfa, depth); \ + } + +#define DTRACE_BIF_ENTRY(p, m, f, a) \ + if (DTRACE_ENABLED(bif_entry)) { \ + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ + dtrace_fun_decode(p, m, f, a, \ + process_name, mfa); \ + DTRACE2(bif_entry, process_name, mfa); \ + } + +#define DTRACE_BIF_RETURN(p, m, f, a) \ + if (DTRACE_ENABLED(bif_return)) { \ + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ + dtrace_fun_decode(p, m, f, a, \ + process_name, mfa); \ + DTRACE2(bif_return, process_name, mfa); \ + } + +#define DTRACE_NIF_ENTRY(p, m, f, a) \ + if (DTRACE_ENABLED(nif_entry)) { \ + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ + dtrace_fun_decode(p, m, f, a, \ + process_name, mfa); \ + DTRACE2(nif_entry, process_name, mfa); \ + } + +#define DTRACE_NIF_RETURN(p, m, f, a) \ + if (DTRACE_ENABLED(nif_return)) { \ + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ + dtrace_fun_decode(p, m, f, a, \ + process_name, mfa); \ + DTRACE2(nif_return, process_name, mfa); \ + } + +#else /* HAVE_DTRACE */ + +#define DTRACE_CALL(p, m, f, a) do {} while (0) +#define DTRACE_RETURN(p, m, f, a) do {} while (0) +#define DTRACE_BIF_ENTRY(p, m, f, a) do {} while (0) +#define DTRACE_BIF_RETURN(p, m, f, a) do {} while (0) +#define DTRACE_NIF_ENTRY(p, m, f, a) do {} while (0) +#define DTRACE_NIF_RETURN(p, m, f, a) do {} while (0) + +#endif /* HAVE_DTRACE */ + /* * process_main() is called twice: * The first call performs some initialisation, including exporting @@ -1221,6 +1361,28 @@ void process_main(void) #endif SWAPIN; ASSERT(VALID_INSTR(next)); + + if (DTRACE_ENABLED(process_scheduled)) { + DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(fun_buf, DTRACE_TERM_BUF_SIZE); + dtrace_proc_str(c_p, process_buf); + + if (ERTS_PROC_IS_EXITING(c_p)) { + strcpy(fun_buf, ""); + } else { + BeamInstr *fptr = find_function_from_pc(c_p->i); + if (fptr) { + dtrace_fun_decode(c_p, (Eterm)fptr[0], + (Eterm)fptr[1], (Uint)fptr[2], + NULL, fun_buf); + } else { + snprintf(fun_buf, sizeof(fun_buf), "", next); + } + } + + DTRACE2(process_scheduled, process_buf, fun_buf); + } + Goto(next); } @@ -1486,7 +1648,13 @@ void process_main(void) OpCase(return): { + BeamInstr* fptr; SET_I(c_p->cp); + + if (DTRACE_ENABLED(function_return) && (fptr = find_function_from_pc(c_p->cp))) { + DTRACE_RETURN(c_p, (Eterm)fptr[0], (Eterm)fptr[1], (Uint)fptr[2]); + } + /* * We must clear the CP to make sure that a stale value do not * create a false module dependcy preventing code upgrading. @@ -1755,6 +1923,7 @@ void process_main(void) * remove it... */ ASSERT(!msgp->data.attached); + /* TODO: Add DTrace probe for this bad message situation? */ UNLINK_MESSAGE(c_p, msgp); free_message(msgp); goto loop_rec__; @@ -1798,6 +1967,22 @@ void process_main(void) seq_trace_output(SEQ_TRACE_TOKEN(c_p), msg, SEQ_TRACE_RECEIVE, c_p->id, c_p); } + 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; + + dtrace_proc_str(c_p, receiver_name); + token2 = SEQ_TRACE_TOKEN(c_p); + if (token2 != NIL) { + tok_label = signed_val(SEQ_TRACE_T_LABEL(token2)); + tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token2)); + tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token2)); + } + DTRACE6(message_receive, + receiver_name, size_object(ERL_MESSAGE_TERM(msgp)), + c_p->msg.len - 1, tok_label, tok_lastcnt, tok_serial); + } UNLINK_MESSAGE(c_p, msgp); JOIN_MESSAGE(c_p); CANCEL_TIMER(c_p); @@ -3157,6 +3342,8 @@ void process_main(void) */ BifFunction vbf; + DTRACE_NIF_ENTRY(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]); + c_p->current = I-3; /* current and vbf set to please handle_error */ SWAPOUT; c_p->fcalls = FCALLS - 1; @@ -3178,6 +3365,9 @@ void process_main(void) ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(nif_bif_result)); PROCESS_MAIN_CHK_LOCKS(c_p); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); + + DTRACE_NIF_RETURN(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]); + goto apply_bif_or_nif_epilogue; OpCase(apply_bif): @@ -3197,6 +3387,8 @@ void process_main(void) c_p->arity = 0; /* To allow garbage collection on ourselves * (check_process_code/2). */ + DTRACE_BIF_ENTRY(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]); + SWAPOUT; c_p->fcalls = FCALLS - 1; vbf = (BifFunction) Arg(0); @@ -3216,6 +3408,8 @@ void process_main(void) PROCESS_MAIN_CHK_LOCKS(c_p); } + DTRACE_BIF_RETURN(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]); + apply_bif_or_nif_epilogue: ERTS_SMP_REQ_PROC_MAIN_LOCK(c_p); ERTS_HOLE_CHECK(c_p); @@ -5899,6 +6093,13 @@ apply(Process* p, Eterm module, Eterm function, Eterm args, Eterm* reg) save_calls(p, ep); } + if (DTRACE_ENABLED(function_entry) && ep->address) { + BeamInstr *fptr = find_function_from_pc(ep->address); + if (fptr) { + DTRACE_CALL(p, (Eterm)fptr[0], (Eterm)fptr[1], (Uint)fptr[2]); + } + } + return ep->address; } @@ -5948,6 +6149,13 @@ fixed_apply(Process* p, Eterm* reg, Uint arity) save_calls(p, ep); } + if (DTRACE_ENABLED(function_entry)) { + BeamInstr *fptr = find_function_from_pc(ep->address); + if (fptr) { + DTRACE_CALL(p, (Eterm)fptr[0], (Eterm)fptr[1], (Uint)fptr[2]); + } + } + return ep->address; } @@ -5997,6 +6205,14 @@ erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* re c_p->max_arg_reg = sizeof(c_p->def_arg_reg)/sizeof(c_p->def_arg_reg[0]); } + if (DTRACE_ENABLED(process_hibernate)) { + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); + dtrace_fun_decode(c_p, module, function, arity, + process_name, mfa); + DTRACE2(process_hibernate, process_name, mfa); + } + /* * Arrange for the process to be resumed at the given MFA with * the stack cleared. @@ -6071,6 +6287,14 @@ call_fun(Process* p, /* Current process. */ code_ptr = fe->address; actual_arity = (int) code_ptr[-1]; + if (DTRACE_ENABLED(function_entry)) { + BeamInstr *fptr = find_function_from_pc(code_ptr); + + if (fptr) { + DTRACE_CALL(p, fe->module, (Eterm)fptr[1], actual_arity); + } + } + if (actual_arity == arity+num_free) { if (num_free == 0) { return code_ptr; @@ -6089,7 +6313,7 @@ call_fun(Process* p, /* Current process. */ } else { /* * Something wrong here. First build a list of the arguments. - */ + */ if (is_non_value(args)) { Uint sz = 2 * arity; @@ -6164,6 +6388,7 @@ call_fun(Process* p, /* Current process. */ actual_arity = (int) ep->code[2]; if (arity == actual_arity) { + DTRACE_CALL(p, ep->code[0], ep->code[1], (Uint)ep->code[2]); return ep->address; } else { /* @@ -6239,6 +6464,7 @@ call_fun(Process* p, /* Current process. */ reg[1] = function; reg[2] = args; } + DTRACE_CALL(p, module, function, arity); return ep->address; } else { badfun: diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c index 1d968fb147..4ee60807d9 100644 --- a/erts/emulator/beam/copy.c +++ b/erts/emulator/beam/copy.c @@ -30,6 +30,7 @@ #include "big.h" #include "erl_binary.h" #include "erl_bits.h" +#include "dtrace-wrapper.h" #ifdef HYBRID MA_STACK_DECLARE(src); @@ -59,6 +60,12 @@ copy_object(Eterm obj, Process* to) Eterm* hp = HAlloc(to, size); Eterm res; + if (DTRACE_ENABLED(copy_object)) { + DTRACE_CHARBUF(proc_name, 64); + + erts_snprintf(proc_name, sizeof(proc_name), "%T", to->id); + DTRACE2(copy_object, proc_name, size); + } res = copy_struct(obj, size, &hp, &to->off_heap); #ifdef DEBUG if (eq(obj, res) == 0) { @@ -213,6 +220,8 @@ Eterm copy_struct(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap) if (IS_CONST(obj)) return obj; + DTRACE1(copy_struct, (int32_t)sz); + hp = htop = *hpp; hbot = htop + sz; hstart = (char *)htop; diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index bee61e7273..6f6b04d278 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -42,6 +42,7 @@ #include "external.h" #include "erl_binary.h" #include "erl_thr_progress.h" +#include "dtrace-wrapper.h" /* Turn this on to get printouts of all distribution messages * which go on the line @@ -740,6 +741,11 @@ 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; + DTRACE_CHARBUF(node_name, 64); + DTRACE_CHARBUF(sender_name, 64); + DTRACE_CHARBUF(receiver_name, 64); UseTmpHeapNoproc(5); if (SEQ_TRACE_TOKEN(sender) != NIL) { @@ -747,12 +753,28 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message) token = SEQ_TRACE_TOKEN(sender); seq_trace_output(token, message, SEQ_TRACE_SEND, remote, sender); } + *node_name = *sender_name = *receiver_name = '\0'; + if (DTRACE_ENABLED(message_send) || DTRACE_ENABLED(message_send_remote)) { + erts_snprintf(node_name, sizeof(node_name), "%T", dsdp->dep->sysname); + erts_snprintf(sender_name, sizeof(sender_name), "%T", sender->id); + erts_snprintf(receiver_name, sizeof(receiver_name), "%T", remote); + msize = size_object(message); + if (token != NIL) { + tok_label = signed_val(SEQ_TRACE_T_LABEL(token)); + tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token)); + tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); + } + } if (token != NIL) ctl = TUPLE4(&ctl_heap[0], make_small(DOP_SEND_TT), am_Cookie, remote, token); else ctl = TUPLE3(&ctl_heap[0], make_small(DOP_SEND), am_Cookie, remote); + DTRACE6(message_send, sender_name, receiver_name, + msize, tok_label, tok_lastcnt, tok_serial); + DTRACE7(message_send_remote, sender_name, node_name, receiver_name, + msize, tok_label, tok_lastcnt, tok_serial); res = dsig_send(dsdp, ctl, message, 0); UnUseTmpHeapNoproc(5); return res; @@ -766,6 +788,11 @@ 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; + DTRACE_CHARBUF(node_name, 64); + DTRACE_CHARBUF(sender_name, 64); + DTRACE_CHARBUF(receiver_name, 128); UseTmpHeapNoproc(6); if (SEQ_TRACE_TOKEN(sender) != NIL) { @@ -773,6 +800,19 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message) token = SEQ_TRACE_TOKEN(sender); seq_trace_output(token, message, SEQ_TRACE_SEND, remote_name, sender); } + *node_name = *sender_name = *receiver_name = '\0'; + if (DTRACE_ENABLED(message_send) || DTRACE_ENABLED(message_send_remote)) { + erts_snprintf(node_name, sizeof(node_name), "%T", dsdp->dep->sysname); + erts_snprintf(sender_name, sizeof(sender_name), "%T", sender->id); + erts_snprintf(receiver_name, sizeof(receiver_name), + "{%T,%s}", remote_name, node_name); + msize = size_object(message); + if (token != NIL) { + tok_label = signed_val(SEQ_TRACE_T_LABEL(token)); + tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token)); + tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); + } + } if (token != NIL) ctl = TUPLE5(&ctl_heap[0], make_small(DOP_REG_SEND_TT), @@ -780,6 +820,10 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message) else ctl = TUPLE4(&ctl_heap[0], make_small(DOP_REG_SEND), sender->id, am_Cookie, remote_name); + DTRACE6(message_send, sender_name, receiver_name, + msize, tok_label, tok_lastcnt, tok_serial); + DTRACE7(message_send_remote, sender_name, node_name, receiver_name, + msize, tok_label, tok_lastcnt, tok_serial); res = dsig_send(dsdp, ctl, message, 0); UnUseTmpHeapNoproc(6); return res; @@ -793,6 +837,12 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote, Eterm ctl; DeclareTmpHeapNoproc(ctl_heap,6); int res; + Process *sender = dsdp->proc; + Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0; + DTRACE_CHARBUF(node_name, 64); + DTRACE_CHARBUF(sender_name, 64); + DTRACE_CHARBUF(remote_name, 128); + DTRACE_CHARBUF(reason_str, 128); UseTmpHeapNoproc(6); if (token != NIL) { @@ -803,6 +853,21 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote, } else { ctl = TUPLE4(&ctl_heap[0], make_small(DOP_EXIT), local, remote, reason); } + *node_name = *sender_name = *remote_name = '\0'; + if (DTRACE_ENABLED(process_exit_signal_remote)) { + erts_snprintf(node_name, sizeof(node_name), "%T", dsdp->dep->sysname); + erts_snprintf(sender_name, sizeof(sender_name), "%T", sender->id); + erts_snprintf(remote_name, sizeof(remote_name), + "{%T,%s}", remote, node_name); + erts_snprintf(reason_str, sizeof(reason), "%T", reason); + if (token != NIL) { + tok_label = signed_val(SEQ_TRACE_T_LABEL(token)); + tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token)); + tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); + } + } + DTRACE7(process_exit_signal_remote, sender_name, node_name, + remote_name, reason_str, tok_label, tok_lastcnt, tok_serial); /* forced, i.e ignore busy */ res = dsig_send(dsdp, ctl, THE_NON_VALUE, 1); UnUseTmpHeapNoproc(6); @@ -1619,6 +1684,16 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy) if (!(dep->qflgs & ERTS_DE_QFLG_BUSY)) { if (suspended) resume = 1; /* was busy when we started, but isn't now */ + if (resume && DTRACE_ENABLED(dist_port_not_busy)) { + DTRACE_CHARBUF(port_str, 64); + DTRACE_CHARBUF(remote_str, 64); + + erts_snprintf(port_str, sizeof(port_str), "%T", cid); + erts_snprintf(remote_str, sizeof(remote_str), + "%T", dep->sysname); + DTRACE3(dist_port_not_busy, erts_this_node_sysname, + port_str, remote_str); + } } else { /* Enqueue suspended process on dist entry */ @@ -1668,6 +1743,17 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy) } if (suspended) { + if (!resume && DTRACE_ENABLED(dist_port_busy)) { + DTRACE_CHARBUF(port_str, 64); + DTRACE_CHARBUF(remote_str, 64); + DTRACE_CHARBUF(pid_str, 16); + + erts_snprintf(port_str, sizeof(port_str), "%T", cid); + erts_snprintf(remote_str, sizeof(remote_str), "%T", dep->sysname); + erts_snprintf(pid_str, sizeof(pid_str), "%T", c_p->id); + DTRACE4(dist_port_busy, erts_this_node_sysname, + port_str, remote_str, pid_str); + } if (!resume && erts_system_monitor_flags.busy_dist_port) monitor_generic(c_p, am_busy_dist_port, cid); return ERTS_DSIG_SEND_YIELD; @@ -1691,6 +1777,16 @@ dist_port_command(Port *prt, ErtsDistOutputBuf *obuf) "(%beu bytes) passed.\n", size); + if (DTRACE_ENABLED(dist_output)) { + DTRACE_CHARBUF(port_str, 64); + DTRACE_CHARBUF(remote_str, 64); + + erts_snprintf(port_str, sizeof(port_str), "%T", prt->id); + erts_snprintf(remote_str, sizeof(remote_str), + "%T", prt->dist_entry->sysname); + DTRACE4(dist_output, erts_this_node_sysname, port_str, + remote_str, size); + } prt->caller = NIL; fpe_was_unmasked = erts_block_fpe(); (*prt->drv_ptr->output)((ErlDrvData) prt->drv_data, @@ -1733,6 +1829,16 @@ dist_port_commandv(Port *prt, ErtsDistOutputBuf *obuf) ASSERT(prt->drv_ptr->outputv); + if (DTRACE_ENABLED(dist_outputv)) { + DTRACE_CHARBUF(port_str, 64); + DTRACE_CHARBUF(remote_str, 64); + + erts_snprintf(port_str, sizeof(port_str), "%T", prt->id); + erts_snprintf(remote_str, sizeof(remote_str), + "%T", prt->dist_entry->sysname); + DTRACE4(dist_outputv, erts_this_node_sysname, port_str, + remote_str, size); + } prt->caller = NIL; fpe_was_unmasked = erts_block_fpe(); (*prt->drv_ptr->outputv)((ErlDrvData) prt->drv_data, &eiov); @@ -2052,6 +2158,16 @@ erts_dist_command(Port *prt, int reds_limit) void erts_dist_port_not_busy(Port *prt) { + if (DTRACE_ENABLED(dist_port_not_busy)) { + DTRACE_CHARBUF(port_str, 64); + DTRACE_CHARBUF(remote_str, 64); + + erts_snprintf(port_str, sizeof(port_str), "%T", prt->id); + erts_snprintf(remote_str, sizeof(remote_str), + "%T", prt->dist_entry->sysname); + DTRACE3(dist_port_not_busy, erts_this_node_sysname, + port_str, remote_str); + } erts_schedule_dist_command(prt, NULL); } @@ -2985,6 +3101,19 @@ send_nodes_mon_msgs(Process *c_p, Eterm what, Eterm node, Eterm type, Eterm reas ASSERT(is_immed(what)); ASSERT(is_immed(node)); ASSERT(is_immed(type)); + if (DTRACE_ENABLED(dist_monitor)) { + DTRACE_CHARBUF(what_str, 12); + DTRACE_CHARBUF(node_str, 64); + DTRACE_CHARBUF(type_str, 12); + DTRACE_CHARBUF(reason_str, 64); + + erts_snprintf(what_str, sizeof(what_str), "%T", what); + erts_snprintf(node_str, sizeof(node_str), "%T", node); + erts_snprintf(type_str, sizeof(type_str), "%T", type); + erts_snprintf(reason_str, sizeof(reason_str), "%T", reason); + DTRACE5(dist_monitor, erts_this_node_sysname, + what_str, node_str, type_str, reason_str); + } ERTS_SMP_LC_ASSERT(!c_p || (erts_proc_lc_my_proc_locks(c_p) diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c index 8bca9ae582..72dcc99f4f 100644 --- a/erts/emulator/beam/erl_async.c +++ b/erts/emulator/beam/erl_async.c @@ -26,6 +26,7 @@ #include "erl_threads.h" #include "erl_thr_queue.h" #include "erl_async.h" +#include "dtrace-wrapper.h" #define ERTS_MAX_ASYNC_READY_CALLS_IN_SEQ 20 @@ -121,6 +122,14 @@ typedef struct { #endif } ErtsAsyncData; +/* + * Some compilers, e.g. GCC 4.2.1 and -O3, will optimize away DTrace + * calls if they're the last thing in the function. :-( + * Many thanks to Trond Norbye, via: + * https://github.com/memcached/memcached/commit/6298b3978687530bc9d219b6ac707a1b681b2a46 + */ +static unsigned gcc_optimizer_hack = 0; + int erts_async_max_threads; /* Initialized by erl_init.c */ int erts_async_thread_suggested_stack_size; /* Initialized by erl_init.c */ @@ -244,6 +253,9 @@ 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; + if (is_internal_port(a->port)) { #if ERTS_USE_ASYNC_READY_Q ErtsAsyncReadyQ *arq = async_ready_q(a->sched_id); @@ -259,6 +271,13 @@ static ERTS_INLINE void async_add(ErtsAsync *a, ErtsAsyncQ* q) #endif erts_thr_q_enqueue(&q->thr_q, a); + if (DTRACE_ENABLED(aio_pool_add)) { + DTRACE_CHARBUF(port_str, 16); + + erts_snprintf(port_str, sizeof(port_str), "%T", a->port); + DTRACE2(aio_pool_add, port_str, len); + } + gcc_optimizer_hack++; } static ERTS_INLINE ErtsAsync *async_get(ErtsThrQ_t *q, @@ -269,6 +288,8 @@ 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; while (1) { ErtsAsync *a = (ErtsAsync *) erts_thr_q_dequeue(q); @@ -280,7 +301,12 @@ static ERTS_INLINE ErtsAsync *async_get(ErtsThrQ_t *q, if (saved_fin_deq) erts_thr_q_append_finalize_dequeue_data(&a->q.fin_deq, &fin_deq); #endif + if (DTRACE_ENABLED(aio_pool_get)) { + DTRACE_CHARBUF(port_str, 16); + erts_snprintf(port_str, sizeof(port_str), "%T", a->port); + DTRACE2(aio_pool_get, port_str, len); + } return a; } diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c index 37d540b41b..3326fd84df 100644 --- a/erts/emulator/beam/erl_bif_ddll.c +++ b/erts/emulator/beam/erl_bif_ddll.c @@ -45,6 +45,7 @@ #include "big.h" #include "dist.h" #include "erl_version.h" +#include "dtrace-wrapper.h" #ifdef ERTS_SMP #define DDLL_SMP 1 @@ -1647,6 +1648,7 @@ static int do_unload_driver_entry(DE_Handle *dh, Eterm *save_name) diver_list lock here!*/ if (q->finish) { int fpe_was_unmasked = erts_block_fpe(); + DTRACE1(driver_finish, q->name); (*(q->finish))(); erts_unblock_fpe(fpe_was_unmasked); } diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index ebd475f73a..90bbb34927 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -114,6 +114,9 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE #endif #ifdef VALGRIND " [valgrind-compiled]" +#endif +#ifdef HAVE_DTRACE + " [dtrace]" #endif "\n"); diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index cd423eb200..8caa64b97d 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -40,6 +40,7 @@ #include "external.h" #include "packet_parser.h" #include "erl_bits.h" +#include "dtrace-wrapper.h" static int open_port(Process* p, Eterm name, Eterm settings, int *err_nump); static byte* convert_environment(Process* p, Eterm env); @@ -343,6 +344,14 @@ port_call(Process* c_p, Eterm arg1, Eterm arg2, Eterm arg3) __FILE__, __LINE__, endp - (bytes + size)); } erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN); + if (DTRACE_ENABLED(driver_call)) { + DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); + + dtrace_pid_str(p->connected, process_str); + dtrace_port_str(p, port_str); + DTRACE5(driver_call, process_str, port_str, p->name, op, real_size); + } prc = (char *) port_resp; fpe_was_unmasked = erts_block_fpe(); ret = drv->call((ErlDrvData)p->drv_data, @@ -539,6 +548,16 @@ BIF_RETTYPE port_connect_2(BIF_ALIST_2) prt->connected = pid; /* internal pid */ erts_smp_port_unlock(prt); + if (DTRACE_ENABLED(port_connect)) { + DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(newprocess_str, DTRACE_TERM_BUF_SIZE); + + dtrace_pid_str(prt->connected, process_str); + erts_snprintf(port_str, sizeof(port_str), "%T", prt->id); + dtrace_proc_str(rp, newprocess_str); + DTRACE4(port_connect, process_str, port_str, prt->name, newprocess_str); + } BIF_RET(am_true); } @@ -904,6 +923,14 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_nump) erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN); port_num = erts_open_driver(driver, p->id, name_buf, &opts, err_nump); + if (port_num >= 0 && DTRACE_ENABLED(port_open)) { + DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); + + dtrace_proc_str(p, process_str); + erts_snprintf(port_str, sizeof(port_str), "%T", erts_port[port_num].id); + DTRACE3(port_open, process_str, name_buf, port_str); + } erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN); diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index bde87b8346..858ae32ad5 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -35,6 +35,7 @@ #include "hipe_stack.h" #include "hipe_mode_switch.h" #endif +#include "dtrace-wrapper.h" #define ERTS_INACT_WR_PB_LEAVE_MUCH_LIMIT 1 #define ERTS_INACT_WR_PB_LEAVE_MUCH_PERCENTAGE 20 @@ -349,6 +350,7 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj) Uint reclaimed_now = 0; int done = 0; Uint ms1, s1, us1; + DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); if (IS_TRACED_FL(p, F_TRACE_GC)) { trace_gc(p, am_gc_start); @@ -370,14 +372,26 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj) FLAGS(p) |= F_NEED_FULLSWEEP; } + *pidbuf = '\0'; + if (DTRACE_ENABLED(gc_major_start) + || DTRACE_ENABLED(gc_major_end) + || DTRACE_ENABLED(gc_minor_start) + || DTRACE_ENABLED(gc_minor_end)) { + dtrace_proc_str(p, pidbuf); + } + /* * Test which type of GC to do. */ while (!done) { if ((FLAGS(p) & F_NEED_FULLSWEEP) != 0) { + DTRACE2(gc_major_start, pidbuf, need); done = major_collection(p, need, objv, nobj, &reclaimed_now); + DTRACE2(gc_major_end, pidbuf, reclaimed_now); } else { + DTRACE2(gc_minor_start, pidbuf, need); done = minor_collection(p, need, objv, nobj, &reclaimed_now); + DTRACE2(gc_minor_end, pidbuf, reclaimed_now); } } @@ -1118,6 +1132,13 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj) sys_memcpy(n_heap + new_sz - n, p->stop, n * sizeof(Eterm)); p->stop = n_heap + new_sz - n; + if (HEAP_SIZE(p) != new_sz && DTRACE_ENABLED(process_heap_grow)) { + DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); + + dtrace_proc_str(p, pidbuf); + DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz); + } + ERTS_HEAP_FREE(ERTS_ALC_T_HEAP, (void*)HEAP_START(p), HEAP_SIZE(p) * sizeof(Eterm)); @@ -1339,6 +1360,13 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl) sys_memcpy(n_heap + new_sz - n, p->stop, n * sizeof(Eterm)); p->stop = n_heap + new_sz - n; + if (HEAP_SIZE(p) != new_sz && DTRACE_ENABLED(process_heap_grow)) { + DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); + + dtrace_proc_str(p, pidbuf); + DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz); + } + ERTS_HEAP_FREE(ERTS_ALC_T_HEAP, (void *) HEAP_START(p), (HEAP_END(p) - HEAP_START(p)) * sizeof(Eterm)); @@ -2009,6 +2037,14 @@ grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj) HEAP_TOP(p) = new_heap + heap_size; HEAP_START(p) = new_heap; } + + if (DTRACE_ENABLED(process_heap_grow)) { + DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); + + dtrace_proc_str(p, pidbuf); + DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz); + } + HEAP_SIZE(p) = new_sz; } @@ -2018,8 +2054,8 @@ shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj) Eterm* new_heap; 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 * @@ -2047,6 +2083,14 @@ shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj) HEAP_TOP(p) = new_heap + heap_size; HEAP_START(p) = new_heap; } + + if (DTRACE_ENABLED(process_heap_shrink)) { + DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); + + dtrace_proc_str(p, pidbuf); + DTRACE3(process_heap_shrink, pidbuf, HEAP_SIZE(p), new_sz); + } + HEAP_SIZE(p) = new_sz; } diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c index 09e85893c3..561570c30e 100644 --- a/erts/emulator/beam/erl_lock_check.c +++ b/erts/emulator/beam/erl_lock_check.c @@ -182,6 +182,9 @@ static erts_lc_lock_order_t erts_lock_order[] = { #ifdef DEBUG { "save_ops_lock", NULL }, #endif +#endif +#ifdef HAVE_DTRACE + { "efile_drv dtrace mutex", NULL }, #endif { "mtrace_buf", NULL }, { "erts_alloc_hard_debug", NULL } diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index ab1ab7b1ea..8489353c9e 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -31,6 +31,7 @@ #include "erl_process.h" #include "erl_nmgc.h" #include "erl_binary.h" +#include "dtrace-wrapper.h" ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(message, ErlMessage, @@ -335,6 +336,7 @@ erts_queue_dist_message(Process *rcvr, Eterm token) { ErlMessage* mp; + Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0; #ifdef ERTS_SMP ErtsProcLocks need_locks; #endif @@ -376,6 +378,19 @@ erts_queue_dist_message(Process *rcvr, message_free(mp); msg = erts_msg_distext2heap(rcvr, rcvr_locks, &mbuf, &token, dist_ext); if (is_value(msg)) + if (DTRACE_ENABLED(message_queued)) { + DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE); + + dtrace_proc_str(rcvr, receiver_name); + if (token != NIL) { + tok_label = signed_val(SEQ_TRACE_T_LABEL(token)); + tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token)); + tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); + } + DTRACE6(message_queued, + receiver_name, size_object(msg), rcvr->msg.len, + tok_label, tok_lastcnt, tok_serial); + } erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token); } else { @@ -385,6 +400,22 @@ erts_queue_dist_message(Process *rcvr, ERL_MESSAGE_TOKEN(mp) = token; mp->next = NULL; + if (DTRACE_ENABLED(message_queued)) { + DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE); + + dtrace_proc_str(rcvr, receiver_name); + if (token != NIL) { + tok_label = signed_val(SEQ_TRACE_T_LABEL(token)); + tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token)); + tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); + } + /* + * TODO: We don't know the real size of the external message here. + * -1 will appear to a D script as 4294967295. + */ + DTRACE6(message_queued, receiver_name, -1, rcvr->msg.len + 1, + tok_label, tok_lastcnt, tok_serial); + } mp->data.dist_ext = dist_ext; LINK_MESSAGE(rcvr, mp); @@ -462,12 +493,27 @@ erts_queue_message(Process* receiver, LINK_MESSAGE(receiver, mp); #endif + if (DTRACE_ENABLED(message_queued)) { + DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE); + Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0; + + dtrace_proc_str(receiver, receiver_name); + if (seq_trace_token != NIL && is_tuple(seq_trace_token)) { + tok_label = signed_val(SEQ_TRACE_T_LABEL(seq_trace_token)); + tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(seq_trace_token)); + tok_serial = signed_val(SEQ_TRACE_T_SERIAL(seq_trace_token)); + } + DTRACE6(message_queued, + receiver_name, size_object(message), receiver->msg.len, + tok_label, tok_lastcnt, tok_serial); + } + notify_new_message(receiver); if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) { trace_receive(receiver, message); } - + #ifndef ERTS_SMP ERTS_HOLE_CHECK(receiver); #endif @@ -774,11 +820,19 @@ erts_send_message(Process* sender, Uint msize; ErlHeapFragment* bp = NULL; Eterm token = NIL; + DTRACE_CHARBUF(sender_name, 64); + DTRACE_CHARBUF(receiver_name, 64); + Sint tok_label = 0, tok_lastcnt = 0, tok_serial = 0; BM_STOP_TIMER(system); BM_MESSAGE(message,sender,receiver); BM_START_TIMER(send); + *sender_name = *receiver_name = '\0'; + if (DTRACE_ENABLED(message_send)) { + erts_snprintf(sender_name, sizeof(sender_name), "%T", sender->id); + erts_snprintf(receiver_name, sizeof(receiver_name), "%T", receiver->id); + } if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) { Eterm* hp; @@ -802,6 +856,16 @@ erts_send_message(Process* sender, BM_MESSAGE_COPIED(msize); BM_SWAP_TIMER(copy,send); + if (DTRACE_ENABLED(message_send)) { + Eterm token2 = NIL; + + token2 = SEQ_TRACE_TOKEN(sender); + tok_label = signed_val(SEQ_TRACE_T_LABEL(token2)); + tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token2)); + tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token2)); + DTRACE6(message_send, sender_name, receiver_name, + msize, tok_label, tok_lastcnt, tok_serial); + } erts_queue_message(receiver, receiver_locks, bp, @@ -835,6 +899,8 @@ erts_send_message(Process* sender, #endif LAZY_COPY(sender,message); BM_SWAP_TIMER(copy,send); + DTRACE6(message_send, sender_name, receiver_name, + size_object(message)msize, tok_label, tok_lastcnt, tok_serial); ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = NIL; mp->next = NULL; @@ -874,6 +940,8 @@ erts_send_message(Process* sender, { ErlMessage* mp = message_alloc(); + DTRACE6(message_send, sender_name, receiver_name, + size_object(message), tok_label, tok_lastcnt, tok_serial); mp->data.attached = NULL; ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = NIL; @@ -908,6 +976,8 @@ erts_send_message(Process* sender, message = copy_struct(message, msize, &hp, ohp); BM_MESSAGE_COPIED(msz); BM_SWAP_TIMER(copy,send); + DTRACE6(message_send, sender_name, receiver_name, + msize, tok_label, tok_lastcnt, tok_serial); erts_queue_message(receiver, receiver_locks, bp, message, token); BM_SWAP_TIMER(send,system); #else @@ -928,6 +998,8 @@ erts_send_message(Process* sender, message = copy_struct(message, msize, &hp, &receiver->off_heap); BM_MESSAGE_COPIED(msize); BM_SWAP_TIMER(copy,send); + DTRACE6(message_send, sender_name, receiver_name, + (uint32_t)msize, tok_label, tok_lastcnt, tok_serial); ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = NIL; mp->next = NULL; diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 58a09986d2..dc4049327d 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -66,6 +66,7 @@ static void add_readonly_check(ErlNifEnv*, unsigned char* ptr, unsigned sz); static int is_offheap(const ErlOffHeap* off_heap); #endif +void dtrace_nifenv_str(ErlNifEnv *, char *); #define MIN_HEAP_FRAG_SZ 200 static Eterm* alloc_heap_heavy(ErlNifEnv* env, unsigned need, Eterm* hp); @@ -1779,6 +1780,11 @@ void erl_nif_init() resource_type_list.name = THE_NON_VALUE; } +void dtrace_nifenv_str(ErlNifEnv *env, char *process_buf) +{ + dtrace_pid_str(env->proc->id, process_buf); +} + #ifdef READONLY_CHECK /* Use checksums to assert that NIFs do not write into inspected binaries */ diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c index 908ba755ed..1481f66b55 100644 --- a/erts/emulator/beam/erl_node_tables.c +++ b/erts/emulator/beam/erl_node_tables.c @@ -27,6 +27,7 @@ #include "big.h" #include "error.h" #include "erl_thr_progress.h" +#include "dtrace-wrapper.h" Hash erts_dist_table; Hash erts_node_table; @@ -42,6 +43,8 @@ Sint erts_no_of_not_connected_dist_entries; DistEntry *erts_this_dist_entry; ErlNode *erts_this_node; +char erts_this_node_sysname_BUFFER[256], + *erts_this_node_sysname = "uninitialized yet"; static Uint node_entries; static Uint dist_entries; @@ -702,6 +705,9 @@ erts_set_this_node(Eterm sysname, Uint creation) (void) hash_erase(&erts_node_table, (void *) erts_this_node); erts_this_node->sysname = sysname; erts_this_node->creation = creation; + erts_this_node_sysname = erts_this_node_sysname_BUFFER; + erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname), + "%T", sysname); (void) hash_put(&erts_node_table, (void *) erts_this_node); erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx); @@ -789,6 +795,9 @@ void erts_init_node_tables(void) erts_this_node->sysname = am_Noname; erts_this_node->creation = 0; erts_this_node->dist_entry = erts_this_dist_entry; + erts_this_node_sysname = erts_this_node_sysname_BUFFER; + erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname), + "%T", erts_this_node->sysname); (void) hash_put(&erts_node_table, (void *) erts_this_node); diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h index 8abb748a78..5cfd0ac641 100644 --- a/erts/emulator/beam/erl_node_tables.h +++ b/erts/emulator/beam/erl_node_tables.h @@ -169,7 +169,7 @@ extern Sint erts_no_of_not_connected_dist_entries; extern DistEntry *erts_this_dist_entry; extern ErlNode *erts_this_node; -extern char erts_this_node_sysname[256]; /* must match erl_node_tables.c */ +extern char *erts_this_node_sysname; /* must match erl_node_tables.c */ DistEntry *erts_channel_no_to_dist_entry(Uint); DistEntry *erts_sysname_to_connected_dist_entry(Eterm); diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index a2b08fcf56..25bba5cf17 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -32,6 +32,7 @@ #include "global.h" #include "erl_port_task.h" #include "dist.h" +#include "dtrace-wrapper.h" #if defined(DEBUG) && 0 #define HARD_DEBUG @@ -61,6 +62,16 @@ do { \ (P)->sched.next = NULL; \ } while (0) +#define DTRACE_DRIVER(PROBE_NAME, PP) \ + if (DTRACE_ENABLED(driver_ready_input)) { \ + DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); \ + \ + dtrace_pid_str(PP->connected, process_str); \ + dtrace_port_str(PP, port_str); \ + DTRACE3(PROBE_NAME, process_str, port_str, PP->name); \ + } + erts_smp_atomic_t erts_port_task_outstanding_io_tasks; struct ErtsPortTaskQueue_ { @@ -823,12 +834,15 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp) goto tasks_done; case ERTS_PORT_TASK_TIMEOUT: reds += ERTS_PORT_REDS_TIMEOUT; - if (!(pp->status & ERTS_PORT_SFLGS_DEAD)) + if (!(pp->status & ERTS_PORT_SFLGS_DEAD)) { + DTRACE_DRIVER(driver_timeout, pp); (*pp->drv_ptr->timeout)((ErlDrvData) pp->drv_data); + } break; case ERTS_PORT_TASK_INPUT: reds += ERTS_PORT_REDS_INPUT; ASSERT((pp->status & ERTS_PORT_SFLGS_DEAD) == 0); + DTRACE_DRIVER(driver_ready_input, pp); /* NOTE some windows drivers use ->ready_input for input and output */ (*pp->drv_ptr->ready_input)((ErlDrvData) pp->drv_data, ptp->event); io_tasks_executed++; @@ -836,12 +850,14 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp) case ERTS_PORT_TASK_OUTPUT: reds += ERTS_PORT_REDS_OUTPUT; ASSERT((pp->status & ERTS_PORT_SFLGS_DEAD) == 0); + DTRACE_DRIVER(driver_ready_output, pp); (*pp->drv_ptr->ready_output)((ErlDrvData) pp->drv_data, ptp->event); io_tasks_executed++; break; case ERTS_PORT_TASK_EVENT: reds += ERTS_PORT_REDS_EVENT; ASSERT((pp->status & ERTS_PORT_SFLGS_DEAD) == 0); + DTRACE_DRIVER(driver_event, pp); (*pp->drv_ptr->event)((ErlDrvData) pp->drv_data, ptp->event, ptp->event_data); io_tasks_executed++; break; diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 45f6dc800c..1173624f51 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -42,6 +42,7 @@ #include "erl_thr_progress.h" #include "erl_thr_queue.h" #include "erl_async.h" +#include "dtrace-wrapper.h" #define ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED (2000*CONTEXT_REDS) #define ERTS_RUNQ_CALL_CHECK_BALANCE_REDS \ @@ -6214,6 +6215,13 @@ Process *schedule(Process *p, int calls) int actual_reds; int reds; + if (p != NULL && DTRACE_ENABLED(process_unscheduled)) { + DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE); + + dtrace_proc_str(p, process_buf); + DTRACE1(process_unscheduled, process_buf); + } + if (ERTS_USE_MODIFIED_TIMING()) { context_reds = ERTS_MODIFIED_TIMING_CONTEXT_REDS; input_reductions = ERTS_MODIFIED_TIMING_INPUT_REDS; @@ -7384,6 +7392,14 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). VERBOSE(DEBUG_PROCESSES, ("Created a new process: %T\n",p->id)); + if (DTRACE_ENABLED(process_spawn)) { + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); + + dtrace_fun_decode(p, mod, func, arity, process_name, mfa); + DTRACE2(process_spawn, process_name, mfa); + } + error: erts_smp_proc_unlock(parent, ERTS_PROC_LOCKS_ALL_MINOR); @@ -7952,6 +7968,17 @@ send_exit_signal(Process *c_p, /* current process if and only ASSERT(reason != THE_NON_VALUE); + if(DTRACE_ENABLED(process_exit_signal) && is_pid(from)) { + DTRACE_CHARBUF(sender_str, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(receiver_str, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(reason_buf, DTRACE_TERM_BUF_SIZE); + + dtrace_pid_str(from, sender_str); + dtrace_proc_str(rp, receiver_str); + erts_snprintf(reason_buf, sizeof(reason_buf) - 1, "%T", reason); + DTRACE3(process_exit_signal, sender_str, receiver_str, reason_buf); + } + if (ERTS_PROC_IS_TRAPPING_EXITS(rp) && (reason != am_kill || (flags & ERTS_XSIG_FLG_IGN_KILL))) { if (is_not_nil(token) && token_update) @@ -8378,7 +8405,16 @@ erts_do_exit_process(Process* p, Eterm reason) p->arity = 0; /* No live registers */ p->fvalue = reason; - + + if (DTRACE_ENABLED(process_exit)) { + DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(reason_buf, 256); + + dtrace_proc_str(p, process_buf); + erts_snprintf(reason_buf, sizeof(reason_buf) - 1, "%T", reason); + DTRACE2(process_exit, process_buf, reason_buf); + } + #ifdef ERTS_SMP ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p); /* By locking all locks (main lock is already locked) when going diff --git a/erts/emulator/beam/erlang_dtrace.d b/erts/emulator/beam/erlang_dtrace.d new file mode 100644 index 0000000000..d8508426f4 --- /dev/null +++ b/erts/emulator/beam/erlang_dtrace.d @@ -0,0 +1,716 @@ +/* + * %CopyrightBegin% + * + * Copyright Dustin Sallings, Michal Ptaszek, Scott Lystig Fritchie 2011. + * 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/. + * + * 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. + * + * %CopyrightEnd% + */ + +/* + * A note on probe naming: if "__" appears in a provider probe + * definition, then two things happen during compilation: + * + * 1. The "__" will turn into a hypen, "-", for the probe name. + * 2. The "__" will turn into a single underscore, "_", for the + * macro names and function definitions that the compiler and + * C developers will see. + * + * We'll try to use the following naming convention. We're a bit + * limited because, as a USDT probe, we can only specify the 4th part + * of the probe name, e.g. erlang*:::mumble. The 2nd part of the + * probe name is always going to be "beam" or "beam.smp", and the 3rd + * part of the probe name will always be the name of the function + * that's calling the probe. + * + * So, all probes will be have names defined in this file using the + * convention category__name or category__sub_category__name. This + * will translate to probe names of category-name or + * category-sub_category-name. + * + * Each of "category", "sub_category", and "name" may have underscores + * but may not have hyphens. + */ + +provider erlang { + /** + * Fired when a message is sent from one local process to another. + * + * NOTE: The 'size' parameter is in machine-dependent words and + * that the actual size of any binary terms in the message + * are not included. + * + * @param sender the PID (string form) of the sender + * @param receiver the PID (string form) of the receiver + * @param size the size of the message being delivered (words) + * @param token_label for the sender's sequential trace token + * @param token_previous count for the sender's sequential trace token + * @param token_current count for the sender's sequential trace token + */ + probe message__send(char *sender, char *receiver, uint32_t size, + int token_label, int token_previous, int token_current); + + /** + * Fired when a message is sent from a local process to a remote process. + * + * NOTE: The 'size' parameter is in machine-dependent words and + * that the actual size of any binary terms in the message + * are not included. + * + * @param sender the PID (string form) of the sender + * @param node_name the Erlang node name (string form) of the receiver + * @param receiver the PID/name (string form) of the receiver + * @param size the size of the message being delivered (words) + * @param token_label for the sender's sequential trace token + * @param token_previous count for the sender's sequential trace token + * @param token_current count for the sender's sequential trace token + */ + probe message__send__remote(char *sender, char *node_name, char *receiver, + uint32_t size, + int token_label, int token_previous, int token_current); + + /** + * Fired when a message is queued to a local process. This probe + * will not fire if the sender's pid == receiver's pid. + * + * NOTE: The 'size' parameter is in machine-dependent words and + * that the actual size of any binary terms in the message + * are not included. + * + * NOTE: In cases of messages in external format (i.e. from another + * Erlang node), we probably don't know the message size + * without performing substantial extra computation. To + * avoid the extra CPU overhead, the message size may be + * reported as -1, which can appear to a D script as 4294967295. + * + * @param receiver the PID (string form) of the receiver + * @param size the size of the message being delivered (words) + * @param queue_len length of the queue of the receiving process + * @param token_label for the sender's sequential trace token + * @param token_previous count for the sender's sequential trace token + * @param token_current count for the sender's sequential trace token + */ + probe message__queued(char *receiver, uint32_t size, uint32_t queue_len, + int token_label, int token_previous, int token_current); + + /** + * Fired when a message is 'receive'd by a local process and removed + * from its mailbox. + * + * NOTE: The 'size' parameter is in machine-dependent words and + * that the actual size of any binary terms in the message + * are not included. + * + * NOTE: In cases of messages in external format (i.e. from another + * Erlang node), we probably don't know the message size + * without performing substantial extra computation. To + * avoid the extra CPU overhead, the message size may be + * reported as -1, which can appear to a D script as 4294967295. + * + * @param receiver the PID (string form) of the receiver + * @param size the size of the message being delivered (words) + * @param queue_len length of the queue of the receiving process + * @param token_label for the sender's sequential trace token + * @param token_previous count for the sender's sequential trace token + * @param token_current count for the sender's sequential trace token + */ + probe message__receive(char *receiver, uint32_t size, uint32_t queue_len, + int token_label, int token_previous, int token_current); + + /** + * Fired when an Eterm structure is being copied. + * + * NOTE: Due to the placement of this probe, the process ID of + * owner of the Eterm is not available. + * + * @param size the size of the structure + */ + probe copy__struct(uint32_t size); + + /** + * Fired when an Eterm is being copied onto a process. + * + * @param proc the PID (string form) of the recipient process + * @param size the size of the structure + */ + probe copy__object(char *proc, uint32_t size); + + /* PID, Module, Function, Arity */ + + /** + * Fired whenever a user function is being called. + * + * @param p the PID (string form) of the process + * @param mfa the m:f/a of the function + * @param depth the stack depth + */ + probe function__entry(char *p, char *mfa, int depth); + + /** + * Fired whenever a user function returns. + * + * @param p the PID (string form) of the process + * @param mfa the m:f/a of the function + * @param depth the stack depth + */ + probe function__return(char *p, char *mfa, int depth); + + /** + * Fired whenever a Built In Function is called. + * + * @param p the PID (string form) of the process + * @param mfa the m:f/a of the function + */ + probe bif__entry(char *p, char *mfa); + + /** + * Fired whenever a Built In Function returns. + * + * @param p the PID (string form) of the process + * @param mfa the m:f/a of the function + */ + probe bif__return(char *p, char *mfa); + + /** + * Fired whenever a Native Function is called. + * + * @param p the PID (string form) of the process + * @param mfa the m:f/a of the function + */ + probe nif__entry(char *p, char *mfa); + + /** + * Fired whenever a Native Function returns. + * + * @param p the PID (string form) of the process + * @param mfa the m:f/a of the function + */ + probe nif__return(char *p, char *mfa); + + /** + * Fired when a major GC is starting. + * + * @param p the PID (string form) of the exiting process + * @param need the number of words needed on the heap + */ + probe gc_major__start(char *p, int need); + + /** + * Fired when a minor GC is starting. + * + * @param p the PID (string form) of the exiting process + * @param need the number of words needed on the heap + */ + probe gc_minor__start(char *p, int need); + + /** + * Fired when a major GC is starting. + * + * @param p the PID (string form) of the exiting process + * @param reclaimed the amount of space reclaimed + */ + probe gc_major__end(char *p, int reclaimed); + + /** + * Fired when a minor GC is starting. + * + * @param p the PID (string form) of the exiting process + * @param reclaimed the amount of space reclaimed + */ + probe gc_minor__end(char *p, int reclaimed); + + /** + * Fired when a process is spawned. + * + * @param p the PID (string form) of the new process. + * @param mfa the m:f/a of the function + */ + probe process__spawn(char *p, char *mfa); + + /** + * Fired when a process is exiting. + * + * @param p the PID (string form) of the exiting process + * @param reason the reason for the exit (may be truncated) + */ + probe process__exit(char *p, char *reason); + + /** + * Fired when exit signal is delivered to a local process. + * + * @param sender the PID (string form) of the exiting process + * @param receiver the PID (string form) of the process receiving EXIT signal + * @param reason the reason for the exit (may be truncated) + */ + probe process__exit_signal(char *sender, char *receiver, char *reason); + + /** + * Fired when exit signal is delivered to a remote process. + * + * @param sender the PID (string form) of the exiting process + * @param node_name the Erlang node name (string form) of the receiver + * @param receiver the PID (string form) of the process receiving EXIT signal + * @param reason the reason for the exit (may be truncated) + * @param token_label for the sender's sequential trace token + * @param token_previous count for the sender's sequential trace token + * @param token_current count for the sender's sequential trace token + */ + probe process__exit_signal__remote(char *sender, char *node_name, + char *receiver, char *reason, + int token_label, int token_previous, int token_current); + + /** + * Fired when a process is scheduled. + * + * @param p the PID (string form) of the newly scheduled process + * @param mfa the m:f/a of the function it should run next + */ + probe process__scheduled(char *p, char *mfa); + + /** + * Fired when a process is unscheduled. + * + * @param p the PID (string form) of the process that has been + * unscheduled. + */ + probe process__unscheduled(char *p); + + /** + * Fired when a process goes into hibernation. + * + * @param p the PID (string form) of the process entering hibernation + * @param mfa the m:f/a of the location to resume + */ + probe process__hibernate(char *p, char *mfa); + + /** + * Fired when a process is unblocked after a port has been unblocked. + * + * @param p the PID (string form) of the process that has been + * unscheduled. + * @param port the port that is no longer busy (i.e., is now unblocked) + */ + probe process__port_unblocked(char *p, char *port); + + /** + * Fired when process' heap is growing. + * + * @param p the PID (string form) + * @param old_size the size of the old heap + * @param new_size the size of the new heap + */ + probe process__heap_grow(char *p, int old_size, int new_size); + + /** + * Fired when process' heap is shrinking. + * + * @param p the PID (string form) + * @param old_size the size of the old heap + * @param new_size the size of the new heap + */ + probe process__heap_shrink(char *p, int old_size, int new_size); + + /* network distribution */ + + /** + * Fired when network distribution event monitor events are triggered. + * + * @param node the name of the reporting node + * @param what the type of event, e.g., nodeup, nodedown + * @param monitored_node the name of the monitored node + * @param type the type of node, e.g., visible, hidden + * @param reason the reason term, e.g., normal, connection_closed, term() + */ + probe dist__monitor(char *node, char *what, char *monitored_node, + char *type, char *reason); + + /** + * Fired when network distribution port is busy (i.e. blocked), + * usually due to the remote node not consuming distribution + * data quickly enough. + * + * @param node the name of the reporting node + * @param port the port ID of the busy port + * @param remote_node the name of the remote node. + * @param pid the PID (string form) of the local process that has + * become unschedulable until the port becomes unblocked. + */ + probe dist__port_busy(char *node, char *port, char *remote_node, + char *pid); + + /** + * Fired when network distribution's driver's "output" callback is called + * + * @param node the name of the reporting node + * @param port the port ID of the busy port + * @param remote_node the name of the remote node. + * @param bytes the number of bytes written + */ + probe dist__output(char *node, char *port, char *remote_node, int bytes); + + /** + * Fired when network distribution's driver's "outputv" callback is called + * + * @param node the name of the reporting node + * @param port the port ID of the busy port + * @param remote_node the name of the remote node. + * @param bytes the number of bytes written + */ + probe dist__outputv(char *node, char *port, char *remote_node, int bytes); + + /** + * Fired when network distribution port is no longer busy (i.e. blocked). + * + * NOTE: This probe may fire multiple times after the same single + * dist-port_busy probe firing. + * + * @param node the name of the reporting node + * @param port the port ID of the busy port + * @param remote_node the name of the remote node. + */ + probe dist__port_not_busy(char *node, char *port, char *remote_node); + + /* ports */ + + /** + * Fired when new port is opened. + * + * @param process the PID (string form) + * @param port_name the string used when the port was opened + * @param port the Port (string form) of the new port + */ + probe port__open(char *process, char *port_name, char *port); + + /** + * Fired when port_command is issued. + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + * @param command_type type of the issued command, one of: "close", "command" or "connect" + */ + probe port__command(char *process, char *port, char *port_name, char *command_type); + + /** + * Fired when port_control is issued. + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + * @param command_no command number that has been issued to the port + */ + probe port__control(char *process, char *port, char *port_name, int command_no); + + /** + * Fired when port is closed via port_close/1 (reason = 'normal') + * or is sent an exit signal. + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + * @param reason Erlang term representing the exit signal, e.g. 'normal' + */ + probe port__exit(char *process, char *port, char *port_name, + char *new_process); + + /** + * Fired when port_connect is issued. + * + * @param process the PID (string form) of the current port owner + * @param port the Port (string form) + * @param port_name the string used when the port was opened + * @param new_process the PID (string form) of the new port owner + */ + probe port__connect(char *process, char *port, char *port_name, + char *new_process); + + /** + * Fired when a port is busy (i.e. blocked) + * + * @param port the port ID of the busy port + */ + probe port__busy(char *port); + + /** + * Fired when a port is no longer busy (i.e. no longer blocked) + * + * @param port the port ID of the not busy port + */ + probe port__not_busy(char *port); + + /* drivers */ + + /** + * Fired when drivers's "init" callback is called. + * + * @param name the name of the driver + * @param major the major version number + * @param minor the minor version number + * @param flags the flags argument + */ + probe driver__init(char *name, int major, int minor, int flags); + + /** + * Fired when drivers's "start" callback is called. + * + * @param process the PID (string form) of the calling process + * @param name the name of the driver + * @param port the Port (string form) of the driver's port + */ + probe driver__start(char *process, char *name, char *port); + + /** + * Fired when drivers's "stop" callback is called. + * + * @param process the PID (string form) of the calling process + * @param name the name of the driver + * @param port the Port (string form) of the driver's port + */ + probe driver__stop(char *process, char *name, char *port); + + /** + * Fired when drivers's "finish" callback is called. + * + * @param name the name of the driver + */ + probe driver__finish(char *name); + + /** + * Fired when drivers's "flush" callback is called. + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + */ + probe driver__flush(char *process, char *port, char *port_name); + + /** + * Fired when driver's "output" callback is called + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + * @param bytes the number of bytes written + */ + probe driver__output(char *node, char *port, char *port_name, int bytes); + + /** + * Fired when driver's "outputv" callback is called + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + * @param bytes the number of bytes written + */ + probe driver__outputv(char *node, char *port, char *port_name, int bytes); + + /** + * Fired when driver's "control" callback is called + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + * @param command the command # + * @param bytes the number of bytes written + */ + probe driver__control(char *node, char *port, char *port_name, + int command, int bytes); + + /** + * Fired when driver's "call" callback is called + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + * @param command the command # + * @param bytes the number of bytes written + */ + probe driver__call(char *node, char *port, char *port_name, + int command, int bytes); + + /** + * Fired when driver's "event" callback is called + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + */ + probe driver__event(char *node, char *port, char *port_name); + + /** + * Fired when driver's "ready_input" callback is called + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + */ + probe driver__ready_input(char *node, char *port, char *port_name); + + /** + * Fired when driver's "read_output" callback is called + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + */ + probe driver__ready_output(char *node, char *port, char *port_name); + + /** + * Fired when driver's "timeout" callback is called + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + */ + probe driver__timeout(char *node, char *port, char *port_name); + + /** + * Fired when drivers's "ready_async" callback is called. + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + */ + probe driver__ready_async(char *process, char *port, char *port_name); + + /** + * Fired when driver's "process_exit" callback is called + * + * @param process the PID (string form) + * @param port the Port (string form) + * @param port_name the string used when the port was opened + */ + probe driver__process_exit(char *node, char *port, char *port_name); + + /** + * Fired when driver's "stop_select" callback is called + * + * @param name the name of the driver + */ + probe driver__stop_select(char *name); + + + /* Async driver pool */ + + /** + * Show the post-add length of the async driver thread pool member's queue. + * + * NOTE: The port name is not available: additional lock(s) must + * be acquired in order to get the port name safely in an SMP + * environment. The same is true for the aio__pool_get probe. + * + * @param port the Port (string form) + * @param new queue length + */ + probe aio_pool__add(char *, int); + + /** + * Show the post-get length of the async driver thread pool member's queue. + * + * @param port the Port (string form) + * @param new queue length + */ + probe aio_pool__get(char *, int); + + /* Probes for efile_drv.c */ + + /** + * Entry into the efile_drv.c file I/O driver + * + * For a list of command numbers used by this driver, see the section + * "Guide to probe arguments" in ../../../README.md. That section + * also contains explanation of the various integer and string + * arguments that may be present when any particular probe fires. + * + * NOTE: Not all Linux platforms (using SystemTap) can support + * arguments beyond arg9. + * + * + * TODO: Adding the port string, args[10], is a pain. Making that + * port string available to all the other efile_drv.c probes + * will be more pain. Is the pain worth it? If yes, then + * add them everywhere else and grit our teeth. If no, then + * rip it out. + * + * @param thread-id number of the scheduler Pthread arg0 + * @param tag number: {thread-id, tag} uniquely names a driver operation + * @param user-tag string arg2 + * @param command number arg3 + * @param string argument 1 arg4 + * @param string argument 2 arg5 + * @param integer argument 1 arg6 + * @param integer argument 2 arg7 + * @param integer argument 3 arg8 + * @param integer argument 4 arg9 + * @param port the port ID of the busy port args[10] + */ + probe efile_drv__entry(int, int, char *, int, char *, char *, + int64_t, int64_t, int64_t, int64_t, char *); + + /** + * Entry into the driver's internal work function. Computation here + * is performed by a async worker pool Pthread. + * + * @param thread-id number + * @param tag number + * @param command number + */ + probe efile_drv__int_entry(int, int, int); + + /** + * Return from the driver's internal work function. + * + * @param thread-id number + * @param tag number + * @param command number + */ + probe efile_drv__int_return(int, int, int); + + /** + * Return from the efile_drv.c file I/O driver + * + * @param thread-id number arg0 + * @param tag number arg1 + * @param user-tag string arg2 + * @param command number arg3 + * @param Success? 1 is success, 0 is failure arg4 + * @param If failure, the errno of the error. arg5 + */ + probe efile_drv__return(int, int, char *, int, int, int); + +/* + * NOTE: + * For formatting int64_t arguments within a D script, see: + * + * http://mail.opensolaris.org/pipermail/dtrace-discuss/2006-November/002830.html + * Summary: + * "1) you don't need the 'l' printf() modifiers with DTrace ever" + */ + +/* + * NOTE: For file_drv_return + SMP + R14B03 (and perhaps other + * releases), the sched-thread-id will be the same as the + * work-thread-id: erl_async.c's async_main() function + * will call the asynchronous invoke function and then + * immediately call the drivers ready_async function while + * inside the same I/O worker pool thread. + * For R14B03's source, see erl_async.c lines 302-317. + */ +}; + +#pragma D attributes Evolving/Evolving/Common provider erlang provider +#pragma D attributes Private/Private/Common provider erlang module +#pragma D attributes Private/Private/Common provider erlang function +#pragma D attributes Evolving/Evolving/Common provider erlang name +#pragma D attributes Evolving/Evolving/Common provider erlang args diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index fb1514a147..81f79b8f85 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -43,6 +43,7 @@ #include "erl_version.h" #include "error.h" #include "erl_async.h" +#include "dtrace-wrapper.h" extern ErlDrvEntry fd_driver_entry; extern ErlDrvEntry vanilla_driver_entry; @@ -180,6 +181,19 @@ typedef struct line_buf_context { #define LINEBUF_INITIAL 100 +#define DTRACE_FORMAT_COMMON_PID_AND_PORT(PID, PORT) \ + DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); \ + \ + dtrace_pid_str((PID), process_str); \ + dtrace_port_str((PORT), port_str); +#define DTRACE_FORMAT_COMMON_PROC_AND_PORT(PID, PORT) \ + DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); \ + \ + dtrace_proc_str((PID), process_str); \ + dtrace_port_str((PORT), port_str); + /* The 'number' field in a port now has two parts: the lowest bits contain the index in the port table, and the higher bits are a counter @@ -639,6 +653,10 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */ trace_sched_ports_where(port, am_in, am_start); } port->caller = pid; + if (DTRACE_ENABLED(driver_start)) { + DTRACE_FORMAT_COMMON_PID_AND_PORT(pid, port) + DTRACE3(driver_start, process_str, driver->name, port_str); + } fpe_was_unmasked = erts_block_fpe(); drv_data = (*driver->start)((ErlDrvPort)(port_ix), name, opts); @@ -1170,6 +1188,10 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list) ev.size = size; /* total size */ ev.iov = ivp; ev.binv = bvp; + if (DTRACE_ENABLED(driver_outputv)) { + DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p) + DTRACE4(driver_outputv, process_str, port_str, p->name, size); + } fpe_was_unmasked = erts_block_fpe(); (*drv->outputv)((ErlDrvData)p->drv_data, &ev); erts_unblock_fpe(fpe_was_unmasked); @@ -1189,8 +1211,17 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list) buf = erts_alloc(ERTS_ALC_T_TMP, size+1); r = io_list_to_buf(list, buf, size); + if(DTRACE_ENABLED(port_command)) { + DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p) + DTRACE4(port_command, process_str, port_str, p->name, "command"); + } + if (r >= 0) { size -= r; + if (DTRACE_ENABLED(driver_output)) { + DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p) + DTRACE4(driver_output, process_str, port_str, p->name, size); + } fpe_was_unmasked = erts_block_fpe(); (*drv->output)((ErlDrvData)p->drv_data, buf, size); erts_unblock_fpe(fpe_was_unmasked); @@ -1214,6 +1245,10 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list) */ buf = erts_alloc(ERTS_ALC_T_TMP, size+1); r = io_list_to_buf(list, buf, size); + if (DTRACE_ENABLED(driver_output)) { + DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p) + DTRACE4(driver_output, process_str, port_str, p->name, size); + } fpe_was_unmasked = erts_block_fpe(); (*drv->output)((ErlDrvData)p->drv_data, buf, size); erts_unblock_fpe(fpe_was_unmasked); @@ -1810,6 +1845,10 @@ static void flush_port(Port *p) ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p)); if (p->drv_ptr->flush != NULL) { + if (DTRACE_ENABLED(driver_flush)) { + DTRACE_FORMAT_COMMON_PID_AND_PORT(p->connected, p) + DTRACE3(driver_flush, process_str, port_str, p->name); + } if (IS_TRACED_FL(p, F_TRACE_SCHED_PORTS)) { trace_sched_ports_where(p, am_in, am_flush); } @@ -1865,6 +1904,10 @@ terminate_port(Port *prt) drv = prt->drv_ptr; if ((drv != NULL) && (drv->stop != NULL)) { int fpe_was_unmasked = erts_block_fpe(); + if (DTRACE_ENABLED(driver_stop)) { + DTRACE_FORMAT_COMMON_PID_AND_PORT(prt->connected, prt) + DTRACE3(driver_stop, process_str, drv->name, port_str); + } (*drv->stop)((ErlDrvData)prt->drv_data); erts_unblock_fpe(fpe_was_unmasked); #ifdef ERTS_SMP @@ -2026,6 +2069,17 @@ erts_do_exit_port(Port *p, Eterm from, Eterm reason) rreason = (reason == am_kill) ? am_killed : reason; + if (DTRACE_ENABLED(port_exit)) { + DTRACE_CHARBUF(from_str, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); + DTRACE_CHARBUF(rreason_str, 64); + + erts_snprintf(from_str, sizeof(from_str), "%T", from); + dtrace_port_str(p, port_str); + erts_snprintf(rreason_str, sizeof(rreason_str), "%T", rreason); + DTRACE4(port_exit, from_str, port_str, p->name, rreason_str); + } + if ((p->status & (ERTS_PORT_SFLGS_DEAD | ERTS_PORT_SFLG_EXITING | ERTS_PORT_SFLG_IMMORTAL)) @@ -2126,6 +2180,11 @@ void erts_port_command(Process *proc, if (tp[2] == am_close) { erts_port_status_bor_set(port, ERTS_PORT_SFLG_SEND_CLOSED); erts_do_exit_port(port, pid, am_normal); + + if(DTRACE_ENABLED(port_command)) { + DTRACE_FORMAT_COMMON_PROC_AND_PORT(proc, port) + DTRACE4(port_command, process_str, port_str, port->name, "close"); + } goto done; } else if (is_tuple_arity(tp[2], 2)) { tp = tuple_val(tp[2]); @@ -2133,6 +2192,10 @@ void erts_port_command(Process *proc, if (erts_write_to_port(caller_id, port, tp[2]) == 0) goto done; } else if ((tp[1] == am_connect) && is_internal_pid(tp[2])) { + if(DTRACE_ENABLED(port_command)) { + DTRACE_FORMAT_COMMON_PROC_AND_PORT(proc, port) + DTRACE4(port_command, process_str, port_str, port->name, "connect"); + } port->connected = tp[2]; deliver_result(port->id, pid, am_connected); goto done; @@ -2235,6 +2298,13 @@ erts_port_control(Process* p, Port* prt, Uint command, Eterm iolist) erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN); ERTS_SMP_CHK_NO_PROC_LOCKS; + if (DTRACE_ENABLED(port_control) || DTRACE_ENABLED(driver_control)) { + DTRACE_FORMAT_COMMON_PROC_AND_PORT(p, prt); + DTRACE4(port_control, process_str, port_str, prt->name, command); + DTRACE5(driver_control, process_str, port_str, prt->name, + command, to_len); + } + /* * Call the port's control routine. */ @@ -2375,6 +2445,8 @@ print_port_info(int to, void *arg, int i) void set_busy_port(ErlDrvPort port_num, int on) { + DTRACE_CHARBUF(port_str, 16); + ERTS_SMP_CHK_NO_PROC_LOCKS; ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(&erts_port[port_num])); @@ -2382,12 +2454,22 @@ set_busy_port(ErlDrvPort port_num, int on) if (on) { erts_port_status_bor_set(&erts_port[port_num], ERTS_PORT_SFLG_PORT_BUSY); + if (DTRACE_ENABLED(port_busy)) { + erts_snprintf(port_str, sizeof(port_str), + "%T", erts_port[port_num].id); + DTRACE1(port_busy, port_str); + } } else { ErtsProcList* plp = erts_port[port_num].suspended; erts_port_status_band_set(&erts_port[port_num], ~ERTS_PORT_SFLG_PORT_BUSY); erts_port[port_num].suspended = NULL; + if (DTRACE_ENABLED(port_not_busy)) { + erts_snprintf(port_str, sizeof(port_str), + "%T", erts_port[port_num].id); + DTRACE1(port_not_busy, port_str); + } if (erts_port[port_num].dist_entry) { /* * Processes suspended on distribution ports are @@ -2405,6 +2487,26 @@ set_busy_port(ErlDrvPort port_num, int on) */ if (plp) { + /* + * Hrm, for blocked dist ports, plp always seems to be NULL. + * That's not so fun. + * Well, another way to get the same info is using a D + * script to correlate an earlier process-port_blocked+pid + * event with a later process-scheduled event. That's + * subject to the multi-CPU races with how events are + * handled, but hey, that way works most of the time. + */ + if (DTRACE_ENABLED(process_port_unblocked)) { + DTRACE_CHARBUF(pid_str, 16); + ErtsProcList* plp2 = plp; + + erts_snprintf(port_str, sizeof(port_str), + "%T", erts_port[port_num]); + while (plp2 != NULL) { + erts_snprintf(pid_str, sizeof(pid_str), "%T", plp2->pid); + DTRACE2(process_port_unblocked, pid_str, port_str); + } + } /* First proc should be resumed last */ if (plp->next) { erts_resume_processes(plp->next); @@ -2451,6 +2553,12 @@ void erts_raw_port_command(Port* p, byte* buf, Uint len) p->drv_ptr->name ? p->drv_ptr->name : "unknown"); p->caller = NIL; + if (DTRACE_ENABLED(driver_output)) { + DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); + + dtrace_port_str(p, port_str); + DTRACE4(driver_output, "-raw-", port_str, p->name, len); + } fpe_was_unmasked = erts_block_fpe(); (*p->drv_ptr->output)((ErlDrvData)p->drv_data, (char*) buf, (int) len); erts_unblock_fpe(fpe_was_unmasked); @@ -2466,6 +2574,10 @@ int async_ready(Port *p, void* data) ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p)); ASSERT(!(p->status & ERTS_PORT_SFLGS_DEAD)); if (p->drv_ptr->ready_async != NULL) { + if (DTRACE_ENABLED(driver_ready_async)) { + DTRACE_FORMAT_COMMON_PID_AND_PORT(p->connected, p) + DTRACE3(driver_ready_async, process_str, port_str, p->name); + } (*p->drv_ptr->ready_async)((ErlDrvData)p->drv_data, data); need_free = 0; #ifdef ERTS_SMP @@ -4441,6 +4553,10 @@ void erts_fire_port_monitor(Port *prt, Eterm ref) ASSERT(callback != NULL); ref_to_driver_monitor(ref,&drv_monitor); DRV_MONITOR_UNLOCK_PDL(prt); + if (DTRACE_ENABLED(driver_process_exit)) { + DTRACE_FORMAT_COMMON_PID_AND_PORT(prt->connected, prt) + DTRACE3(driver_process_exit, process_str, port_str, prt->name); + } fpe_was_unmasked = erts_block_fpe(); (*callback)((ErlDrvData) (prt->drv_data), &drv_monitor); erts_unblock_fpe(fpe_was_unmasked); @@ -4884,6 +5000,8 @@ init_driver(erts_driver_t *drv, ErlDrvEntry *de, DE_Handle *handle) else { int res; int fpe_was_unmasked = erts_block_fpe(); + DTRACE4(driver_init, drv->name, drv->version.major, drv->version.minor, + drv->flags); res = (*de->init)(); erts_unblock_fpe(fpe_was_unmasked); return res; diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c index 23a4bf1b04..cb7ef95f00 100644 --- a/erts/emulator/sys/common/erl_check_io.c +++ b/erts/emulator/sys/common/erl_check_io.c @@ -36,6 +36,7 @@ #include "global.h" #include "erl_check_io.h" #include "erl_thr_progress.h" +#include "dtrace-wrapper.h" #ifdef ERTS_SYS_CONTINOUS_FD_NUMBERS # define ERTS_DRV_EV_STATE_EXTRA_SIZE 128 @@ -314,6 +315,7 @@ forget_removed(struct pollset_info* psi) erts_smp_mtx_unlock(mtx); if (drv_ptr) { int was_unmasked = erts_block_fpe(); + DTRACE1(driver_stop_select, drv_ptr->name); (*drv_ptr->stop_select) ((ErlDrvEvent) fd, NULL); erts_unblock_fpe(was_unmasked); if (drv_ptr->handle) { @@ -496,6 +498,7 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix, ErtsDrvEventState *state; int wake_poller; int ret; + DTRACE_CHARBUF(name, 64); ERTS_SMP_LC_ASSERT(erts_drvport2port(ix) && erts_lc_is_port_locked(erts_drvport2port(ix))); @@ -525,6 +528,8 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix, if (IS_FD_UNKNOWN(state)) { /* fast track to stop_select callback */ stop_select_fn = erts_drvport2port(ix)->drv_ptr->stop_select; + strncpy(name, erts_drvport2port(ix)->drv_ptr->name, sizeof(name)-1); + name[sizeof(name)-1] = '\0'; ret = 0; goto done_unknown; } @@ -661,6 +666,8 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix, /* Safe to close fd now as it is not in pollset or there was no need to eject fd (kernel poll) */ stop_select_fn = drv_ptr->stop_select; + strncpy(name, erts_drvport2port(ix)->drv_ptr->name, sizeof(name)-1); + name[sizeof(name)-1] = '\0'; } else { /* Not safe to close fd, postpone stop_select callback. */ @@ -686,6 +693,7 @@ done_unknown: erts_smp_mtx_unlock(fd_mtx(fd)); if (stop_select_fn) { int was_unmasked = erts_block_fpe(); + DTRACE1(driver_stop_select, name); (*stop_select_fn)(e, NULL); erts_unblock_fpe(was_unmasked); } -- cgit v1.2.3 From ad6387b0242caa2b3c64d62a133752e10546211b Mon Sep 17 00:00:00 2001 From: Scott Lystig Fritchie Date: Thu, 17 Nov 2011 00:47:23 -0600 Subject: Add DTrace support for OS X, Solaris, and Linux (via SystemTap), 4/4 Add probes to (mostly) the efile_drv.c driver and other file I/O-related source files. --- erts/emulator/drivers/common/efile_drv.c | 569 +++++++++++++++++++++++++------ 1 file changed, 472 insertions(+), 97 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index a251b064da..b72f95792c 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -112,6 +112,8 @@ #include "erl_threads.h" #include "zlib.h" #include "gzio.h" +#define DTRACE_DRIVER_SKIP_FUNC_DECLARATIONS +#include "dtrace-wrapper.h" #include #include @@ -119,6 +121,40 @@ void erl_exit(int n, char *fmt, ...); static ErlDrvSysInfo sys_info; +/* For explanation of this var, see comment for same var in erl_async.c */ +static unsigned gcc_optimizer_hack = 0; + +#ifdef HAVE_DTRACE + +#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) \ + struct t_data *d = (struct t_data *) data ; \ + DTRACE_INVOKE_SETUP(op) +#define DTRACE_INVOKE_RETURN(op) \ + do { DTRACE3(efile_drv_int_return, d->sched_i1, d->sched_i2, \ + op); } while (0) ; gcc_optimizer_hack++ ; + +/* Assign human-friendlier id numbers to scheduler & I/O worker threads */ +int dt_driver_idnum = 0; +int dt_driver_io_worker_base = 5000; +erts_mtx_t dt_driver_mutex; +pthread_key_t dt_driver_key; + +typedef struct { + int thread_num; + Uint64 tag; +} dt_private; + +dt_private *get_dt_private(int); +#else /* HAVE_DTRACE */ +typedef struct { +} dt_private; + +#define DTRACE_INVOKE_SETUP(op) do {} while (0) +#define DTRACE_INVOKE_SETUP_BY_NAME(op) do {} while (0) +#define DTRACE_INVOKE_RETURN(op) do {} while (0) +#endif /* HAVE_DTRACE */ /* #define TRACE 1 */ #ifdef TRACE @@ -289,6 +325,10 @@ typedef struct { ErlDrvPDL q_mtx; /* Mutex for the driver queue, known by the emulator. Also used for mutual exclusion when accessing field(s) below. */ size_t write_buffered; +#ifdef HAVE_DTRACE + int idnum; /* Unique ID # for this driver thread/desc */ + char port_str[DTRACE_TERM_BUF_SIZE]; +#endif } file_descriptor; @@ -386,6 +426,13 @@ struct t_data void (*free)(void *); int again; int reply; +#ifdef HAVE_DTRACE + int sched_i1; + Uint64 sched_i2; + char sched_utag[128+1]; +#else + char sched_utag[1]; +#endif int result_ok; Efile_error errInfo; int flags; @@ -458,8 +505,6 @@ struct t_data char b[1]; }; - - #define EF_ALLOC(S) driver_alloc((S)) #define EF_REALLOC(P, S) driver_realloc((P), (S)) #define EF_SAFE_ALLOC(S) ef_safe_alloc((S)) @@ -488,7 +533,7 @@ static void *ef_safe_realloc(void *op, Uint s) * ErlIOVec manipulation functions. */ -/* char EV_CHAR(ErlIOVec *ev, int p, int q) */ +/* char EV_CHAR_P(ErlIOVec *ev, int p, int q) */ #define EV_CHAR_P(ev, p, q) \ (((char *)(ev)->iov[(q)].iov_base) + (p)) @@ -683,6 +728,11 @@ file_init(void) : 0); driver_system_info(&sys_info, sizeof(ErlDrvSysInfo)); +#ifdef HAVE_DTRACE + erts_mtx_init(&dt_driver_mutex, "efile_drv dtrace mutex"); + pthread_key_create(&dt_driver_key, NULL); +#endif /* HAVE_DTRACE */ + return 0; } @@ -722,6 +772,10 @@ file_start(ErlDrvPort port, char* command) desc->write_error = 0; MUTEX_INIT(desc->q_mtx, port); /* Refc is one, referenced by emulator now */ desc->write_buffered = 0; +#ifdef HAVE_DTRACE + dtrace_drvport_str(port, desc->port_str); + get_dt_private(0); /* throw away return value */ +#endif /* HAVE_DTRACE */ return (ErlDrvData) desc; } @@ -741,8 +795,10 @@ static void do_close(int flags, SWord fd) { static void invoke_close(void *data) { struct t_data *d = (struct t_data *) data; + DTRACE_INVOKE_SETUP(FILE_CLOSE); d->again = 0; do_close(d->flags, d->fd); + DTRACE_INVOKE_RETURN(FILE_CLOSE); } /********************************************************************* @@ -972,49 +1028,63 @@ static void invoke_name(void *data, int (*f)(Efile_error *, char *)) static void invoke_mkdir(void *data) { + DTRACE_INVOKE_SETUP_BY_NAME(FILE_MKDIR); invoke_name(data, efile_mkdir); + DTRACE_INVOKE_RETURN(FILE_MKDIR); } static void invoke_rmdir(void *data) { + DTRACE_INVOKE_SETUP_BY_NAME(FILE_RMDIR); invoke_name(data, efile_rmdir); + DTRACE_INVOKE_RETURN(FILE_RMDIR); } static void invoke_delete_file(void *data) { + DTRACE_INVOKE_SETUP_BY_NAME(FILE_DELETE); invoke_name(data, efile_delete_file); + DTRACE_INVOKE_RETURN(FILE_DELETE); } static void invoke_chdir(void *data) { + DTRACE_INVOKE_SETUP_BY_NAME(FILE_CHDIR); invoke_name(data, efile_chdir); + DTRACE_INVOKE_RETURN(FILE_CHDIR); } static void invoke_fdatasync(void *data) { struct t_data *d = (struct t_data *) data; int fd = (int) d->fd; + DTRACE_INVOKE_SETUP(FILE_FDATASYNC); d->again = 0; d->result_ok = efile_fdatasync(&d->errInfo, fd); + DTRACE_INVOKE_RETURN(FILE_FDATASYNC); } static void invoke_fsync(void *data) { struct t_data *d = (struct t_data *) data; int fd = (int) d->fd; + DTRACE_INVOKE_SETUP(FILE_FSYNC); d->again = 0; d->result_ok = efile_fsync(&d->errInfo, fd); + DTRACE_INVOKE_RETURN(FILE_FSYNC); } static void invoke_truncate(void *data) { struct t_data *d = (struct t_data *) data; int fd = (int) d->fd; + DTRACE_INVOKE_SETUP(FILE_TRUNCATE); d->again = 0; d->result_ok = efile_truncate_file(&d->errInfo, &fd, d->flags); + DTRACE_INVOKE_RETURN(FILE_TRUNCATE); } static void invoke_read(void *data) @@ -1022,6 +1092,7 @@ static void invoke_read(void *data) struct t_data *d = (struct t_data *) data; int status, segment; size_t size, read_size; + DTRACE_INVOKE_SETUP(FILE_READ); segment = d->again && d->c.read.bin_size >= 2*FILE_SEGMENT_READ; if (segment) { @@ -1056,6 +1127,7 @@ static void invoke_read(void *data) } else { d->again = 0; } + DTRACE_INVOKE_RETURN(FILE_READ); } static void free_read(void *data) @@ -1072,6 +1144,7 @@ static void invoke_read_line(void *data) int status; size_t read_size; int local_loop = (d->again == 0); + DTRACE_INVOKE_SETUP(FILE_READ_LINE); do { size_t size = (d->c.read_line.binp)->orig_size - @@ -1163,6 +1236,7 @@ static void invoke_read_line(void *data) break; } } while (local_loop); + DTRACE_INVOKE_RETURN(FILE_READ_LINE); } static void free_read_line(void *data) @@ -1178,6 +1252,7 @@ static void invoke_read_file(void *data) struct t_data *d = (struct t_data *) data; size_t read_size; int chop; + DTRACE_INVOKE_SETUP(FILE_READ_FILE); if (! d->c.read_file.binp) { /* First invocation only */ int fd; @@ -1214,12 +1289,14 @@ static void invoke_read_file(void *data) &read_size); if (d->result_ok) { d->c.read_file.offset += read_size; - if (chop) return; /* again */ + if (chop) goto chop_done; /* again */ } close: efile_closefile((int) d->fd); done: d->again = 0; + chop_done: + DTRACE_INVOKE_RETURN(FILE_READ_FILE); } static void free_read_file(void *data) @@ -1239,6 +1316,7 @@ static void invoke_preadv(void *data) ErlIOVec *ev = &c->eiov; size_t bytes_read_so_far = 0; unsigned char *p = (unsigned char *)ev->iov[0].iov_base + 4+4+8*c->cnt; + DTRACE_INVOKE_SETUP(FILE_PREADV); while (c->cnt < c->n) { size_t read_size = ev->iov[1 + c->cnt].iov_len - c->size; @@ -1260,7 +1338,7 @@ static void invoke_preadv(void *data) bytes_read_so_far += bytes_read; if (chop && bytes_read == read_size) { c->size += bytes_read; - return; + goto done; } ASSERT(bytes_read <= read_size); ev->iov[1 + c->cnt].iov_len = bytes_read + c->size; @@ -1271,7 +1349,7 @@ static void invoke_preadv(void *data) if (d->again && bytes_read_so_far >= FILE_SEGMENT_READ && c->cnt < c->n) { - return; + goto done; } } else { /* In case of a read error, ev->size will not be correct, @@ -1282,6 +1360,8 @@ static void invoke_preadv(void *data) } } d->again = 0; + done: + DTRACE_INVOKE_RETURN(FILE_PREADV); } static void free_preadv(void *data) { @@ -1303,6 +1383,7 @@ static void invoke_ipread(void *data) size_t bytes_read = 0; char buf[2*sizeof(Uint32)]; Uint32 offset, size; + DTRACE_INVOKE_SETUP(FILE_IPREAD); /* Read indirection header */ if (! efile_pread(&d->errInfo, (int) d->fd, c->offsets[0], @@ -1341,14 +1422,17 @@ static void invoke_ipread(void *data) /* Read data block */ d->invoke = invoke_preadv; invoke_preadv(data); + DTRACE_INVOKE_RETURN(FILE_IPREAD); return; error: d->result_ok = 0; d->again = 0; + DTRACE_INVOKE_RETURN(FILE_IPREAD); return; done: d->result_ok = !0; d->again = 0; + DTRACE_INVOKE_RETURN(FILE_IPREAD); } /* invoke_writev and invoke_pwritev are the only thread functions that @@ -1371,6 +1455,7 @@ static void invoke_writev(void *data) { size_t size; size_t p; int segment; + DTRACE_INVOKE_SETUP(FILE_WRITE); segment = d->again && d->c.writev.size >= 2*FILE_SEGMENT_WRITE; if (segment) { @@ -1444,6 +1529,7 @@ static void invoke_writev(void *data) { TRACE_F(("w%lu", (unsigned long)size)); } + DTRACE_INVOKE_RETURN(FILE_WRITE); } static void free_writev(void *data) { @@ -1457,34 +1543,40 @@ static void free_writev(void *data) { static void invoke_pwd(void *data) { struct t_data *d = (struct t_data *) data; + DTRACE_INVOKE_SETUP(FILE_PWD); d->again = 0; d->result_ok = efile_getdcwd(&d->errInfo,d->drive, d->b+1, RESBUFSIZE-1); + DTRACE_INVOKE_RETURN(FILE_PWD); } static void invoke_readlink(void *data) { struct t_data *d = (struct t_data *) data; char resbuf[RESBUFSIZE]; /* Result buffer. */ + DTRACE_INVOKE_SETUP(FILE_READLINK); d->again = 0; d->result_ok = efile_readlink(&d->errInfo, d->b, resbuf+1, RESBUFSIZE-1); if (d->result_ok != 0) FILENAME_COPY((char *) d->b + 1, resbuf+1); + DTRACE_INVOKE_RETURN(FILE_READLINK); } static void invoke_altname(void *data) { struct t_data *d = (struct t_data *) data; char resbuf[RESBUFSIZE]; /* Result buffer. */ + DTRACE_INVOKE_SETUP(FILE_ALTNAME); d->again = 0; d->result_ok = efile_altname(&d->errInfo, d->b, resbuf+1, RESBUFSIZE-1); if (d->result_ok != 0) FILENAME_COPY((char *) d->b + 1, resbuf+1); + DTRACE_INVOKE_RETURN(FILE_ALTNAME); } static void invoke_pwritev(void *data) { @@ -1497,6 +1589,7 @@ static void invoke_pwritev(void *data) { size_t p; int segment; size_t size, write_size; + DTRACE_INVOKE_SETUP(FILE_PWRITEV); segment = d->again && c->size >= 2*FILE_SEGMENT_WRITE; if (segment) { @@ -1576,6 +1669,7 @@ static void invoke_pwritev(void *data) { } done: EF_FREE(iov); /* Free our copy of the vector, nothing to restore */ + DTRACE_INVOKE_RETURN(FILE_PWRITEV); } static void free_pwritev(void *data) { @@ -1591,9 +1685,14 @@ static void invoke_flstat(void *data) { struct t_data *d = (struct t_data *) data; + DTRACE3(efile_drv_int_entry, d->sched_i1, d->sched_i2, + d->command == FILE_LSTAT ? FILE_LSTAT : FILE_FSTAT); d->again = 0; d->result_ok = efile_fileinfo(&d->errInfo, &d->info, d->b, d->command == FILE_LSTAT); + DTRACE3(efile_drv_int_entry, d->sched_i1, d->sched_i2, + d->command == FILE_LSTAT ? FILE_LSTAT : FILE_FSTAT); + gcc_optimizer_hack++; } static void invoke_link(void *data) @@ -1601,10 +1700,12 @@ static void invoke_link(void *data) struct t_data *d = (struct t_data *) data; char *name = d->b; char *new_name; + DTRACE_INVOKE_SETUP(FILE_LINK); d->again = 0; new_name = name+FILENAME_BYTELEN(name)+FILENAME_CHARSIZE; d->result_ok = efile_link(&d->errInfo, name, new_name); + DTRACE_INVOKE_RETURN(FILE_LINK); } static void invoke_symlink(void *data) @@ -1612,10 +1713,12 @@ static void invoke_symlink(void *data) struct t_data *d = (struct t_data *) data; char *name = d->b; char *new_name; + DTRACE_INVOKE_SETUP(FILE_SYMLINK); d->again = 0; new_name = name+FILENAME_BYTELEN(name)+FILENAME_CHARSIZE; d->result_ok = efile_symlink(&d->errInfo, name, new_name); + DTRACE_INVOKE_RETURN(FILE_SYMLINK); } static void invoke_rename(void *data) @@ -1623,24 +1726,29 @@ static void invoke_rename(void *data) struct t_data *d = (struct t_data *) data; char *name = d->b; char *new_name; + DTRACE_INVOKE_SETUP(FILE_RENAME); d->again = 0; new_name = name+FILENAME_BYTELEN(name)+FILENAME_CHARSIZE; d->result_ok = efile_rename(&d->errInfo, name, new_name); + DTRACE_INVOKE_RETURN(FILE_RENAME); } static void invoke_write_info(void *data) { struct t_data *d = (struct t_data *) data; + DTRACE_INVOKE_SETUP(FILE_WRITE_INFO); d->again = 0; d->result_ok = efile_write_info(&d->errInfo, &d->info, d->b); + DTRACE_INVOKE_RETURN(FILE_WRITE_INFO); } static void invoke_lseek(void *data) { struct t_data *d = (struct t_data *) data; int status; + DTRACE_INVOKE_SETUP(FILE_LSEEK); d->again = 0; if (d->flags & EFILE_COMPRESSED) { @@ -1665,6 +1773,7 @@ static void invoke_lseek(void *data) &d->c.lseek.location); } d->result_ok = status; + DTRACE_INVOKE_RETURN(FILE_LSEEK); } static void invoke_readdir(void *data) @@ -1675,6 +1784,7 @@ static void invoke_readdir(void *data) size_t n = 0, total = 0; struct t_readdir_buf *b = NULL; int res = 0; + DTRACE_INVOKE_SETUP(FILE_READDIR); d->again = 0; d->errInfo.posix_errno = 0; @@ -1710,13 +1820,14 @@ static void invoke_readdir(void *data) } while(res); d->result_ok = (d->errInfo.posix_errno == 0); + DTRACE_INVOKE_RETURN(FILE_READDIR); } static void invoke_open(void *data) { struct t_data *d = (struct t_data *) data; - int status = 1; /* Status of open call. */ + DTRACE_INVOKE_SETUP(FILE_OPEN); d->again = 0; if ((d->flags & EFILE_COMPRESSED) == 0) { @@ -1749,6 +1860,7 @@ static void invoke_open(void *data) } d->result_ok = status; + DTRACE_INVOKE_RETURN(FILE_OPEN); } static void invoke_fadvise(void *data) @@ -1758,9 +1870,11 @@ static void invoke_fadvise(void *data) off_t offset = (off_t) d->c.fadvise.offset; off_t length = (off_t) d->c.fadvise.length; int advise = (int) d->c.fadvise.advise; + DTRACE_INVOKE_SETUP(FILE_FADVISE); d->again = 0; d->result_ok = efile_fadvise(&d->errInfo, fd, offset, length, advise); + DTRACE_INVOKE_RETURN(FILE_FADVISE); } #ifdef HAVE_SENDFILE @@ -1841,6 +1955,7 @@ static void free_readdir(void *data) { struct t_data *d = (struct t_data *) data; struct t_readdir_buf *b1 = d->c.read_dir.first_buf; + while (b1) { struct t_readdir_buf *b2 = b1; b1 = b1->next; @@ -1909,12 +2024,13 @@ static void cq_execute(file_descriptor *desc) { DRIVER_ASYNC(d->level, desc, d->invoke, void_ptr=d, d->free); } -static int async_write(file_descriptor *desc, int *errp, - int reply, Uint32 reply_size) { +static struct t_data *async_write(file_descriptor *desc, int *errp, + int reply, Uint32 reply_size, + Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3) { struct t_data *d; if (! (d = EF_ALLOC(sizeof(struct t_data) - 1))) { if (errp) *errp = ENOMEM; - return -1; + return NULL; } TRACE_F(("w%lu", (unsigned long)desc->write_buffered)); d->command = FILE_WRITE; @@ -1923,6 +2039,11 @@ static int async_write(file_descriptor *desc, int *errp, d->c.writev.port = desc->port; d->c.writev.q_mtx = desc->q_mtx; d->c.writev.size = desc->write_buffered; + if (dt_i1 != NULL) { + *dt_i1 = d->fd; + *dt_i2 = d->flags; + *dt_i3 = d->c.writev.size; + } d->reply = reply; d->c.writev.free_size = 0; d->c.writev.reply_size = reply_size; @@ -1931,18 +2052,41 @@ static int async_write(file_descriptor *desc, int *errp, d->level = 1; cq_enq(desc, d); desc->write_buffered = 0; - return 0; + return d; } -static int flush_write(file_descriptor *desc, int *errp) { - int result; +static int flush_write(file_descriptor *desc, int *errp, + dt_private *dt_priv, char *dt_utag) { + int result = 0; + Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; + struct t_data *d = NULL; + MUTEX_LOCK(desc->q_mtx); if (desc->write_buffered > 0) { - result = async_write(desc, errp, 0, 0); - } else { - result = 0; + if ((d = async_write(desc, errp, 0, 0, + &dt_i1, &dt_i2, &dt_i3)) == NULL) { + result = -1; + } } MUTEX_UNLOCK(desc->q_mtx); +#ifdef HAVE_DTRACE + if (d != NULL) { + d->sched_i1 = dt_priv->thread_num; + d->sched_i2 = dt_priv->tag; + d->sched_utag[0] = '\0'; + if (dt_utag != NULL) { + if (dt_utag[0] == '\0') { + dt_utag = NULL; + } else { + strncpy(d->sched_utag, dt_utag, sizeof(d->sched_utag) - 1); + d->sched_utag[sizeof(d->sched_utag) - 1] = '\0'; + } + } + DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++, + dt_utag, FILE_WRITE, + NULL, NULL, dt_i1, dt_i2, dt_i3, 0, desc->port_str); + } +#endif /* HAVE_DTRACE */ return result; } @@ -1955,9 +2099,10 @@ static int check_write_error(file_descriptor *desc, int *errp) { return 0; } -static int flush_write_check_error(file_descriptor *desc, int *errp) { +static int flush_write_check_error(file_descriptor *desc, int *errp, + dt_private *dt_priv, char *dt_utag) { int r; - if ( (r = flush_write(desc, errp)) != 0) { + if ( (r = flush_write(desc, errp, dt_priv, dt_utag)) != 0) { check_write_error(desc, NULL); return r; } else { @@ -1965,12 +2110,13 @@ static int flush_write_check_error(file_descriptor *desc, int *errp) { } } -static int async_lseek(file_descriptor *desc, int *errp, int reply, - Sint64 offset, int origin) { +static struct t_data *async_lseek(file_descriptor *desc, int *errp, int reply, + Sint64 offset, int origin, + Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3) { struct t_data *d; if (! (d = EF_ALLOC(sizeof(struct t_data)))) { *errp = ENOMEM; - return -1; + return NULL; } d->flags = desc->flags; d->fd = desc->fd; @@ -1978,11 +2124,16 @@ static int async_lseek(file_descriptor *desc, int *errp, int reply, d->reply = reply; d->c.lseek.offset = offset; d->c.lseek.origin = origin; + if (dt_i1 != NULL) { + *dt_i1 = d->fd; + *dt_i2 = d->c.lseek.offset; + *dt_i3 = d->c.lseek.origin; + } d->invoke = invoke_lseek; d->free = free_data; d->level = 1; cq_enq(desc, d); - return 0; + return d; } static void flush_read(file_descriptor *desc) { @@ -1994,18 +2145,37 @@ static void flush_read(file_descriptor *desc) { } } -static int lseek_flush_read(file_descriptor *desc, int *errp) { +static int lseek_flush_read(file_descriptor *desc, int *errp, + dt_private *dt_priv, char *dt_utag) { int r = 0; size_t read_size = desc->read_size; + Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; + struct t_data *d; + + flush_read(desc); if (read_size != 0) { - flush_read(desc); - if ((r = async_lseek(desc, errp, 0, - -((ssize_t)read_size), EFILE_SEEK_CUR)) - < 0) { - return r; - } - } else { - flush_read(desc); + if ((d = async_lseek(desc, errp, 0, + -((ssize_t)read_size), EFILE_SEEK_CUR, + &dt_i1, &dt_i2, &dt_i3)) == NULL) { + r = -1; + } else { +#ifdef HAVE_DTRACE + d->sched_i1 = dt_priv->thread_num; + d->sched_i2 = dt_priv->tag; + d->sched_utag[0] = '\0'; + if (dt_utag != NULL) { + if (dt_utag[0] == '\0') { + dt_utag = NULL; + } else { + strncpy(d->sched_utag, dt_utag, sizeof(d->sched_utag) - 1); + d->sched_utag[sizeof(d->sched_utag) - 1] = '\0'; + } + } + DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++, + dt_utag, FILE_LSEEK, + NULL, NULL, dt_i1, dt_i2, dt_i3, 0, desc->port_str); +#endif /* HAVE_DTRACE */ + } } return r; } @@ -2022,11 +2192,23 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) struct t_data *d = (struct t_data *) data; char header[5]; /* result code + count */ char resbuf[RESBUFSIZE]; /* Result buffer. */ - +#ifdef HAVE_DTRACE + 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); + + 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'; + } +#endif /* HAVE_DTRACE */ TRACE_C('r'); if (try_again(desc, d)) { + /* DTRACE TODO: what kind of probe makes sense here? */ return; } @@ -2224,6 +2406,9 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) if (d->reply) { TRACE_C('K'); reply_ok(desc); +#ifdef HAVE_DTRACE + result_ok = 1; +#endif } free_data(data); break; @@ -2279,6 +2464,8 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) default: abort(); } + DTRACE6(efile_drv_return, sched_i1, sched_i2, sched_utag, + command, result_ok, posix_errno); if (desc->write_buffered != 0 && desc->timer_state == timer_idle) { desc->timer_state = timer_write; driver_set_timer(desc->port, desc->write_delay); @@ -2301,7 +2488,11 @@ 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; +#ifdef HAVE_DTRACE + dt_private *dt_priv = get_dt_private(0); +#endif /* HAVE_DTRACE */ TRACE_C('o'); @@ -2316,6 +2507,8 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); + dt_s1 = d->b; + dt_utag = name + strlen(d->b) + 1; d->command = command; d->invoke = invoke_mkdir; d->free = free_data; @@ -2327,6 +2520,8 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); + dt_s1 = d->b; + dt_utag = name + strlen(d->b) + 1; d->command = command; d->invoke = invoke_rmdir; d->free = free_data; @@ -2338,6 +2533,8 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); + dt_s1 = d->b; + dt_utag = name + strlen(d->b) + 1; d->command = command; d->invoke = invoke_delete_file; d->free = free_data; @@ -2354,7 +2551,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); + dt_s1 = d->b; FILENAME_COPY(d->b + namelen, new_name); + dt_s2 = d->b + namelen; + dt_utag = buf + namelen + strlen(dt_s2) + 1; d->flags = desc->flags; d->fd = fd; d->command = command; @@ -2368,6 +2568,8 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); + dt_s1 = d->b; + dt_utag = name + strlen(d->b) + 1; d->command = command; d->invoke = invoke_chdir; d->free = free_data; @@ -2379,6 +2581,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); d->drive = *(uchar*)buf; + dt_utag = buf + 1; d->command = command; d->invoke = invoke_pwd; d->free = free_data; @@ -2394,6 +2597,8 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); + dt_s1 = d->b; + dt_utag = name + strlen(d->b) + 1; d->dir_handle = NULL; d->command = command; d->invoke = invoke_readdir; @@ -2418,6 +2623,9 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) dir_handle = NULL; resbuf[0] = FILE_RESP_LFNAME; + dt_s1 = name; + dt_utag = name + strlen(dt_s1) + 1; + /* Fill the buffer with multiple directory listings before sending it to the * receiving process. READDIR_CHUNKS is minimum number of files sent to the * receiver. @@ -2451,6 +2659,11 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) reply_error(desc, &errInfo); return; } +#ifdef HAVE_DTRACE + DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++, + dt_utag, command, name, dt_s2, + dt_i1, dt_i2, dt_i3, dt_i4, desc->port_str); +#endif TRACE_C('R'); driver_output2(desc->port, resbuf, 1, NULL, 0); return; @@ -2461,8 +2674,11 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_CHARSIZE); d->flags = get_int32((uchar*)buf); + dt_i1 = d->flags; name = buf+4; FILENAME_COPY(d->b, name); + dt_s1 = d->b; + dt_utag = name + strlen(d->b) + 1; d->command = command; d->invoke = invoke_open; d->free = free_data; @@ -2474,7 +2690,9 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data)); + dt_utag = name; d->fd = fd; + dt_i1 = fd; d->command = command; d->invoke = invoke_fdatasync; d->free = free_data; @@ -2486,7 +2704,9 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data)); + dt_utag = name; d->fd = fd; + dt_i1 = fd; d->command = command; d->invoke = invoke_fsync; d->free = free_data; @@ -2502,7 +2722,13 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); + dt_utag = name + strlen(d->b) + 1; d->fd = fd; + if (command == FILE_LSTAT) { + dt_s1 = d->b; + } else { + dt_i1 = fd; + } d->command = command; d->invoke = invoke_flstat; d->free = free_data; @@ -2514,8 +2740,11 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data)); + dt_utag = name; d->flags = desc->flags; d->fd = fd; + dt_i1 = fd; + dt_i2 = d->flags; d->command = command; d->invoke = invoke_truncate; d->free = free_data; @@ -2529,13 +2758,18 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(buf + 9*4) + FILENAME_CHARSIZE); d->info.mode = get_int32(buf + 0 * 4); + dt_i1 = d->info.mode; d->info.uid = get_int32(buf + 1 * 4); + dt_i2 = d->info.uid; d->info.gid = get_int32(buf + 2 * 4); + dt_i3 = d->info.gid; d->info.accessTime = (time_t)((Sint64)get_int64(buf + 3 * 4)); d->info.modifyTime = (time_t)((Sint64)get_int64(buf + 5 * 4)); d->info.cTime = (time_t)((Sint64)get_int64(buf + 7 * 4)); FILENAME_COPY(d->b, buf + 9*4); + dt_s1 = d->b; + dt_utag = buf + 9 * 4 + strlen(d->b) + 1; d->command = command; d->invoke = invoke_write_info; d->free = free_data; @@ -2548,6 +2782,8 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); FILENAME_COPY(d->b, name); + dt_s1 = d->b; + dt_utag = name + strlen(d->b) + 1; d->command = command; d->invoke = invoke_readlink; d->free = free_data; @@ -2559,6 +2795,8 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); FILENAME_COPY(d->b, name); + dt_s1 = d->b; + dt_utag = name + strlen(d->b) + 1; d->command = command; d->invoke = invoke_altname; d->free = free_data; @@ -2578,7 +2816,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); + dt_s1 = d->b; FILENAME_COPY(d->b + namelen, new_name); + dt_s2 = d->b + namelen; + dt_utag = buf + namelen + strlen(dt_s2) + 1; d->flags = desc->flags; d->fd = fd; d->command = command; @@ -2599,7 +2840,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); + dt_s1 = d->b; FILENAME_COPY(d->b + namelen, new_name); + dt_s2 = d->b + namelen; + dt_utag = buf + namelen + strlen(dt_s2) + 1; d->flags = desc->flags; d->fd = fd; d->command = command; @@ -2614,13 +2858,18 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data)); d->fd = fd; + dt_i1 = d->fd; d->command = command; d->invoke = invoke_fadvise; d->free = free_data; d->level = 2; d->c.fadvise.offset = get_int64((uchar*) buf); + dt_i2 = d->c.fadvise.offset; d->c.fadvise.length = get_int64(((uchar*) buf) + sizeof(Sint64)); + dt_i3 = d->c.fadvise.length; d->c.fadvise.advise = get_int32(((uchar*) buf) + 2 * sizeof(Sint64)); + dt_i4 = d->c.fadvise.advise; + dt_utag = buf + 3 * sizeof(Sint64); goto done; } @@ -2634,6 +2883,22 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) done: if (d) { +#ifdef HAVE_DTRACE + d->sched_i1 = dt_priv->thread_num; + d->sched_i2 = dt_priv->tag; + d->sched_utag[0] = '\0'; + if (dt_utag != NULL) { + if (dt_utag[0] == '\0') { + dt_utag = NULL; + } else { + strncpy(d->sched_utag, dt_utag, sizeof(d->sched_utag) - 1); + d->sched_utag[sizeof(d->sched_utag) - 1] = '\0'; + } + } + DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++, + dt_utag, command, dt_s1, dt_s2, + dt_i1, dt_i2, dt_i3, dt_i4, desc->port_str); +#endif cq_enq(desc, d); } } @@ -2647,6 +2912,11 @@ file_flush(ErlDrvData e) { #ifdef DEBUG int r; #endif +#ifdef HAVE_DTRACE + dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); +#else + dt_private *dt_priv = NULL; +#endif TRACE_C('f'); @@ -2657,7 +2927,8 @@ file_flush(ErlDrvData e) { #ifdef DEBUG r = #endif - flush_write(desc, NULL); + flush_write(desc, NULL, dt_priv, + (desc->d == NULL) ? NULL : desc->d->sched_utag); /* Only possible reason for bad return value is ENOMEM, and * there is nobody to tell... */ @@ -2699,6 +2970,11 @@ static void file_timeout(ErlDrvData e) { file_descriptor *desc = (file_descriptor *)e; enum e_timer timer_state = desc->timer_state; +#ifdef HAVE_DTRACE + dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); +#else + dt_private *dt_priv = NULL; +#endif TRACE_C('t'); @@ -2716,7 +2992,8 @@ file_timeout(ErlDrvData e) { #ifdef DEBUG int r = #endif - flush_write(desc, NULL); + flush_write(desc, NULL, dt_priv, + (desc->d == NULL) ? NULL : desc->d->sched_utag); /* Only possible reason for bad return value is ENOMEM, and * there is nobody to tell... */ @@ -2737,7 +3014,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { char command; 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; +#ifdef HAVE_DTRACE + dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); +#else + dt_private *dt_priv = NULL; +#endif TRACE_C('v'); p = 0; q = 1; @@ -2756,25 +3040,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { switch (command) { case FILE_CLOSE: { + dt_utag = EV_CHAR_P(ev, p, q); flush_read(desc); - if (flush_write_check_error(desc, &err) < 0) { + if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { reply_posix_error(desc, err); goto done; } - if (ev->size != 1) { - /* Wrong command length */ - reply_posix_error(desc, EINVAL); - goto done; - } if (desc->fd != FILE_FD_INVALID) { - struct t_data *d; if (! (d = EF_ALLOC(sizeof(struct t_data)))) { reply_posix_error(desc, ENOMEM); } else { d->command = command; d->reply = !0; d->fd = desc->fd; + dt_i1 = d->fd; d->flags = desc->flags; + dt_i2 = d->flags; d->invoke = invoke_close; d->free = free_data; d->level = 2; @@ -2790,8 +3071,15 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { case FILE_READ: { Uint32 sizeH, sizeL; size_t size, alloc_size; - struct t_data *d; - if (flush_write_check_error(desc, &err) < 0) { + + if (!EV_GET_UINT32(ev, &sizeH, &p, &q) + || !EV_GET_UINT32(ev, &sizeL, &p, &q)) { + /* Wrong buffer length to contain the read count */ + reply_posix_error(desc, EINVAL); + goto done; + } + dt_utag = EV_CHAR_P(ev, p, q); + if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { reply_posix_error(desc, err); goto done; } @@ -2799,19 +3087,12 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { if (desc->read_bufsize == 0 && desc->read_binp != NULL && desc->read_size > 0) { /* We have allocated a buffer for line mode but should not really have a read-ahead buffer... */ - if (lseek_flush_read(desc, &err) < 0) { + if (lseek_flush_read(desc, &err, dt_priv) < 0) { reply_posix_error(desc, err); goto done; } } #endif - if (ev->size != 1+8 - || !EV_GET_UINT32(ev, &sizeH, &p, &q) - || !EV_GET_UINT32(ev, &sizeL, &p, &q)) { - /* Wrong buffer length to contain the read count */ - reply_posix_error(desc, EINVAL); - goto done; - } #if SIZEOF_SIZE_T == 4 if (sizeH != 0) { reply_posix_error(desc, EINVAL); @@ -2882,11 +3163,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; + dt_i1 = d->fd; d->flags = desc->flags; + dt_i2 = d->flags; d->c.read.binp = desc->read_binp; d->c.read.bin_offset = desc->read_offset + desc->read_size; d->c.read.bin_size = desc->read_binp->orig_size - d->c.read.bin_offset; d->c.read.size = size; + dt_i3 = d->c.read.size; driver_binary_inc_refc(d->c.read.binp); d->invoke = invoke_read; d->free = free_read; @@ -2904,12 +3188,12 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { * allocated binary + dealing with offsets and lengts are done in file_async ready * for this OP. */ - struct t_data *d; - if (flush_write_check_error(desc, &err) < 0) { + dt_utag = EV_CHAR_P(ev, p, q); + if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { reply_posix_error(desc, err); goto done; } - if (ev->size != 1) { + if (ev->size != 1+strlen(dt_utag)+1) { /* Wrong command length */ reply_posix_error(desc, EINVAL); goto done; @@ -2961,13 +3245,17 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; + dt_i1 = d->fd; d->flags = desc->flags; + dt_i2 = d->flags; d->c.read_line.binp = desc->read_binp; d->c.read_line.read_offset = desc->read_offset; d->c.read_line.read_size = desc->read_size; + dt_i3 = d->c.read_line.read_offset; #if !ALWAYS_READ_LINE_AHEAD d->c.read_line.read_ahead = (desc->read_bufsize > 0); #endif + dt_i4 = d->c.read_line.read_ahead; driver_binary_inc_refc(d->c.read.binp); d->invoke = invoke_read_line; d->free = free_read_line; @@ -2977,7 +3265,21 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { case FILE_WRITE: { ErlDrvSizeT skip = 1; ErlDrvSizeT size = ev->size - skip; - if (lseek_flush_read(desc, &err) < 0) { + + dt_utag = EV_CHAR_P(ev, p, q); + skip += strlen(dt_utag) + 1; + size = ev->size - skip; + /* + * Interesting dependency on using port # for key to async + * I/O worker pool thread: lseek_flush_read() can enqueue a + * lseek() op. If that lseek() were scheduled on a different + * thread than the write that we'll enqueue later in this case, + * then Bad Things could happen. This DTrace work is probably + * well worthwhile to get a sense of how often there's head-of- + * line blocking/unfairness during busy file I/O because of the + * mapping of port #/key -> thread. + */ + if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { reply_posix_error(desc, err); goto done; } @@ -3004,7 +3306,8 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { driver_set_timer(desc->port, desc->write_delay); } } else { - if (async_write(desc, &err, !0, size) != 0) { + if ((d = async_write(desc, &err, !0, size, + &dt_i1, &dt_i2, &dt_i3)) == NULL) { MUTEX_UNLOCK(desc->q_mtx); reply_posix_error(desc, err); goto done; @@ -3017,19 +3320,25 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { case FILE_PWRITEV: { Uint32 i, j, n; size_t total; - struct t_data *d; - if (lseek_flush_read(desc, &err) < 0) { - reply_Uint_posix_error(desc, 0, err); + char tmp; + int dt_utag_bytes = 1; + + dt_utag = EV_CHAR_P(ev, p, q); + while (EV_GET_CHAR(ev, &tmp, &p, &q) && tmp != '\0') { + dt_utag_bytes++; + } + if (ev->size < 1+4+dt_utag_bytes + || !EV_GET_UINT32(ev, &n, &p, &q)) { + /* Buffer too short to contain even the number of pos/size specs */ + reply_Uint_posix_error(desc, 0, EINVAL); goto done; } - if (flush_write_check_error(desc, &err) < 0) { + if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { reply_Uint_posix_error(desc, 0, err); goto done; } - if (ev->size < 1+4 - || !EV_GET_UINT32(ev, &n, &p, &q)) { - /* Buffer too short to contain even the number of pos/size specs */ - reply_Uint_posix_error(desc, 0, EINVAL); + if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + reply_Uint_posix_error(desc, 0, err); goto done; } if (n == 0) { @@ -3041,7 +3350,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } goto done; } - if (ev->size < 1+4+8*(2*n)) { + if (ev->size < 1+4+8*(2*n)+dt_utag_bytes) { /* Buffer too short to contain even the pos/size specs */ reply_Uint_posix_error(desc, 0, EINVAL); goto done; @@ -3055,7 +3364,9 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; + dt_i1 = d->fd; d->flags = desc->flags; + dt_i2 = d->flags; d->c.pwritev.port = desc->port; d->c.pwritev.q_mtx = desc->q_mtx; d->c.pwritev.n = n; @@ -3093,13 +3404,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } } d->c.pwritev.size = total; + dt_i3 = d->c.pwritev.size; d->c.pwritev.free_size = 0; if (j == 0) { /* Trivial case - nothing to write */ EF_FREE(d); reply_Uint(desc, 0); } else { - ErlDrvSizeT skip = 1 + 4 + 8*(2*n); + ErlDrvSizeT skip = 1 + 4 + 8 * (2*n) + dt_utag_bytes; if (skip + total != ev->size) { /* Actual amount of data does not match * total of all pos/size specs @@ -3123,24 +3435,30 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { case FILE_PREADV: { register void * void_ptr; Uint32 i, n; - struct t_data *d; ErlIOVec *res_ev; - if (lseek_flush_read(desc, &err) < 0) { + char tmp; + int dt_utag_bytes = 1; + + dt_utag = EV_CHAR_P(ev, p, q); + while (EV_GET_CHAR(ev, &tmp, &p, &q) && tmp != '\0') { + dt_utag_bytes++; + } + if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { reply_posix_error(desc, err); goto done; } - if (flush_write_check_error(desc, &err) < 0) { + if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { reply_posix_error(desc, err); goto done; } - if (ev->size < 1+8 + if (ev->size < 1+8+dt_utag_bytes || !EV_GET_UINT32(ev, &n, &p, &q) || !EV_GET_UINT32(ev, &n, &p, &q)) { /* Buffer too short to contain even the number of pos/size specs */ reply_posix_error(desc, EINVAL); goto done; } - if (ev->size != 1+8+8*(2*n)) { + if (ev->size < 1+8+8*(2*n)+dt_utag_bytes) { /* Buffer wrong length to contain the pos/size specs */ reply_posix_error(desc, EINVAL); goto done; @@ -3159,7 +3477,9 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; + dt_i1 = d->fd; d->flags = desc->flags; + dt_i2 = d->flags; d->c.preadv.n = n; d->c.preadv.cnt = 0; d->c.preadv.size = 0; @@ -3187,6 +3507,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else size = ((size_t)sizeH<<32) | sizeL; #endif + dt_i3 += size; if (! (res_ev->binv[i] = driver_alloc_binary(size))) { reply_posix_error(desc, ENOMEM); break; @@ -3233,31 +3554,33 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } goto done; /* case FILE_PREADV: */ case FILE_LSEEK: { - Sint64 offset; /* Offset for seek */ + Sint64 offset; /* Offset for seek */ Uint32 origin; /* Origin of seek. */ - if (lseek_flush_read(desc, &err) < 0) { - reply_posix_error(desc, err); + + if (ev->size < 1+8+4 + || !EV_GET_UINT64(ev, &offset, &p, &q) + || !EV_GET_UINT32(ev, &origin, &p, &q)) { + /* Wrong length of buffer to contain offset and origin */ + reply_posix_error(desc, EINVAL); goto done; } - if (flush_write_check_error(desc, &err) < 0) { + dt_utag = EV_CHAR_P(ev, p, q); + if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { reply_posix_error(desc, err); goto done; } - if (ev->size != 1+8+4 - || !EV_GET_UINT64(ev, &offset, &p, &q) - || !EV_GET_UINT32(ev, &origin, &p, &q)) { - /* Wrong length of buffer to contain offset and origin */ - reply_posix_error(desc, EINVAL); + if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + reply_posix_error(desc, err); goto done; } - if (async_lseek(desc, &err, !0, offset, origin) < 0) { + if ((d = async_lseek(desc, &err, !0, offset, origin, + &dt_i1, &dt_i2, &dt_i3)) == NULL) { reply_posix_error(desc, err); goto done; } } goto done; case FILE_READ_FILE: { - struct t_data *d; char *filename; if (ev->size < 1+1) { /* Buffer contains empty name */ @@ -3279,6 +3602,8 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->reply = !0; /* Copy name */ FILENAME_COPY(d->b, filename); + dt_s1 = d->b; + dt_utag = filename + strlen(d->b) + 1; d->c.read_file.binp = NULL; d->invoke = invoke_read_file; d->free = free_read_file; @@ -3298,7 +3623,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { char mode; Sint64 hdr_offset; Uint32 max_size; - struct t_data *d; ErlIOVec *res_ev; int vsize; if (! EV_GET_CHAR(ev, &mode, &p, &q)) { @@ -3310,14 +3634,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } - if (lseek_flush_read(desc, &err) < 0) { - reply_posix_error(desc, err); - goto done; - } - if (flush_write_check_error(desc, &err) < 0) { - reply_posix_error(desc, err); - goto done; - } if (ev->size < 1+1+8+4 || !EV_GET_UINT64(ev, &hdr_offset, &p, &q) || !EV_GET_UINT32(ev, &max_size, &p, &q)) { @@ -3326,6 +3642,15 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } + dt_utag = EV_CHAR_P(ev, p, q); + if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { + reply_posix_error(desc, err); + goto done; + } + if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + reply_posix_error(desc, err); + goto done; + } /* Create the thread data structure with the contained ErlIOVec * and corresponding binaries for the response */ @@ -3339,9 +3664,13 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; + dt_i1 = d->fd; d->flags = desc->flags; + dt_i2 = d->flags; d->c.preadv.offsets[0] = hdr_offset; + dt_i3 = d->c.preadv.offsets[0]; d->c.preadv.size = max_size; + dt_i4 = d->c.preadv.size; res_ev = &d->c.preadv.eiov; /* XXX possible alignment problems here for weird machines */ res_ev->iov = void_ptr = d + 1; @@ -3356,16 +3685,19 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { case FILE_SETOPT: { char opt; + if (ev->size < 1+1 || !EV_GET_CHAR(ev, &opt, &p, &q)) { /* Buffer too short to contain even the option type */ reply_posix_error(desc, EINVAL); goto done; } + dt_i1 = opt; + dt_utag = EV_CHAR_P(ev, p, q); switch (opt) { case FILE_OPT_DELAYED_WRITE: { Uint32 sizeH, sizeL, delayH, delayL; - if (ev->size != 1+1+4*sizeof(Uint32) + if (ev->size != 1+1+4*sizeof(Uint32)+strlen(dt_utag)+1 || !EV_GET_UINT32(ev, &sizeH, &p, &q) || !EV_GET_UINT32(ev, &sizeL, &p, &q) || !EV_GET_UINT32(ev, &delayH, &p, &q) @@ -3392,12 +3724,13 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else desc->write_delay = ((unsigned long)delayH << 32) | delayL; #endif + dt_i2 = desc->write_delay; TRACE_C('K'); reply_ok(desc); } goto done; case FILE_OPT_READ_AHEAD: { Uint32 sizeH, sizeL; - if (ev->size != 1+1+2*sizeof(Uint32) + if (ev->size != 1+1+2*sizeof(Uint32)+strlen(dt_utag)+1 || !EV_GET_UINT32(ev, &sizeH, &p, &q) || !EV_GET_UINT32(ev, &sizeL, &p, &q)) { /* Buffer has wrong length to contain the option values */ @@ -3413,6 +3746,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else desc->read_bufsize = ((size_t)sizeH << 32) | sizeL; #endif + dt_i2 = desc->read_bufsize; TRACE_C('K'); reply_ok(desc); } goto done; @@ -3499,11 +3833,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } /* switch(command) */ - if (lseek_flush_read(desc, &err) < 0) { + if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { reply_posix_error(desc, err); goto done; } - if (flush_write_check_error(desc, &err) < 0) { + if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { reply_posix_error(desc, err); goto done; } else { @@ -3521,5 +3855,46 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } done: + if (d != NULL) { +#ifdef HAVE_DTRACE + /* + * If d == NULL, then either: + * 1). There was an error of some sort, or + * 2). The command given to us is actually implemented + * by file_output() instead. + * + * Case #1 is probably a TODO item, perhaps? + * Case #2 we definitely don't want to activate a probe. + */ + d->sched_i1 = dt_priv->thread_num; + d->sched_i2 = dt_priv->tag; + d->sched_utag[0] = '\0'; + if (dt_utag != NULL) { + strncpy(d->sched_utag, dt_utag, sizeof(d->sched_utag) - 1); + d->sched_utag[sizeof(d->sched_utag) - 1] = '\0'; + } + DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++, + dt_utag, command, dt_s1, NULL, dt_i1, dt_i2, dt_i3, dt_i4, + desc->port_str); +#endif + } cq_execute(desc); } + +#ifdef HAVE_DTRACE +dt_private * +get_dt_private(int base) +{ + dt_private *dt_priv = (dt_private *) pthread_getspecific(dt_driver_key); + + if (dt_priv == NULL) { + dt_priv = EF_SAFE_ALLOC(sizeof(dt_private)); + erts_mtx_lock(&dt_driver_mutex); + dt_priv->thread_num = (base + dt_driver_idnum++); + erts_mtx_unlock(&dt_driver_mutex); + dt_priv->tag = 0; + pthread_setspecific(dt_driver_key, dt_priv); + } + return dt_priv; +} +#endif /* HAVE_DTRACE */ -- cgit v1.2.3 From 0fd4e39abeea3fc87b78eec8495109f9245b5ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 7 Feb 2012 19:19:27 +0100 Subject: Update dtrace for changes in R15 --- erts/emulator/Makefile.in | 6 ++- erts/emulator/beam/beam_emu.c | 85 ++++++-------------------------- erts/emulator/beam/dist.c | 16 ++++-- erts/emulator/beam/dtrace-wrapper.h | 9 ---- erts/emulator/beam/erl_async.c | 10 ++-- erts/emulator/beam/erl_gc.c | 1 - erts/emulator/beam/erl_message.c | 12 +++-- erts/emulator/beam/global.h | 69 +++++++++++++++++++++++--- erts/emulator/drivers/common/efile_drv.c | 26 ++++++---- 9 files changed, 125 insertions(+), 109 deletions(-) (limited to 'erts/emulator') 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 #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), "", next); + erts_snprintf(fun_buf, sizeof(fun_buf), + "", 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 #include @@ -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 -- cgit v1.2.3 From c15f94e7922040b63f3abf8680cd77d5548fecf3 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Mon, 13 Feb 2012 20:13:37 +0100 Subject: Add user tag spreading functionality to VM and use in file User tags in a dynamic trace enabled VM are spread throughout the system in the same way as seq_trace tokens. This is used by the file module and various other modules to get hold of the tag from the user process without changing the protocol. --- erts/emulator/beam/atom.names | 1 + erts/emulator/beam/beam_emu.c | 55 +++- erts/emulator/beam/bif.c | 188 +++++++++++- erts/emulator/beam/bif.tab | 17 ++ erts/emulator/beam/dist.c | 32 +- erts/emulator/beam/erl_alloc.c | 6 +- erts/emulator/beam/erl_bif_ddll.c | 6 +- erts/emulator/beam/erl_bif_timer.c | 6 +- erts/emulator/beam/erl_bif_trace.c | 34 ++- erts/emulator/beam/erl_db_util.c | 12 +- erts/emulator/beam/erl_gc.c | 18 +- erts/emulator/beam/erl_message.c | 182 ++++++++++-- erts/emulator/beam/erl_message.h | 13 +- erts/emulator/beam/erl_nif.c | 6 +- erts/emulator/beam/erl_process.c | 34 ++- erts/emulator/beam/erl_process.h | 12 + erts/emulator/beam/erl_trace.c | 51 +++- erts/emulator/beam/io.c | 30 +- erts/emulator/beam/utils.c | 6 +- erts/emulator/drivers/common/efile_drv.c | 488 +++++++++++++++++++++++-------- 20 files changed, 988 insertions(+), 209 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index 7be40976f6..9ce1068b23 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -248,6 +248,7 @@ atom global_heaps_size atom Gt='>' atom grun atom group_leader +atom have_dt_utag atom heap_block_size atom heap_size atom heap_sizes diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 1dbe2cad00..deeb7357d6 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -1892,23 +1892,52 @@ void process_main(void) save_calls(c_p, &exp_receive); } if (ERL_MESSAGE_TOKEN(msgp) == NIL) { - SEQ_TRACE_TOKEN(c_p) = NIL; +#ifdef HAVE_DTRACE + if (DT_UTAG(c_p) != NIL) { + if (DT_UTAG_FLAGS(c_p) & DT_UTAG_PERMANENT) { + SEQ_TRACE_TOKEN(c_p) = am_have_dt_utag; + if (DT_UTAG_FLAGS(c_p) & DT_UTAG_SPREADING) + erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) stop spreading tag %T with message %T\r\n",c_p->id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp)); + } else { + erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) kill tag %T with message %T\r\n",c_p->id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp)); + DT_UTAG(c_p) = NIL; + SEQ_TRACE_TOKEN(c_p) = NIL; + } + } else { +#endif + SEQ_TRACE_TOKEN(c_p) = NIL; +#ifdef HAVE_DTRACE + } + DT_UTAG_FLAGS(c_p) &= ~DT_UTAG_SPREADING; +#endif } else if (ERL_MESSAGE_TOKEN(msgp) != am_undefined) { Eterm msg; SEQ_TRACE_TOKEN(c_p) = ERL_MESSAGE_TOKEN(msgp); - ASSERT(is_tuple(SEQ_TRACE_TOKEN(c_p))); - ASSERT(SEQ_TRACE_TOKEN_ARITY(c_p) == 5); - ASSERT(is_small(SEQ_TRACE_TOKEN_SERIAL(c_p))); - ASSERT(is_small(SEQ_TRACE_TOKEN_LASTCNT(c_p))); - ASSERT(is_small(SEQ_TRACE_TOKEN_FLAGS(c_p))); - ASSERT(is_pid(SEQ_TRACE_TOKEN_SENDER(c_p))); - c_p->seq_trace_lastcnt = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p)); - if (c_p->seq_trace_clock < unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p))) { - c_p->seq_trace_clock = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p)); +#ifdef HAVE_DTRACE + if (ERL_MESSAGE_TOKEN(msgp) == am_have_dt_utag) { + if (DT_UTAG(c_p) == NIL) { + DT_UTAG(c_p) = ERL_MESSAGE_DT_UTAG(msgp); + } + DT_UTAG_FLAGS(c_p) |= DT_UTAG_SPREADING; + erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) receive tag (%T) with message %T\r\n",c_p->id, DT_UTAG(c_p), ERL_MESSAGE_TERM(msgp)); + } else { +#endif + ASSERT(is_tuple(SEQ_TRACE_TOKEN(c_p))); + ASSERT(SEQ_TRACE_TOKEN_ARITY(c_p) == 5); + ASSERT(is_small(SEQ_TRACE_TOKEN_SERIAL(c_p))); + ASSERT(is_small(SEQ_TRACE_TOKEN_LASTCNT(c_p))); + ASSERT(is_small(SEQ_TRACE_TOKEN_FLAGS(c_p))); + ASSERT(is_pid(SEQ_TRACE_TOKEN_SENDER(c_p))); + c_p->seq_trace_lastcnt = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p)); + if (c_p->seq_trace_clock < unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p))) { + c_p->seq_trace_clock = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p)); + } + msg = ERL_MESSAGE_TERM(msgp); + seq_trace_output(SEQ_TRACE_TOKEN(c_p), msg, SEQ_TRACE_RECEIVE, + c_p->id, c_p); +#ifdef HAVE_DTRACE } - msg = ERL_MESSAGE_TERM(msgp); - seq_trace_output(SEQ_TRACE_TOKEN(c_p), msg, SEQ_TRACE_RECEIVE, - c_p->id, c_p); +#endif } if (DTRACE_ENABLED(message_receive)) { Eterm token2 = NIL; diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index ebdca87f4a..6478e54996 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -563,7 +563,11 @@ erts_queue_monitor_message(Process *p, ref_copy = copy_struct(ref, ref_size, &hp, ohp); tup = TUPLE5(hp, am_DOWN, ref_copy, type, item_copy, reason_copy); - erts_queue_message(p, p_locksp, bp, tup, NIL); + erts_queue_message(p, p_locksp, bp, tup, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); } static BIF_RETTYPE @@ -1944,7 +1948,11 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend) { if (ERTS_PROC_GET_SAVED_CALLS_BUF(p)) save_calls(p, &exp_send); - if (SEQ_TRACE_TOKEN(p) != NIL) { + if (SEQ_TRACE_TOKEN(p) != NIL +#ifdef HAVE_DTRACE + && SEQ_TRACE_TOKEN(p) != am_have_dt_utag +#endif + ) { seq_trace_update_send(p); seq_trace_output(SEQ_TRACE_TOKEN(p), msg, SEQ_TRACE_SEND, portid, p); @@ -4226,13 +4234,21 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2) for (i = 0; i < erts_max_processes; i++) { if (process_tab[i] != (Process*) 0) { Process* p = process_tab[i]; +#ifdef HAVE_DTRACE + p->seq_trace_token = (p->dt_utag != NIL) ? am_have_dt_utag : NIL; +#else p->seq_trace_token = NIL; +#endif p->seq_trace_clock = 0; p->seq_trace_lastcnt = 0; ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p); mp = p->msg.first; while(mp != NULL) { +#ifdef HAVE_DTRACE + ERL_MESSAGE_TOKEN(mp) = (ERL_MESSAGE_DT_UTAG(mp) != NIL) ? am_have_dt_utag : NIL; +#else ERL_MESSAGE_TOKEN(mp) = NIL; +#endif mp = mp->next; } } @@ -4630,3 +4646,171 @@ BIF_RETTYPE get_module_info_2(BIF_ALIST_2) } BIF_RET(ret); } + +BIF_RETTYPE put_utag_1(BIF_ALIST_1) +{ +#ifdef HAVE_DTRACE + Eterm otag; + if (BIF_ARG_1 == am_undefined) { + otag = (DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P); + DT_UTAG(BIF_P) = NIL; + DT_UTAG_FLAGS(BIF_P) = 0; + if (SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag) { + SEQ_TRACE_TOKEN(BIF_P) = NIL; + } + BIF_RET(otag); + } + if (!is_binary(BIF_ARG_1)) { + BIF_ERROR(BIF_P,BADARG); + } + otag = (DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P); + DT_UTAG(BIF_P) = BIF_ARG_1; + DT_UTAG_FLAGS(BIF_P) |= DT_UTAG_PERMANENT; + if (SEQ_TRACE_TOKEN(BIF_P) == NIL) { + SEQ_TRACE_TOKEN(BIF_P) = am_have_dt_utag; + } + BIF_RET(otag); +#else + BIF_RET(am_undefined); +#endif +} + +BIF_RETTYPE get_utag_0(BIF_ALIST_0) +{ +#ifdef HAVE_DTRACE + BIF_RET((DT_UTAG(BIF_P) == NIL || !(DT_UTAG_FLAGS(BIF_P) & DT_UTAG_PERMANENT)) ? am_undefined : DT_UTAG(BIF_P)); +#else + BIF_RET(am_undefined); +#endif +} +BIF_RETTYPE get_utag_data_0(BIF_ALIST_0) +{ +#ifdef HAVE_DTRACE + BIF_RET((DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P)); +#else + BIF_RET(am_undefined); +#endif +} +BIF_RETTYPE prepend_vm_utag_data_1(BIF_ALIST_1) +{ +#ifdef HAVE_DTRACE + Eterm b; + Eterm *hp; + hp = HAlloc(BIF_P,2); + if (is_binary((DT_UTAG(BIF_P)))) { + Uint sz = binary_size(DT_UTAG(BIF_P)); + int i; + unsigned char *p,*q; + byte *temp_alloc = NULL; + b = new_binary(BIF_P,NULL,sz+1); + q = binary_bytes(b); + p = erts_get_aligned_binary_bytes(DT_UTAG(BIF_P),&temp_alloc); + for(i=0;i (%T) start spreading tag %T\r\n",BIF_P->id,DT_UTAG(BIF_P)); + } else { + DT_UTAG_FLAGS(BIF_P) &= ~DT_UTAG_SPREADING; + erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) stop spreading tag %T\r\n",BIF_P->id,DT_UTAG(BIF_P)); + } + } + BIF_RET(ret); +#else + BIF_RET(am_true); +#endif +} +BIF_RETTYPE restore_utag_1(BIF_ALIST_1) +{ +#ifdef HAVE_DTRACE + Eterm *tpl; + Uint x; + if (is_not_tuple(BIF_ARG_1)) { + BIF_ERROR(BIF_P,BADARG); + } + tpl = tuple_val(BIF_ARG_1); + if(arityval(*tpl) != 2 || is_not_small(tpl[1]) || (is_not_binary(tpl[2]) && tpl[2] != NIL)) { + BIF_ERROR(BIF_P,BADARG); + } + if (tpl[2] == NIL) { + if (DT_UTAG(BIF_P) != NIL) { + erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) restore Killing tag!\r\n",BIF_P->id); + } + DT_UTAG(BIF_P) = NIL; + if (SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag) { + SEQ_TRACE_TOKEN(BIF_P) = NIL; + } + DT_UTAG_FLAGS(BIF_P) = 0; + } else { + x = unsigned_val(tpl[1]) & (DT_UTAG_SPREADING | DT_UTAG_PERMANENT); + if (!(x & DT_UTAG_SPREADING) && (DT_UTAG_FLAGS(BIF_P) & DT_UTAG_SPREADING)) { + erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) restore stop spreading tag %T\r\n",BIF_P->id,tpl[2]); + } else if ((x & DT_UTAG_SPREADING) && !(DT_UTAG_FLAGS(BIF_P) & DT_UTAG_SPREADING)) { + erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) restore start spreading tag %T\r\n",BIF_P->id,tpl[2]); + } + DT_UTAG_FLAGS(BIF_P) = x; + DT_UTAG(BIF_P) = tpl[2]; + if (SEQ_TRACE_TOKEN(BIF_P) == NIL) { + SEQ_TRACE_TOKEN(BIF_P) = am_have_dt_utag; + } + } +#else + if (BIF_ARG_1 != am_true) { + BIF_ERROR(BIF_P,BADARG); + } +#endif + BIF_RET(am_true); +} + + diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index 007c884a6a..7940544156 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -814,6 +814,23 @@ bif erlang:check_old_code/1 # bif erlang:universaltime_to_posixtime/1 bif erlang:posixtime_to_universaltime/1 + +# +# New in R15B01 +# + +# The dtrace BIF's are always present, but give dummy results if dynamic trace is not enabled in the build +bif erlang:put_utag/1 +bif erlang:get_utag/0 +bif erlang:get_utag_data/0 +bif erlang:spread_utag/1 +bif erlang:restore_utag/1 + +# These are dummies even with enabled dynamic trace unless vm probes are enabled. +# They are also internal, for dtrace tags sent to the VM's own drivers (efile) +bif erlang:prepend_vm_utag_data/1 +bif erlang:append_vm_utag_data/1 + # # Obsolete # diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index ba55a1918a..43fc910054 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -382,7 +382,11 @@ static void doit_node_link_net_exits(ErtsLink *lnk, void *vnecp) Eterm tup; Eterm *hp = erts_alloc_message_heap(3,&bp,&ohp,rp,&rp_locks); tup = TUPLE2(hp, am_nodedown, name); - erts_queue_message(rp, &rp_locks, bp, tup, NIL); + erts_queue_message(rp, &rp_locks, bp, tup, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); } erts_smp_proc_unlock(rp, rp_locks); } @@ -750,7 +754,11 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message) DTRACE_CHARBUF(receiver_name, 64); UseTmpHeapNoproc(5); - if (SEQ_TRACE_TOKEN(sender) != NIL) { + if (SEQ_TRACE_TOKEN(sender) != NIL +#ifdef HAVE_DTRACE + && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag +#endif + ) { seq_trace_update_send(sender); token = SEQ_TRACE_TOKEN(sender); seq_trace_output(token, message, SEQ_TRACE_SEND, remote, sender); @@ -799,7 +807,11 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message) DTRACE_CHARBUF(receiver_name, 128); UseTmpHeapNoproc(6); - if (SEQ_TRACE_TOKEN(sender) != NIL) { + if (SEQ_TRACE_TOKEN(sender) != NIL +#ifdef HAVE_DTRACE + && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag +#endif + ) { seq_trace_update_send(sender); token = SEQ_TRACE_TOKEN(sender); seq_trace_output(token, message, SEQ_TRACE_SEND, remote_name, sender); @@ -851,7 +863,11 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote, DTRACE_CHARBUF(reason_str, 128); UseTmpHeapNoproc(6); - if (token != NIL) { + if (token != NIL +#ifdef HAVE_DTRACE + && token != am_have_dt_utag +#endif + ) { seq_trace_update_send(dsdp->proc); seq_trace_output_exit(token, reason, SEQ_TRACE_SEND, remote, local); ctl = TUPLE5(&ctl_heap[0], @@ -866,7 +882,7 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote, erts_snprintf(remote_name, sizeof(remote_name), "{%T,%s}", remote, node_name); erts_snprintf(reason_str, sizeof(reason), "%T", reason); - if (token != NIL) { + if (token != NIL && token != am_have_dt_utag) { tok_label = signed_val(SEQ_TRACE_T_LABEL(token)); tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token)); tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); @@ -3094,7 +3110,11 @@ send_nodes_mon_msg(Process *rp, } ASSERT(hend == hp); - erts_queue_message(rp, rp_locksp, bp, msg, NIL); + erts_queue_message(rp, rp_locksp, bp, msg, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); } static void diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index df27186680..d575e30092 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -3001,7 +3001,11 @@ reply_alloc_info(void *vair) HRelease(rp, hp_end, hp); } - erts_queue_message(rp, &rp_locks, bp, msg, NIL); + erts_queue_message(rp, &rp_locks, bp, msg, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); if (air->req_sched == sched_id) rp_locks &= ~ERTS_PROC_LOCK_MAIN; diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c index 3326fd84df..b58c5ab761 100644 --- a/erts/emulator/beam/erl_bif_ddll.c +++ b/erts/emulator/beam/erl_bif_ddll.c @@ -1762,7 +1762,11 @@ static void notify_proc(Process *proc, Eterm ref, Eterm driver_name, Eterm type, hp += REF_THING_SIZE; mess = TUPLE5(hp,type,r,am_driver,driver_name,tag); } - erts_queue_message(proc, &rp_locks, bp, mess, am_undefined); + erts_queue_message(proc, &rp_locks, bp, mess, am_undefined +#ifdef HAVE_DTRACE + , NIL +#endif + ); erts_smp_proc_unlock(proc, rp_locks); ERTS_SMP_CHK_NO_PROC_LOCKS; } diff --git a/erts/emulator/beam/erl_bif_timer.c b/erts/emulator/beam/erl_bif_timer.c index a922a33da3..fbc2f08c09 100644 --- a/erts/emulator/beam/erl_bif_timer.c +++ b/erts/emulator/beam/erl_bif_timer.c @@ -373,7 +373,11 @@ bif_timer_timeout(ErtsBifTimer* btm) message = TUPLE3(hp, am_timeout, ref, message); } - erts_queue_message(rp, &rp_locks, bp, message, NIL); + erts_queue_message(rp, &rp_locks, bp, message, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); erts_smp_proc_unlock(rp, rp_locks); erts_smp_proc_dec_refc(rp); } diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c index b0a58c80ea..c518aa6866 100644 --- a/erts/emulator/beam/erl_bif_trace.c +++ b/erts/emulator/beam/erl_bif_trace.c @@ -1744,9 +1744,17 @@ Eterm erts_seq_trace(Process *p, Eterm arg1, Eterm arg2, return THE_NON_VALUE; } if (build_result) { +#ifdef HAVE_DTRACE + old_value = (SEQ_TRACE_TOKEN(p) == am_have_dt_utag) ? NIL : SEQ_TRACE_TOKEN(p); +#else old_value = SEQ_TRACE_TOKEN(p); +#endif } +#ifdef HAVE_DTRACE + SEQ_TRACE_TOKEN(p) = (DT_UTAG(p) != NIL) ? am_have_dt_utag : NIL; +#else SEQ_TRACE_TOKEN(p) = NIL; +#endif return old_value; } else { @@ -1759,7 +1767,11 @@ new_seq_trace_token(Process* p) { Eterm* hp; - if (SEQ_TRACE_TOKEN(p) == NIL) { + if (SEQ_TRACE_TOKEN(p) == NIL +#ifdef HAVE_DTRACE + || SEQ_TRACE_TOKEN(p) == am_have_dt_utag +#endif + ) { hp = HAlloc(p, 6); SEQ_TRACE_TOKEN(p) = TUPLE5(hp, make_small(0), /* Flags */ make_small(0), /* Label */ @@ -1779,7 +1791,11 @@ BIF_RETTYPE erl_seq_trace_info(Process *p, Eterm item) BIF_ERROR(p, BADARG); } - if (SEQ_TRACE_TOKEN(p) == NIL) { + if (SEQ_TRACE_TOKEN(p) == NIL +#ifdef HAVE_DTRACE + || SEQ_TRACE_TOKEN(p) == am_have_dt_utag +#endif + ) { if ((item == am_send) || (item == am_receive) || (item == am_print) || (item == am_timestamp)) { hp = HAlloc(p,3); @@ -1836,8 +1852,13 @@ BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1) */ BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1) { - if (SEQ_TRACE_TOKEN(BIF_P) == NIL) + if (SEQ_TRACE_TOKEN(BIF_P) == NIL +#ifdef HAVE_DTRACE + || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag +#endif + ) { BIF_RET(am_false); + } seq_trace_update_send(BIF_P); seq_trace_output(SEQ_TRACE_TOKEN(BIF_P), BIF_ARG_1, SEQ_TRACE_PRINT, NIL, BIF_P); @@ -1854,8 +1875,13 @@ BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1) */ BIF_RETTYPE seq_trace_print_2(BIF_ALIST_2) { - if (SEQ_TRACE_TOKEN(BIF_P) == NIL) + if (SEQ_TRACE_TOKEN(BIF_P) == NIL +#ifdef HAVE_DTRACE + || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag +#endif + ) { BIF_RET(am_false); + } if (!(is_atom(BIF_ARG_1) || is_small(BIF_ARG_1))) { BIF_ERROR(BIF_P, BADARG); } diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index 4821a7d9fb..eb05ceaaf1 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -2203,7 +2203,11 @@ restart: *esp++ = am_true; break; case matchIsSeqTrace: - if (SEQ_TRACE_TOKEN(c_p) != NIL) + if (SEQ_TRACE_TOKEN(c_p) != NIL +#ifdef HAVE_DTRACE + && SEQ_TRACE_TOKEN(c_p) != am_have_dt_utag +#endif + ) *esp++ = am_true; else *esp++ = am_false; @@ -2227,7 +2231,11 @@ restart: --esp; break; case matchGetSeqToken: - if (SEQ_TRACE_TOKEN(c_p) == NIL) + if (SEQ_TRACE_TOKEN(c_p) == NIL +#ifdef HAVE_DTRACE + || SEQ_TRACE_TOKEN(c_p) == am_have_dt_utag +#endif + ) *esp++ = NIL; else { Eterm sender = SEQ_TRACE_TOKEN_SENDER(c_p); diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 679a3645ba..6dfccfe52f 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -1935,7 +1935,13 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset) roots[n].sz = 1; n++; } - +#ifdef HAVE_DTRACE + if (is_not_immed(p->dt_utag)) { + roots[n].v = &p->dt_utag; + roots[n].sz = 1; + n++; + } +#endif ASSERT(is_nil(p->tracer_proc) || is_internal_pid(p->tracer_proc) || is_internal_port(p->tracer_proc)); @@ -2472,6 +2478,13 @@ offset_mqueue(Process *p, Sint offs, char* area, Uint area_size) if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) { ERL_MESSAGE_TOKEN(mp) = offset_ptr(mesg, offs); } +#ifdef HAVE_DTRACE + mesg = ERL_MESSAGE_DT_UTAG(mp); + if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) { + ERL_MESSAGE_DT_UTAG(mp) = offset_ptr(mesg, offs); + } +#endif + ASSERT((is_nil(ERL_MESSAGE_TOKEN(mp)) || is_tuple(ERL_MESSAGE_TOKEN(mp)) || is_atom(ERL_MESSAGE_TOKEN(mp)))); @@ -2491,6 +2504,9 @@ offset_one_rootset(Process *p, Sint offs, char* area, Uint area_size, offset_heap_ptr(&p->fvalue, 1, offs, area, area_size); offset_heap_ptr(&p->ftrace, 1, offs, area, area_size); offset_heap_ptr(&p->seq_trace_token, 1, offs, area, area_size); +#ifdef HAVE_DTRACE + offset_heap_ptr(&p->dt_utag, 1, offs, area, area_size); +#endif offset_heap_ptr(&p->group_leader, 1, offs, area, area_size); offset_mqueue(p, offs, area, area_size); offset_heap_ptr(p->stop, (STACK_START(p) - p->stop), offs, area, area_size); diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index 786d6ac52c..dc59b9c2c4 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -393,13 +393,26 @@ erts_queue_dist_message(Process *rcvr, receiver_name, size_object(msg), rcvr->msg.len, tok_label, tok_lastcnt, tok_serial); } - erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token); + erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token +#ifdef HAVE_DTRACE + , NIL +#endif + ); } else { /* Enqueue message on external format */ ERL_MESSAGE_TERM(mp) = THE_NON_VALUE; - ERL_MESSAGE_TOKEN(mp) = token; +#ifdef HAVE_DTRACE + ERL_MESSAGE_DT_UTAG(mp) = NIL; + if (token == am_have_dt_utag) { + ERL_MESSAGE_TOKEN(mp) = NIL; + } else { +#endif + ERL_MESSAGE_TOKEN(mp) = token; +#ifdef HAVE_DTRACE + } +#endif mp->next = NULL; if (DTRACE_ENABLED(message_queued)) { @@ -431,7 +444,11 @@ erts_queue_message(Process* receiver, ErtsProcLocks *receiver_locks, ErlHeapFragment* bp, Eterm message, - Eterm seq_trace_token) + Eterm seq_trace_token +#ifdef HAVE_DTRACE + , Eterm dt_utag +#endif +) { ErlMessage* mp; #ifdef ERTS_SMP @@ -472,6 +489,9 @@ erts_queue_message(Process* receiver, ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = seq_trace_token; +#ifdef HAVE_DTRACE + ERL_MESSAGE_DT_UTAG(mp) = dt_utag; +#endif mp->next = NULL; mp->data.heap_frag = bp; @@ -547,6 +567,9 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg) Sint offs; Uint sz; ErlHeapFragment *bp; +#ifdef HAVE_DTRACE + Eterm utag; +#endif #ifdef HARD_DEBUG ProcBin *dbg_mso_start = off_heap->mso; @@ -556,32 +579,56 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg) ErlHeapFragment *dbg_bp; Uint *dbg_hp, *dbg_thp_start; Uint dbg_term_sz, dbg_token_sz; +#ifdef HAVE_DTRACE + Eterm dbg_utag; + Uint dbg_utag_sz; +#endif #endif bp = msg->data.heap_frag; term = ERL_MESSAGE_TERM(msg); token = ERL_MESSAGE_TOKEN(msg); +#ifdef HAVE_DTRACE + utag = ERL_MESSAGE_DT_UTAG(msg); +#endif if (!bp) { +#ifdef HAVE_DTRACE + ASSERT(is_immed(term) && is_immed(token) && is_immed(utag)); +#else ASSERT(is_immed(term) && is_immed(token)); +#endif return; } #ifdef HARD_DEBUG dbg_term_sz = size_object(term); dbg_token_sz = size_object(token); + dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz); +#ifdef HAVE_DTRACE + dbg_utag_sz = size_object(utag); + dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz + dbg_utag_sz ); +#endif /*ASSERT(dbg_term_sz + dbg_token_sz == erts_msg_used_frag_sz(msg)); Copied size may be smaller due to removed SubBins's or garbage. Copied size may be larger due to duplicated shared terms. */ - dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz); dbg_hp = dbg_bp->mem; dbg_term = copy_struct(term, dbg_term_sz, &dbg_hp, &dbg_bp->off_heap); dbg_token = copy_struct(token, dbg_token_sz, &dbg_hp, &dbg_bp->off_heap); - dbg_thp_start = *hpp; +#ifdef HAVE_DTRACE + dbg_utag = copy_struct(utag, dbg_utag_sz, &dbg_hp, &dbg_bp->off_heap); +#endif + dbg_thp_start = *hpp; #endif if (bp->next != NULL) { - move_multi_frags(hpp, off_heap, bp, msg->m, 2); + move_multi_frags(hpp, off_heap, bp, msg->m, +#ifdef HAVE_DTRACE + 3 +#else + 2 +#endif + ); goto copy_done; } @@ -683,6 +730,16 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg) ASSERT(hp > ptr_val(ERL_MESSAGE_TERM(msg))); #endif } +#ifdef HAVE_DTRACE + if (is_not_immed(utag)) { + ASSERT(in_heapfrag(ptr_val(utag), bp)); + ERL_MESSAGE_DT_UTAG(msg) = offset_ptr(utag, offs); +#ifdef HARD_DEBUG + ASSERT(dbg_thp_start <= ptr_val(ERL_MESSAGE_DT_UTAG(msg))); + ASSERT(hp > ptr_val(ERL_MESSAGE_DT_UTAG(msg))); +#endif + } +#endif copy_done: @@ -749,6 +806,9 @@ copy_done: #ifdef HARD_DEBUG ASSERT(eq(ERL_MESSAGE_TERM(msg), dbg_term)); ASSERT(eq(ERL_MESSAGE_TOKEN(msg), dbg_token)); +#ifdef HAVE_DTRACE + ASSERT(eq(ERL_MESSAGE_DT_UTAG(msg), dbg_utag)); +#endif free_message_buffer(dbg_bp); #endif @@ -841,42 +901,85 @@ erts_send_message(Process* sender, } if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) { Eterm* hp; + Eterm stoken = SEQ_TRACE_TOKEN(sender); + Uint seq_trace_size = 0; +#ifdef HAVE_DTRACE + Uint dt_utag_size = 0; + Eterm utag = NIL; +#endif - BM_SWAP_TIMER(send,size); + BM_SWAP_TIMER(send,size); msize = size_object(message); - BM_SWAP_TIMER(size,send); + BM_SWAP_TIMER(size,send); + +#ifdef HAVE_DTRACE + if (stoken != am_have_dt_utag) { +#endif - seq_trace_update_send(sender); - seq_trace_output(SEQ_TRACE_TOKEN(sender), message, SEQ_TRACE_SEND, - receiver->id, sender); - bp = new_message_buffer(msize + 6 /* TUPLE5 */); + seq_trace_update_send(sender); + seq_trace_output(stoken, message, SEQ_TRACE_SEND, + receiver->id, sender); + seq_trace_size = 6; /* TUPLE5 */ +#ifdef HAVE_DTRACE + } + if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) { + dt_utag_size = size_object(DT_UTAG(sender)); + } else if (stoken == am_have_dt_utag ) { + stoken = NIL; + } +#endif + + bp = new_message_buffer(msize + seq_trace_size +#ifdef HAVE_DTRACE + + dt_utag_size +#endif + ); hp = bp->mem; BM_SWAP_TIMER(send,copy); - token = copy_struct(SEQ_TRACE_TOKEN(sender), - 6 /* TUPLE5 */, + token = copy_struct(stoken, + seq_trace_size, &hp, &bp->off_heap); message = copy_struct(message, msize, &hp, &bp->off_heap); +#ifdef HAVE_DTRACE + if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) { + utag = copy_struct(DT_UTAG(sender), dt_utag_size, &hp, &bp->off_heap); + erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) Spreading tag (%T) with message %T!\r\n",sender->id, utag, message); + } +#if 0 + DT_UTAG_FLAGS(sender) &= ~DT_UTAG_SPREADING; + if (!(DT_UTAG_FLAGS(sender) & DT_UTAG_PERMANENT)) { + erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) Killing tag!\r\n",sender->id); + DT_UTAG(sender) = NIL; + if (SEQ_TRACE_TOKEN(sender) == am_have_dt_utag) { + SEQ_TRACE_TOKEN(sender) = NIL; + } + } +#endif +#endif BM_MESSAGE_COPIED(msize); BM_SWAP_TIMER(copy,send); if (DTRACE_ENABLED(message_send)) { - Eterm token2 = NIL; - - token2 = SEQ_TRACE_TOKEN(sender); - tok_label = signed_val(SEQ_TRACE_T_LABEL(token2)); - tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token2)); - tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token2)); - DTRACE6(message_send, sender_name, receiver_name, - msize, tok_label, tok_lastcnt, tok_serial); + if (stoken != NIL) { + tok_label = signed_val(SEQ_TRACE_T_LABEL(stoken)); + tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(stoken)); + tok_serial = signed_val(SEQ_TRACE_T_SERIAL(stoken)); + } + DTRACE6(message_send, sender_name, receiver_name, + msize, tok_label, tok_lastcnt, tok_serial); } erts_queue_message(receiver, receiver_locks, bp, message, - token); + token +#ifdef HAVE_DTRACE + , utag +#endif + ); BM_SWAP_TIMER(send,system); #ifdef HYBRID } else { @@ -909,6 +1012,9 @@ erts_send_message(Process* sender, size_object(message)msize, tok_label, tok_lastcnt, tok_serial); ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = NIL; +#ifdef HAVE_DTRACE + ERL_MESSAGE_DT_UTAG(mp) = NIL; +#endif mp->next = NULL; LINK_MESSAGE(receiver, mp); ACTIVATE(receiver); @@ -951,6 +1057,9 @@ erts_send_message(Process* sender, mp->data.attached = NULL; ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = NIL; +#ifdef HAVE_DTRACE + ERL_MESSAGE_DT_UTAG(mp) = NIL; +#endif mp->next = NULL; /* * We move 'in queue' to 'private queue' and place @@ -984,7 +1093,11 @@ erts_send_message(Process* sender, BM_SWAP_TIMER(copy,send); DTRACE6(message_send, sender_name, receiver_name, msize, tok_label, tok_lastcnt, tok_serial); - erts_queue_message(receiver, receiver_locks, bp, message, token); + erts_queue_message(receiver, receiver_locks, bp, message, token +#ifdef HAVE_DTRACE + , NIL +#endif + ); BM_SWAP_TIMER(send,system); #else ErlMessage* mp = message_alloc(); @@ -1008,6 +1121,9 @@ erts_send_message(Process* sender, (uint32_t)msize, tok_label, tok_lastcnt, tok_serial); ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = NIL; +#ifdef HAVE_DTRACE + ERL_MESSAGE_DT_UTAG(mp) = NIL; +#endif mp->next = NULL; mp->data.attached = NULL; LINK_MESSAGE(receiver, mp); @@ -1046,7 +1162,11 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp, Eterm temptoken; ErlHeapFragment* bp = NULL; - if (token != NIL) { + if (token != NIL +#ifdef HAVE_DTRACE + && token != am_have_dt_utag +#endif + ) { ASSERT(is_tuple(token)); sz_reason = size_object(reason); @@ -1061,7 +1181,11 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp, /* the trace token must in this case be updated by the caller */ seq_trace_output(token, save, SEQ_TRACE_SEND, to->id, NULL); temptoken = copy_struct(token, sz_token, &hp, &bp->off_heap); - erts_queue_message(to, to_locksp, bp, save, temptoken); + erts_queue_message(to, to_locksp, bp, save, temptoken +#ifdef HAVE_DTRACE + , NIL +#endif + ); } else { ErlOffHeap *ohp; sz_reason = size_object(reason); @@ -1078,7 +1202,11 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp, ? from : copy_struct(from, sz_from, &hp, ohp)); save = TUPLE3(hp, am_EXIT, from_copy, mess); - erts_queue_message(to, to_locksp, bp, save, NIL); + erts_queue_message(to, to_locksp, bp, save, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); } } diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h index 5aca0db6fe..98321dd2c6 100644 --- a/erts/emulator/beam/erl_message.h +++ b/erts/emulator/beam/erl_message.h @@ -70,11 +70,18 @@ typedef struct erl_mesg { ErlHeapFragment *heap_frag; void *attached; } data; +#ifdef HAVE_DTRACE + Eterm m[3]; /* m[0] = message, m[1] = seq trace token, m[3] = dynamic trace user tag */ +#else Eterm m[2]; /* m[0] = message, m[1] = seq trace token */ +#endif } ErlMessage; #define ERL_MESSAGE_TERM(mp) ((mp)->m[0]) #define ERL_MESSAGE_TOKEN(mp) ((mp)->m[1]) +#ifdef HAVE_DTRACE +#define ERL_MESSAGE_DT_UTAG(mp) ((mp)->m[2]) +#endif /* Size of default message buffer (erl_message.c) */ #define ERL_MESSAGE_BUF_SZ 500 @@ -221,7 +228,11 @@ ErlHeapFragment* erts_resize_message_buffer(ErlHeapFragment *, Uint, Eterm *, Uint); void free_message_buffer(ErlHeapFragment *); void erts_queue_dist_message(Process*, ErtsProcLocks*, ErtsDistExternal *, Eterm); -void erts_queue_message(Process*, ErtsProcLocks*, ErlHeapFragment*, Eterm, Eterm); +void erts_queue_message(Process*, ErtsProcLocks*, ErlHeapFragment*, Eterm, Eterm +#ifdef HAVE_DTRACE + , Eterm dt_utag +#endif +); void erts_deliver_exit_message(Eterm, Process*, ErtsProcLocks *, Eterm, Eterm); void erts_send_message(Process*, Process*, ErtsProcLocks*, Eterm, unsigned); void erts_link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp); diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index dc4049327d..ebc771b016 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -351,7 +351,11 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, if (flush_me) { flush_env(env); /* Needed for ERTS_HOLE_CHECK */ } - erts_queue_message(rp, &rp_locks, frags, msg, am_undefined); + erts_queue_message(rp, &rp_locks, frags, msg, am_undefined +#ifdef HAVE_DTRACE + , NIL +#endif + ); if (rp_locks) { ERTS_SMP_LC_ASSERT(rp_locks == (rp_had_locks | (ERTS_PROC_LOCK_MSGQ | ERTS_PROC_LOCK_STATUS))); diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 1173624f51..6771e00c7e 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -679,7 +679,11 @@ reply_sched_wall_time(void *vswtrp) hpp = &hp; } - erts_queue_message(rp, &rp_locks, bp, msg, NIL); + erts_queue_message(rp, &rp_locks, bp, msg, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); if (swtrp->req_sched == esdp->no) rp_locks &= ~ERTS_PROC_LOCK_MAIN; @@ -7260,6 +7264,10 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). p->seq_trace_lastcnt = 0; p->seq_trace_clock = 0; SEQ_TRACE_TOKEN(p) = NIL; +#ifdef HAVE_DTRACE + DT_UTAG(p) = NIL; + DT_UTAG_FLAGS(p) = 0; +#endif p->parent = parent->id == ERTS_INVALID_PID ? NIL : parent->id; #ifdef HYBRID @@ -7851,7 +7859,11 @@ static ERTS_INLINE void send_exit_message(Process *to, ErtsProcLocks *to_locksp, Eterm exit_term, Uint term_size, Eterm token) { - if (token == NIL) { + if (token == NIL +#ifdef HAVE_DTRACE + || token == am_have_dt_utag +#endif + ) { Eterm* hp; Eterm mess; ErlHeapFragment* bp; @@ -7859,7 +7871,11 @@ send_exit_message(Process *to, ErtsProcLocks *to_locksp, hp = erts_alloc_message_heap(term_size, &bp, &ohp, to, to_locksp); mess = copy_struct(exit_term, term_size, &hp, ohp); - erts_queue_message(to, to_locksp, bp, mess, NIL); + erts_queue_message(to, to_locksp, bp, mess, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); } else { ErlHeapFragment* bp; Eterm* hp; @@ -7875,7 +7891,11 @@ send_exit_message(Process *to, ErtsProcLocks *to_locksp, /* the trace token must in this case be updated by the caller */ seq_trace_output(token, mess, SEQ_TRACE_SEND, to->id, NULL); temp_token = copy_struct(token, sz_token, &hp, &bp->off_heap); - erts_queue_message(to, to_locksp, bp, mess, temp_token); + erts_queue_message(to, to_locksp, bp, mess, temp_token +#ifdef HAVE_DTRACE + , NIL +#endif + ); } } @@ -7981,7 +8001,11 @@ send_exit_signal(Process *c_p, /* current process if and only if (ERTS_PROC_IS_TRAPPING_EXITS(rp) && (reason != am_kill || (flags & ERTS_XSIG_FLG_IGN_KILL))) { - if (is_not_nil(token) && token_update) + if (is_not_nil(token) +#ifdef HAVE_DTRACE + && token != am_have_dt_utag +#endif + && token_update) seq_trace_update_send(token_update); if (is_value(exit_tuple)) send_exit_message(rp, rp_locks, exit_tuple, exit_tuple_sz, token); diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index d671638ce8..35b31b1009 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -683,6 +683,10 @@ struct process { Uint seq_trace_lastcnt; Eterm seq_trace_token; /* Sequential trace token (tuple size 5 see below) */ +#ifdef HAVE_DTRACE + Eterm dt_utag; /* Place to store the dynamc trace user tag */ + Uint dt_utag_flags; /* flag field for the dt_utag */ +#endif BeamInstr initial[3]; /* Initial module(0), function(1), arity(2), often used instead of pointer to funcinfo instruction, hence the BeamInstr datatype */ BeamInstr* current; /* Current Erlang function, part of the funcinfo: @@ -998,6 +1002,14 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags; #define SEQ_TRACE_PRINT (1 << 2) #define SEQ_TRACE_TIMESTAMP (1 << 3) +#ifdef HAVE_DTRACE +#define DT_UTAG_PERMANENT (1 << 0) +#define DT_UTAG_SPREADING (1 << 1) +#define DT_UTAG(P) ((P)->dt_utag) +#define DT_UTAG_FLAGS(P) ((P)->dt_utag_flags) +#endif + + #ifdef ERTS_SMP /* Status flags ... */ #define ERTS_PROC_SFLG_PENDADD2SCHEDQ (((Uint32) 1) << 0) /* Pending diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index b1d1e1d9b0..a4aed0122b 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -125,8 +125,13 @@ do { \ enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE, (FPID), (TPID), (MSG), (BP)); \ } while(0) #else +#ifdef HAVE_DTRACE #define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \ - erts_queue_message((TPROC), NULL, (BP), (MSG), NIL) + erts_queue_message((TPROC), NULL, (BP), (MSG), NIL, NIL) +#else +#define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \ + erts_queue_message((TPROC), NULL, (BP), (MSG), NIL) +#endif #endif /* @@ -583,7 +588,11 @@ profile_send(Eterm from, Eterm message) { hp = erts_alloc_message_heap(sz, &bp, &off_heap, profile_p, 0); msg = copy_struct(message, sz, &hp, &bp->off_heap); - erts_queue_message(profile_p, NULL, bp, msg, NIL); + erts_queue_message(profile_p, NULL, bp, msg, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); } } @@ -994,9 +1003,13 @@ seq_trace_update_send(Process *p) { Eterm seq_tracer = erts_get_system_seq_tracer(); ASSERT((is_tuple(SEQ_TRACE_TOKEN(p)) || is_nil(SEQ_TRACE_TOKEN(p)))); - if ( (p->id == seq_tracer) || (SEQ_TRACE_TOKEN(p) == NIL)) + if ( (p->id == seq_tracer) || (SEQ_TRACE_TOKEN(p) == NIL) +#ifdef HAVE_DTRACE + || (SEQ_TRACE_TOKEN(p) == am_have_dt_utag) +#endif + ) { return 0; - + } SEQ_TRACE_TOKEN_SENDER(p) = p->id; /* Internal pid */ SEQ_TRACE_TOKEN_SERIAL(p) = make_small(++(p -> seq_trace_clock)); @@ -1178,7 +1191,11 @@ seq_trace_output_generic(Eterm token, Eterm msg, Uint type, enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SEQTRACE, NIL, NIL, mess, bp); erts_smp_mtx_unlock(&smq_mtx); #else - erts_queue_message(tracer, NULL, bp, mess, NIL); /* trace_token must be NIL here */ + erts_queue_message(tracer, NULL, bp, mess, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); /* trace_token must be NIL here */ #endif } } @@ -2469,7 +2486,11 @@ monitor_long_gc(Process *p, Uint time) { #ifdef ERTS_SMP enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp); #else - erts_queue_message(monitor_p, NULL, bp, msg, NIL); + erts_queue_message(monitor_p, NULL, bp, msg, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); #endif } @@ -2541,7 +2562,11 @@ monitor_large_heap(Process *p) { #ifdef ERTS_SMP enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp); #else - erts_queue_message(monitor_p, NULL, bp, msg, NIL); + erts_queue_message(monitor_p, NULL, bp, msg, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); #endif } @@ -2571,7 +2596,11 @@ monitor_generic(Process *p, Eterm type, Eterm spec) { #ifdef ERTS_SMP enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp); #else - erts_queue_message(monitor_p, NULL, bp, msg, NIL); + erts_queue_message(monitor_p, NULL, bp, msg, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); #endif } @@ -3357,7 +3386,11 @@ sys_msg_dispatcher_func(void *unused) } else { queue_proc_msg: - erts_queue_message(proc,&proc_locks,smqp->bp,smqp->msg,NIL); + erts_queue_message(proc,&proc_locks,smqp->bp,smqp->msg,NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); #ifdef DEBUG_PRINTOUTS erts_fprintf(stderr, "delivered\n"); #endif diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 81f79b8f85..75ea53c2b7 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -1564,7 +1564,11 @@ deliver_result(Eterm sender, Eterm pid, Eterm res) hp = erts_alloc_message_heap(sz_res + 3, &bp, &ohp, rp, &rp_locks); res = copy_struct(res, sz_res, &hp, ohp); tuple = TUPLE2(hp, sender, res); - erts_queue_message(rp, &rp_locks, bp, tuple, NIL); + erts_queue_message(rp, &rp_locks, bp, tuple, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); erts_smp_proc_unlock(rp, rp_locks); erts_smp_proc_dec_refc(rp); } @@ -1653,7 +1657,11 @@ static void deliver_read_message(Port* prt, Eterm to, tuple = TUPLE2(hp, prt->id, tuple); hp += 3; - erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined); + erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined +#ifdef HAVE_DTRACE + , NIL +#endif + ); erts_smp_proc_unlock(rp, rp_locks); erts_smp_proc_dec_refc(rp); } @@ -1806,7 +1814,11 @@ deliver_vec_message(Port* prt, /* Port */ tuple = TUPLE2(hp, prt->id, tuple); hp += 3; - erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined); + erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined +#ifdef HAVE_DTRACE + , NIL +#endif + ); erts_smp_proc_unlock(rp, rp_locks); erts_smp_proc_dec_refc(rp); } @@ -2772,7 +2784,11 @@ void driver_report_exit(int ix, int status) hp += 3; tuple = TUPLE2(hp, prt->id, tuple); - erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined); + erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined +#ifdef HAVE_DTRACE + , NIL +#endif + ); erts_smp_proc_unlock(rp, rp_locks); erts_smp_proc_dec_refc(rp); @@ -3322,7 +3338,11 @@ driver_deliver_term(ErlDrvPort port, HRelease(rp, hp_end, hp); } /* send message */ - erts_queue_message(rp, &rp_locks, bp, mess, am_undefined); + erts_queue_message(rp, &rp_locks, bp, mess, am_undefined +#ifdef HAVE_DTRACE + , NIL +#endif + ); } else { if (b2t.ix > b2t.used) diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index 49b6618f73..2efcd19162 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -1697,7 +1697,11 @@ static int do_send_to_logger(Eterm tag, Eterm gleader, char *buf, int len) erts_queue_error_logger_message(from, tuple3, bp); } #else - erts_queue_message(p, NULL /* only used for smp build */, bp, tuple3, NIL); + erts_queue_message(p, NULL /* only used for smp build */, bp, tuple3, NIL +#ifdef HAVE_DTRACE + , NIL +#endif + ); #endif return 0; } diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 293f024e45..62b582f76a 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -100,7 +100,7 @@ #endif #include -// Need (NON)BLOCKING macros for sendfile +/* Need (NON)BLOCKING macros for sendfile */ #ifndef WANT_NONBLOCKING #define WANT_NONBLOCKING #endif @@ -112,7 +112,7 @@ #include "erl_threads.h" #include "zlib.h" #include "gzio.h" -#include "dtrace-wrapper.h" +#include "dtrace-wrapper.h" #include #include @@ -149,10 +149,6 @@ 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) #define DTRACE_INVOKE_SETUP_BY_NAME(op) do {} while (0) #define DTRACE_INVOKE_RETURN(op) do {} while (0) @@ -212,6 +208,9 @@ typedef struct { #ifdef FILENAMES_16BIT +#ifdef HAVE_DTRACE +#error 16bit characters in filenames and dtrace in combination is not supported. +#endif # define FILENAME_BYTELEN(Str) filename_len_16bit(Str) # define FILENAME_COPY(To,From) filename_cpy_16bit((To),(From)) # define FILENAME_CHARSIZE 2 @@ -432,8 +431,6 @@ struct t_data int sched_i1; Uint64 sched_i2; char sched_utag[DTRACE_EFILE_BUFSIZ+1]; -#else - char sched_utag[1]; #endif int result_ok; Efile_error errInfo; @@ -2027,8 +2024,11 @@ static void cq_execute(file_descriptor *desc) { } static struct t_data *async_write(file_descriptor *desc, int *errp, - int reply, Uint32 reply_size, - Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3) { + int reply, Uint32 reply_size +#ifdef HAVE_DTRACE + ,Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3 +#endif +) { struct t_data *d; if (! (d = EF_ALLOC(sizeof(struct t_data) - 1))) { if (errp) *errp = ENOMEM; @@ -2041,11 +2041,13 @@ static struct t_data *async_write(file_descriptor *desc, int *errp, d->c.writev.port = desc->port; d->c.writev.q_mtx = desc->q_mtx; d->c.writev.size = desc->write_buffered; +#ifdef HAVE_DTRACE if (dt_i1 != NULL) { *dt_i1 = d->fd; *dt_i2 = d->flags; *dt_i3 = d->c.writev.size; } +#endif d->reply = reply; d->c.writev.free_size = 0; d->c.writev.reply_size = reply_size; @@ -2057,16 +2059,24 @@ static struct t_data *async_write(file_descriptor *desc, int *errp, return d; } -static int flush_write(file_descriptor *desc, int *errp, - dt_private *dt_priv, char *dt_utag) { +static int flush_write(file_descriptor *desc, int *errp +#ifdef HAVE_DTRACE + , dt_private *dt_priv, char *dt_utag +#endif +) { int result = 0; +#ifdef HAVE_DTRACE Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; +#endif struct t_data *d = NULL; MUTEX_LOCK(desc->q_mtx); if (desc->write_buffered > 0) { - if ((d = async_write(desc, errp, 0, 0, - &dt_i1, &dt_i2, &dt_i3)) == NULL) { + if ((d = async_write(desc, errp, 0, 0 +#ifdef HAVE_DTRACE + ,&dt_i1, &dt_i2, &dt_i3 +#endif + )) == NULL) { result = -1; } } @@ -2101,10 +2111,17 @@ static int check_write_error(file_descriptor *desc, int *errp) { return 0; } -static int flush_write_check_error(file_descriptor *desc, int *errp, - dt_private *dt_priv, char *dt_utag) { +static int flush_write_check_error(file_descriptor *desc, int *errp +#ifdef HAVE_DTRACE + , dt_private *dt_priv, char *dt_utag +#endif + ) { int r; - if ( (r = flush_write(desc, errp, dt_priv, dt_utag)) != 0) { + if ( (r = flush_write(desc, errp +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + )) != 0) { check_write_error(desc, NULL); return r; } else { @@ -2113,8 +2130,11 @@ static int flush_write_check_error(file_descriptor *desc, int *errp, } static struct t_data *async_lseek(file_descriptor *desc, int *errp, int reply, - Sint64 offset, int origin, - Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3) { + Sint64 offset, int origin +#ifdef HAVE_DTRACE + , Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3 +#endif + ) { struct t_data *d; if (! (d = EF_ALLOC(sizeof(struct t_data)))) { *errp = ENOMEM; @@ -2126,11 +2146,13 @@ static struct t_data *async_lseek(file_descriptor *desc, int *errp, int reply, d->reply = reply; d->c.lseek.offset = offset; d->c.lseek.origin = origin; +#ifdef HAVE_DTRACE if (dt_i1 != NULL) { *dt_i1 = d->fd; *dt_i2 = d->c.lseek.offset; *dt_i3 = d->c.lseek.origin; } +#endif d->invoke = invoke_lseek; d->free = free_data; d->level = 1; @@ -2147,18 +2169,26 @@ static void flush_read(file_descriptor *desc) { } } -static int lseek_flush_read(file_descriptor *desc, int *errp, - dt_private *dt_priv, char *dt_utag) { +static int lseek_flush_read(file_descriptor *desc, int *errp +#ifdef HAVE_DTRACE + ,dt_private *dt_priv, char *dt_utag +#endif + ) { int r = 0; size_t read_size = desc->read_size; +#ifdef HAVE_DTRACE Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; +#endif struct t_data *d; flush_read(desc); if (read_size != 0) { if ((d = async_lseek(desc, errp, 0, - -((ssize_t)read_size), EFILE_SEEK_CUR, - &dt_i1, &dt_i2, &dt_i3)) == NULL) { + -((ssize_t)read_size), EFILE_SEEK_CUR +#ifdef HAVE_DTRACE + , &dt_i1, &dt_i2, &dt_i3 +#endif + )) == NULL) { r = -1; } else { #ifdef HAVE_DTRACE @@ -2490,13 +2520,13 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) char* name; /* Points to the filename in buf. */ int command; struct t_data *d = NULL; - 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 + char *dt_utag = NULL; + char *dt_s1 = NULL, *dt_s2 = NULL; + Sint64 dt_i1 = 0; + Sint64 dt_i2 = 0; + Sint64 dt_i3 = 0; + Sint64 dt_i4 = 0; dt_private *dt_priv = get_dt_private(0); #endif /* HAVE_DTRACE */ @@ -2513,8 +2543,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_mkdir; d->free = free_data; @@ -2526,8 +2558,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_rmdir; d->free = free_data; @@ -2539,8 +2573,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_delete_file; d->free = free_data; @@ -2557,10 +2593,12 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); - dt_s1 = d->b; FILENAME_COPY(d->b + namelen, new_name); +#ifdef HAVE_DTRACE + dt_s1 = d->b; dt_s2 = d->b + namelen; - dt_utag = buf + namelen + strlen(dt_s2) + 1; + dt_utag = buf + namelen + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->flags = desc->flags; d->fd = fd; d->command = command; @@ -2574,8 +2612,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_chdir; d->free = free_data; @@ -2587,7 +2627,9 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); d->drive = *(uchar*)buf; +#ifdef HAVE_DTRACE dt_utag = buf + 1; +#endif d->command = command; d->invoke = invoke_pwd; d->free = free_data; @@ -2603,8 +2645,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->dir_handle = NULL; d->command = command; d->invoke = invoke_readdir; @@ -2629,9 +2673,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) dir_handle = NULL; resbuf[0] = FILE_RESP_LFNAME; +#ifdef HAVE_DTRACE dt_s1 = name; - dt_utag = name + strlen(dt_s1) + 1; - + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif /* Fill the buffer with multiple directory listings before sending it to the * receiving process. READDIR_CHUNKS is minimum number of files sent to the * receiver. @@ -2680,11 +2725,13 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_CHARSIZE); d->flags = get_int32((uchar*)buf); - dt_i1 = d->flags; name = buf+4; FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE + dt_i1 = d->flags; dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_open; d->free = free_data; @@ -2696,9 +2743,11 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data)); - dt_utag = name; d->fd = fd; +#ifdef HAVE_DTRACE + dt_utag = name; dt_i1 = fd; +#endif d->command = command; d->invoke = invoke_fdatasync; d->free = free_data; @@ -2710,9 +2759,11 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data)); - dt_utag = name; d->fd = fd; +#ifdef HAVE_DTRACE + dt_utag = name; dt_i1 = fd; +#endif d->command = command; d->invoke = invoke_fsync; d->free = free_data; @@ -2728,13 +2779,15 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); - dt_utag = name + strlen(d->b) + 1; d->fd = fd; +#ifdef HAVE_DTRACE + dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; if (command == FILE_LSTAT) { dt_s1 = d->b; } else { dt_i1 = fd; } +#endif d->command = command; d->invoke = invoke_flstat; d->free = free_data; @@ -2746,11 +2799,13 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data)); - dt_utag = name; d->flags = desc->flags; d->fd = fd; +#ifdef HAVE_DTRACE + dt_utag = name; dt_i1 = fd; dt_i2 = d->flags; +#endif d->command = command; d->invoke = invoke_truncate; d->free = free_data; @@ -2764,18 +2819,20 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(buf + 9*4) + FILENAME_CHARSIZE); d->info.mode = get_int32(buf + 0 * 4); - dt_i1 = d->info.mode; d->info.uid = get_int32(buf + 1 * 4); - dt_i2 = d->info.uid; d->info.gid = get_int32(buf + 2 * 4); - dt_i3 = d->info.gid; d->info.accessTime = (time_t)((Sint64)get_int64(buf + 3 * 4)); d->info.modifyTime = (time_t)((Sint64)get_int64(buf + 5 * 4)); d->info.cTime = (time_t)((Sint64)get_int64(buf + 7 * 4)); FILENAME_COPY(d->b, buf + 9*4); +#ifdef HAVE_DTRACE + dt_i1 = d->info.mode; + dt_i2 = d->info.uid; + dt_i3 = d->info.gid; dt_s1 = d->b; - dt_utag = buf + 9 * 4 + strlen(d->b) + 1; + dt_utag = buf + 9 * 4 + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_write_info; d->free = free_data; @@ -2788,8 +2845,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_readlink; d->free = free_data; @@ -2801,8 +2860,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_altname; d->free = free_data; @@ -2822,10 +2883,12 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); - dt_s1 = d->b; FILENAME_COPY(d->b + namelen, new_name); +#ifdef HAVE_DTRACE + dt_s1 = d->b; dt_s2 = d->b + namelen; - dt_utag = buf + namelen + strlen(dt_s2) + 1; + dt_utag = buf + namelen + FILENAME_BYTELEN(dt_s2) + FILENAME_CHARSIZE; +#endif d->flags = desc->flags; d->fd = fd; d->command = command; @@ -2846,10 +2909,12 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); - dt_s1 = d->b; FILENAME_COPY(d->b + namelen, new_name); +#ifdef HAVE_DTRACE + dt_s1 = d->b; dt_s2 = d->b + namelen; - dt_utag = buf + namelen + strlen(dt_s2) + 1; + dt_utag = buf + namelen + FILENAME_BYTELEN(dt_s2) + FILENAME_CHARSIZE; +#endif d->flags = desc->flags; d->fd = fd; d->command = command; @@ -2864,18 +2929,20 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data)); d->fd = fd; - dt_i1 = d->fd; d->command = command; d->invoke = invoke_fadvise; d->free = free_data; d->level = 2; d->c.fadvise.offset = get_int64((uchar*) buf); - dt_i2 = d->c.fadvise.offset; d->c.fadvise.length = get_int64(((uchar*) buf) + sizeof(Sint64)); - dt_i3 = d->c.fadvise.length; d->c.fadvise.advise = get_int32(((uchar*) buf) + 2 * sizeof(Sint64)); +#ifdef HAVE_DTRACE + dt_i1 = d->fd; + dt_i2 = d->c.fadvise.offset; + dt_i3 = d->c.fadvise.length; dt_i4 = d->c.fadvise.advise; dt_utag = buf + 3 * sizeof(Sint64); +#endif goto done; } @@ -2920,8 +2987,6 @@ file_flush(ErlDrvData e) { #endif #ifdef HAVE_DTRACE dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); -#else - dt_private *dt_priv = NULL; #endif TRACE_C('f'); @@ -2933,8 +2998,11 @@ file_flush(ErlDrvData e) { #ifdef DEBUG r = #endif - flush_write(desc, NULL, dt_priv, - (desc->d == NULL) ? NULL : desc->d->sched_utag); + flush_write(desc, NULL +#ifdef HAVE_DTRACE + , dt_priv, (desc->d == NULL) ? NULL : desc->d->sched_utag +#endif + ); /* Only possible reason for bad return value is ENOMEM, and * there is nobody to tell... */ @@ -2978,8 +3046,6 @@ file_timeout(ErlDrvData e) { enum e_timer timer_state = desc->timer_state; #ifdef HAVE_DTRACE dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); -#else - dt_private *dt_priv = NULL; #endif TRACE_C('t'); @@ -2998,8 +3064,11 @@ file_timeout(ErlDrvData e) { #ifdef DEBUG int r = #endif - flush_write(desc, NULL, dt_priv, - (desc->d == NULL) ? NULL : desc->d->sched_utag); + flush_write(desc, NULL +#ifdef HAVE_DTRACE + , dt_priv, (desc->d == NULL) ? NULL : desc->d->sched_utag +#endif + ); /* Only possible reason for bad return value is ENOMEM, and * there is nobody to tell... */ @@ -3021,15 +3090,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { int p, q; int err; struct t_data *d = NULL; +#ifdef HAVE_DTRACE Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; - ERTS_DECLARE_DUMMY(Sint64 dt_i4) = 0; + Sint64 dt_i4 = 0; char *dt_utag = NULL; - ERTS_DECLARE_DUMMY(char *dt_s1) = NULL; -#ifdef HAVE_DTRACE + char *dt_s1 = NULL; dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); -#else - dt_private *dt_priv = NULL; #endif + TRACE_C('v'); p = 0; q = 1; @@ -3048,9 +3116,15 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { switch (command) { case FILE_CLOSE: { +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); +#endif flush_read(desc); - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } @@ -3061,9 +3135,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; dt_i2 = d->flags; +#endif d->invoke = invoke_close; d->free = free_data; d->level = 2; @@ -3086,8 +3162,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } @@ -3095,7 +3177,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { if (desc->read_bufsize == 0 && desc->read_binp != NULL && desc->read_size > 0) { /* We have allocated a buffer for line mode but should not really have a read-ahead buffer... */ - if (lseek_flush_read(desc, &err, dt_priv) < 0) { + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } @@ -3171,14 +3257,16 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; - dt_i2 = d->flags; d->c.read.binp = desc->read_binp; d->c.read.bin_offset = desc->read_offset + desc->read_size; d->c.read.bin_size = desc->read_binp->orig_size - d->c.read.bin_offset; d->c.read.size = size; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; + dt_i2 = d->flags; dt_i3 = d->c.read.size; +#endif driver_binary_inc_refc(d->c.read.binp); d->invoke = invoke_read; d->free = free_read; @@ -3196,12 +3284,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { * allocated binary + dealing with offsets and lengts are done in file_async ready * for this OP. */ +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (ev->size != 1+strlen(dt_utag)+1) { + if (ev->size != 1 +#ifdef HAVE_DTRACE + + FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE +#endif + ) { /* Wrong command length */ reply_posix_error(desc, EINVAL); goto done; @@ -3253,41 +3351,43 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; - dt_i2 = d->flags; d->c.read_line.binp = desc->read_binp; d->c.read_line.read_offset = desc->read_offset; d->c.read_line.read_size = desc->read_size; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; + dt_i2 = d->flags; dt_i3 = d->c.read_line.read_offset; +#endif #if !ALWAYS_READ_LINE_AHEAD d->c.read_line.read_ahead = (desc->read_bufsize > 0); -#endif +#ifdef HAVE_DTRACE dt_i4 = d->c.read_line.read_ahead; +#endif +#endif driver_binary_inc_refc(d->c.read.binp); d->invoke = invoke_read_line; d->free = free_read_line; d->level = 1; cq_enq(desc, d); } goto done; - case FILE_WRITE: { + case FILE_WRITE: { /* Dtrace: The dtrace user tag is not last in message, + but follows the message tag directly. + This is handled specially in prim_file.erl */ ErlDrvSizeT skip = 1; ErlDrvSizeT size = ev->size - skip; +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); - skip += strlen(dt_utag) + 1; + skip += FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE; size = ev->size - skip; - /* - * Interesting dependency on using port # for key to async - * I/O worker pool thread: lseek_flush_read() can enqueue a - * lseek() op. If that lseek() were scheduled on a different - * thread than the write that we'll enqueue later in this case, - * then Bad Things could happen. This DTrace work is probably - * well worthwhile to get a sense of how often there's head-of- - * line blocking/unfairness during busy file I/O because of the - * mapping of port #/key -> thread. - */ - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } @@ -3314,8 +3414,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { driver_set_timer(desc->port, desc->write_delay); } } else { - if ((d = async_write(desc, &err, !0, size, - &dt_i1, &dt_i2, &dt_i3)) == NULL) { + if ((d = async_write(desc, &err, !0, size +#ifdef HAVE_DTRACE + , &dt_i1, &dt_i2, &dt_i3 +#endif + )) == NULL) { MUTEX_UNLOCK(desc->q_mtx); reply_posix_error(desc, err); goto done; @@ -3325,27 +3428,46 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } } goto done; /* case FILE_WRITE */ - case FILE_PWRITEV: { + case FILE_PWRITEV: { /* Dtrace: The dtrace user tag is not last in message, + but follows the message tag directly. + This is handled specially in prim_file.erl */ Uint32 i, j, n; size_t total; - char tmp; +#ifdef HAVE_DTRACE + char dt_tmp; int dt_utag_bytes = 1; dt_utag = EV_CHAR_P(ev, p, q); - while (EV_GET_CHAR(ev, &tmp, &p, &q) && tmp != '\0') { + /* This will work for UTF-8, but not for UTF-16 - extra reminder here */ +#ifdef FILENAMES_16BIT +#error 16bit characters in filenames and dtrace in combination is not supported. +#endif + while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0') { dt_utag_bytes++; } - if (ev->size < 1+4+dt_utag_bytes +#endif + if (ev->size < 1+4 +#ifdef HAVE_DTRACE + + dt_utag_bytes +#endif || !EV_GET_UINT32(ev, &n, &p, &q)) { /* Buffer too short to contain even the number of pos/size specs */ reply_Uint_posix_error(desc, 0, EINVAL); goto done; } - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_Uint_posix_error(desc, 0, err); goto done; } - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_Uint_posix_error(desc, 0, err); goto done; } @@ -3358,7 +3480,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } goto done; } - if (ev->size < 1+4+8*(2*n)+dt_utag_bytes) { + if (ev->size < 1+4+8*(2*n) +#ifdef HAVE_DTRACE + + dt_utag_bytes +#endif + ) { /* Buffer too short to contain even the pos/size specs */ reply_Uint_posix_error(desc, 0, EINVAL); goto done; @@ -3372,9 +3498,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; dt_i2 = d->flags; +#endif d->c.pwritev.port = desc->port; d->c.pwritev.q_mtx = desc->q_mtx; d->c.pwritev.n = n; @@ -3412,14 +3540,20 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } } d->c.pwritev.size = total; +#ifdef HAVE_DTRACE dt_i3 = d->c.pwritev.size; +#endif d->c.pwritev.free_size = 0; if (j == 0) { /* Trivial case - nothing to write */ EF_FREE(d); reply_Uint(desc, 0); } else { - ErlDrvSizeT skip = 1 + 4 + 8 * (2*n) + dt_utag_bytes; + ErlDrvSizeT skip = 1 + 4 + 8 * (2*n) +#ifdef HAVE_DTRACE + + dt_utag_bytes +#endif + ; if (skip + total != ev->size) { /* Actual amount of data does not match * total of all pos/size specs @@ -3440,33 +3574,55 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } } goto done; /* case FILE_PWRITEV: */ - case FILE_PREADV: { + case FILE_PREADV: { /* Dtrace: The dtrace user tag is not last in message, + but follows the message tag directly. + This is handled specially in prim_file.erl */ register void * void_ptr; Uint32 i, n; ErlIOVec *res_ev; - char tmp; +#ifdef HAVE_DTRACE + char dt_tmp; int dt_utag_bytes = 1; - + /* This will work for UTF-8, but not for UTF-16 - extra reminder here */ +#ifdef FILENAMES_16BIT +#error 16bit characters in filenames and dtrace in combination is not supported. +#endif dt_utag = EV_CHAR_P(ev, p, q); - while (EV_GET_CHAR(ev, &tmp, &p, &q) && tmp != '\0') { + while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0') { dt_utag_bytes++; } - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (ev->size < 1+8+dt_utag_bytes + if (ev->size < 1+8 +#ifdef HAVE_DTRACE + + dt_utag_bytes +#endif || !EV_GET_UINT32(ev, &n, &p, &q) || !EV_GET_UINT32(ev, &n, &p, &q)) { /* Buffer too short to contain even the number of pos/size specs */ reply_posix_error(desc, EINVAL); goto done; } - if (ev->size < 1+8+8*(2*n)+dt_utag_bytes) { + if (ev->size < 1+8+8*(2*n) +#ifdef HAVE_DTRACE + + dt_utag_bytes +#endif + ) { /* Buffer wrong length to contain the pos/size specs */ reply_posix_error(desc, EINVAL); goto done; @@ -3485,9 +3641,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; dt_i2 = d->flags; +#endif d->c.preadv.n = n; d->c.preadv.cnt = 0; d->c.preadv.size = 0; @@ -3515,7 +3673,9 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else size = ((size_t)sizeH<<32) | sizeL; #endif +#ifdef HAVE_DTRACE dt_i3 += size; +#endif if (! (res_ev->binv[i] = driver_alloc_binary(size))) { reply_posix_error(desc, ENOMEM); break; @@ -3572,17 +3732,30 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if ((d = async_lseek(desc, &err, !0, offset, origin, - &dt_i1, &dt_i2, &dt_i3)) == NULL) { + if ((d = async_lseek(desc, &err, !0, offset, origin +#ifdef HAVE_DTRACE + , &dt_i1, &dt_i2, &dt_i3 +#endif + )) == NULL) { reply_posix_error(desc, err); goto done; } @@ -3595,11 +3768,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, ENOENT); goto done; } +#ifndef HAVE_DTRACE + /* In the dtrace case, the iov has an extra element, the dtrace utag - we will need + another test to see that + the filename is in a single buffer: */ if (ev->size-1 != ev->iov[q].iov_len-p) { /* Name not in one single buffer */ reply_posix_error(desc, EINVAL); goto done; } +#else + if (((byte *)ev->iov[q].iov_base)[ev->iov[q].iov_len-1] != '\0') { + /* Name not in one single buffer */ + reply_posix_error(desc, EINVAL); + goto done; + } +#endif filename = EV_CHAR_P(ev, p, q); d = EF_ALLOC(sizeof(struct t_data) -1 + FILENAME_BYTELEN(filename) + FILENAME_CHARSIZE); if (! d) { @@ -3610,8 +3794,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->reply = !0; /* Copy name */ FILENAME_COPY(d->b, filename); - dt_s1 = d->b; - dt_utag = filename + strlen(d->b) + 1; +#ifdef HAVE_DTRACE + { + char dt_tmp; + + /* This will work for UTF-8, but not for UTF-16 - extra reminder here */ +#ifdef FILENAMES_16BIT +#error 16bit characters in filenames and dtrace in combination is not supported. +#endif + while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0') + ; + dt_s1 = d->b; + dt_utag = EV_CHAR_P(ev, p, q); + if (*dt_utag != 0) + fprintf(stderr,"dt_utag = %s\r\n",dt_utag); + } +#endif d->c.read_file.binp = NULL; d->invoke = invoke_read_file; d->free = free_read_file; @@ -3650,12 +3848,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } @@ -3672,13 +3880,15 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; - dt_i2 = d->flags; d->c.preadv.offsets[0] = hdr_offset; - dt_i3 = d->c.preadv.offsets[0]; d->c.preadv.size = max_size; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; + dt_i2 = d->flags; + dt_i3 = d->c.preadv.offsets[0]; dt_i4 = d->c.preadv.size; +#endif res_ev = &d->c.preadv.eiov; /* XXX possible alignment problems here for weird machines */ res_ev->iov = void_ptr = d + 1; @@ -3700,12 +3910,17 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } +#ifdef HAVE_DTRACE dt_i1 = opt; dt_utag = EV_CHAR_P(ev, p, q); +#endif switch (opt) { case FILE_OPT_DELAYED_WRITE: { Uint32 sizeH, sizeL, delayH, delayL; - if (ev->size != 1+1+4*sizeof(Uint32)+strlen(dt_utag)+1 + if (ev->size != 1+1+4*sizeof(Uint32) +#ifdef HAVE_DTRACE + + FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE +#endif || !EV_GET_UINT32(ev, &sizeH, &p, &q) || !EV_GET_UINT32(ev, &sizeL, &p, &q) || !EV_GET_UINT32(ev, &delayH, &p, &q) @@ -3732,13 +3947,18 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else desc->write_delay = ((unsigned long)delayH << 32) | delayL; #endif +#ifdef HAVE_DTRACE dt_i2 = desc->write_delay; +#endif TRACE_C('K'); reply_ok(desc); } goto done; case FILE_OPT_READ_AHEAD: { Uint32 sizeH, sizeL; - if (ev->size != 1+1+2*sizeof(Uint32)+strlen(dt_utag)+1 + if (ev->size != 1+1+2*sizeof(Uint32) +#ifdef HAVE_DTRACE + + FILENAME_BYTELEN(dt_utag)+FILENAME_CHARSIZE +#endif || !EV_GET_UINT32(ev, &sizeH, &p, &q) || !EV_GET_UINT32(ev, &sizeL, &p, &q)) { /* Buffer has wrong length to contain the option values */ @@ -3754,7 +3974,9 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else desc->read_bufsize = ((size_t)sizeH << 32) | sizeL; #endif +#ifdef HAVE_DTRACE dt_i2 = desc->read_bufsize; +#endif TRACE_C('K'); reply_ok(desc); } goto done; @@ -3841,11 +4063,19 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } /* switch(command) */ - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } else { -- cgit v1.2.3 From cca350ef2206a81c0f8969071f412f07b87413a1 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Fri, 2 Mar 2012 18:41:17 +0100 Subject: Change to more specific configure options for dtrace --- erts/emulator/beam/beam_emu.c | 35 +++-- erts/emulator/beam/bif.c | 60 ++++++--- erts/emulator/beam/dist.c | 10 +- erts/emulator/beam/dtrace-wrapper.h | 6 +- erts/emulator/beam/erl_alloc.c | 2 +- erts/emulator/beam/erl_bif_ddll.c | 2 +- erts/emulator/beam/erl_bif_info.c | 2 +- erts/emulator/beam/erl_bif_timer.c | 2 +- erts/emulator/beam/erl_bif_trace.c | 12 +- erts/emulator/beam/erl_db_util.c | 4 +- erts/emulator/beam/erl_gc.c | 6 +- erts/emulator/beam/erl_lock_check.c | 2 +- erts/emulator/beam/erl_message.c | 70 +++++----- erts/emulator/beam/erl_message.h | 6 +- erts/emulator/beam/erl_nif.c | 2 +- erts/emulator/beam/erl_process.c | 12 +- erts/emulator/beam/erl_process.h | 4 +- erts/emulator/beam/erl_trace.c | 16 +-- erts/emulator/beam/io.c | 10 +- erts/emulator/beam/utils.c | 2 +- erts/emulator/drivers/common/efile_drv.c | 214 +++++++++++++++---------------- 21 files changed, 255 insertions(+), 224 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index deeb7357d6..763d15e101 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -1051,7 +1051,7 @@ init_emulator(void) # define REG_tmp_arg2 #endif -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES #define DTRACE_CALL(p, m, f, a) \ if (DTRACE_ENABLED(function_entry)) { \ @@ -1111,7 +1111,7 @@ init_emulator(void) DTRACE2(nif_return, process_name, mfa); \ } -#else /* HAVE_DTRACE */ +#else /* USE_VM_PROBES */ #define DTRACE_CALL(p, m, f, a) do {} while (0) #define DTRACE_RETURN(p, m, f, a) do {} while (0) @@ -1120,7 +1120,7 @@ init_emulator(void) #define DTRACE_NIF_ENTRY(p, m, f, a) do {} while (0) #define DTRACE_NIF_RETURN(p, m, f, a) do {} while (0) -#endif /* HAVE_DTRACE */ +#endif /* USE_VM_PROBES */ void dtrace_drvport_str(ErlDrvPort drvport, char *port_buf) @@ -1892,34 +1892,49 @@ void process_main(void) save_calls(c_p, &exp_receive); } if (ERL_MESSAGE_TOKEN(msgp) == NIL) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES if (DT_UTAG(c_p) != NIL) { if (DT_UTAG_FLAGS(c_p) & DT_UTAG_PERMANENT) { SEQ_TRACE_TOKEN(c_p) = am_have_dt_utag; +#ifdef DTRACE_TAG_HARDDEBUG if (DT_UTAG_FLAGS(c_p) & DT_UTAG_SPREADING) - erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) stop spreading tag %T with message %T\r\n",c_p->id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp)); + erts_fprintf(stderr, + "Dtrace -> (%T) stop spreading " + "tag %T with message %T\r\n", + c_p->id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp)); +#endif } else { - erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) kill tag %T with message %T\r\n",c_p->id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp)); +#ifdef DTRACE_TAG_HARDDEBUG + erts_fprintf(stderr, + "Dtrace -> (%T) kill tag %T with " + "message %T\r\n", + c_p->id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp)); +#endif DT_UTAG(c_p) = NIL; SEQ_TRACE_TOKEN(c_p) = NIL; } } else { #endif SEQ_TRACE_TOKEN(c_p) = NIL; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES } DT_UTAG_FLAGS(c_p) &= ~DT_UTAG_SPREADING; #endif } else if (ERL_MESSAGE_TOKEN(msgp) != am_undefined) { Eterm msg; SEQ_TRACE_TOKEN(c_p) = ERL_MESSAGE_TOKEN(msgp); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES if (ERL_MESSAGE_TOKEN(msgp) == am_have_dt_utag) { if (DT_UTAG(c_p) == NIL) { DT_UTAG(c_p) = ERL_MESSAGE_DT_UTAG(msgp); } DT_UTAG_FLAGS(c_p) |= DT_UTAG_SPREADING; - erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) receive tag (%T) with message %T\r\n",c_p->id, DT_UTAG(c_p), ERL_MESSAGE_TERM(msgp)); +#ifdef DTRACE_TAG_HARDDEBUG + erts_fprintf(stderr, + "Dtrace -> (%T) receive tag (%T) " + "with message %T\r\n", + c_p->id, DT_UTAG(c_p), ERL_MESSAGE_TERM(msgp)); +#endif } else { #endif ASSERT(is_tuple(SEQ_TRACE_TOKEN(c_p))); @@ -1935,7 +1950,7 @@ void process_main(void) msg = ERL_MESSAGE_TERM(msgp); seq_trace_output(SEQ_TRACE_TOKEN(c_p), msg, SEQ_TRACE_RECEIVE, c_p->id, c_p); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES } #endif } diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 6478e54996..2adc713959 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -564,7 +564,7 @@ erts_queue_monitor_message(Process *p, tup = TUPLE5(hp, am_DOWN, ref_copy, type, item_copy, reason_copy); erts_queue_message(p, p_locksp, bp, tup, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -1949,7 +1949,7 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend) { save_calls(p, &exp_send); if (SEQ_TRACE_TOKEN(p) != NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES && SEQ_TRACE_TOKEN(p) != am_have_dt_utag #endif ) { @@ -4234,7 +4234,7 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2) for (i = 0; i < erts_max_processes; i++) { if (process_tab[i] != (Process*) 0) { Process* p = process_tab[i]; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES p->seq_trace_token = (p->dt_utag != NIL) ? am_have_dt_utag : NIL; #else p->seq_trace_token = NIL; @@ -4244,7 +4244,7 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2) ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p); mp = p->msg.first; while(mp != NULL) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ERL_MESSAGE_TOKEN(mp) = (ERL_MESSAGE_DT_UTAG(mp) != NIL) ? am_have_dt_utag : NIL; #else ERL_MESSAGE_TOKEN(mp) = NIL; @@ -4649,7 +4649,7 @@ BIF_RETTYPE get_module_info_2(BIF_ALIST_2) BIF_RETTYPE put_utag_1(BIF_ALIST_1) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Eterm otag; if (BIF_ARG_1 == am_undefined) { otag = (DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P); @@ -4677,7 +4677,7 @@ BIF_RETTYPE put_utag_1(BIF_ALIST_1) BIF_RETTYPE get_utag_0(BIF_ALIST_0) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES BIF_RET((DT_UTAG(BIF_P) == NIL || !(DT_UTAG_FLAGS(BIF_P) & DT_UTAG_PERMANENT)) ? am_undefined : DT_UTAG(BIF_P)); #else BIF_RET(am_undefined); @@ -4685,7 +4685,7 @@ BIF_RETTYPE get_utag_0(BIF_ALIST_0) } BIF_RETTYPE get_utag_data_0(BIF_ALIST_0) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES BIF_RET((DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P)); #else BIF_RET(am_undefined); @@ -4693,7 +4693,7 @@ BIF_RETTYPE get_utag_data_0(BIF_ALIST_0) } BIF_RETTYPE prepend_vm_utag_data_1(BIF_ALIST_1) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Eterm b; Eterm *hp; hp = HAlloc(BIF_P,2); @@ -4720,7 +4720,7 @@ BIF_RETTYPE prepend_vm_utag_data_1(BIF_ALIST_1) } BIF_RETTYPE append_vm_utag_data_1(BIF_ALIST_1) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Eterm b; Eterm *hp; hp = HAlloc(BIF_P,2); @@ -4747,23 +4747,31 @@ BIF_RETTYPE append_vm_utag_data_1(BIF_ALIST_1) } BIF_RETTYPE spread_utag_1(BIF_ALIST_1) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Eterm ret; Eterm *hp; #endif if (BIF_ARG_1 != am_true && BIF_ARG_1 != am_false) { BIF_ERROR(BIF_P,BADARG); } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES hp = HAlloc(BIF_P,3); ret = TUPLE2(hp,make_small(DT_UTAG_FLAGS(BIF_P)),DT_UTAG(BIF_P)); if (DT_UTAG(BIF_P) != NIL) { if (BIF_ARG_1 == am_true) { DT_UTAG_FLAGS(BIF_P) |= DT_UTAG_SPREADING; - erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) start spreading tag %T\r\n",BIF_P->id,DT_UTAG(BIF_P)); +#ifdef DTRACE_TAG_HARDDEBUG + erts_fprintf(stderr, + "Dtrace -> (%T) start spreading tag %T\r\n", + BIF_P->id,DT_UTAG(BIF_P)); +#endif } else { DT_UTAG_FLAGS(BIF_P) &= ~DT_UTAG_SPREADING; - erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) stop spreading tag %T\r\n",BIF_P->id,DT_UTAG(BIF_P)); +#ifdef DTRACE_TAG_HARDDEBUG + erts_fprintf(stderr, + "Dtrace -> (%T) stop spreading tag %T\r\n", + BIF_P->id,DT_UTAG(BIF_P)); +#endif } } BIF_RET(ret); @@ -4773,7 +4781,7 @@ BIF_RETTYPE spread_utag_1(BIF_ALIST_1) } BIF_RETTYPE restore_utag_1(BIF_ALIST_1) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Eterm *tpl; Uint x; if (is_not_tuple(BIF_ARG_1)) { @@ -4785,7 +4793,11 @@ BIF_RETTYPE restore_utag_1(BIF_ALIST_1) } if (tpl[2] == NIL) { if (DT_UTAG(BIF_P) != NIL) { - erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) restore Killing tag!\r\n",BIF_P->id); +#ifdef DTRACE_TAG_HARDDEBUG + erts_fprintf(stderr, + "Dtrace -> (%T) restore Killing tag!\r\n", + BIF_P->id); +#endif } DT_UTAG(BIF_P) = NIL; if (SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag) { @@ -4794,11 +4806,21 @@ BIF_RETTYPE restore_utag_1(BIF_ALIST_1) DT_UTAG_FLAGS(BIF_P) = 0; } else { x = unsigned_val(tpl[1]) & (DT_UTAG_SPREADING | DT_UTAG_PERMANENT); - if (!(x & DT_UTAG_SPREADING) && (DT_UTAG_FLAGS(BIF_P) & DT_UTAG_SPREADING)) { - erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) restore stop spreading tag %T\r\n",BIF_P->id,tpl[2]); - } else if ((x & DT_UTAG_SPREADING) && !(DT_UTAG_FLAGS(BIF_P) & DT_UTAG_SPREADING)) { - erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) restore start spreading tag %T\r\n",BIF_P->id,tpl[2]); +#ifdef DTRACE_TAG_HARDDEBUG + + if (!(x & DT_UTAG_SPREADING) && (DT_UTAG_FLAGS(BIF_P) & + DT_UTAG_SPREADING)) { + erts_fprintf(stderr, + "Dtrace -> (%T) restore stop spreading " + "tag %T\r\n", + BIF_P->id, tpl[2]); + } else if ((x & DT_UTAG_SPREADING) && + !(DT_UTAG_FLAGS(BIF_P) & DT_UTAG_SPREADING)) { + erts_fprintf(stderr, + "Dtrace -> (%T) restore start spreading " + "tag %T\r\n",BIF_P->id,tpl[2]); } +#endif DT_UTAG_FLAGS(BIF_P) = x; DT_UTAG(BIF_P) = tpl[2]; if (SEQ_TRACE_TOKEN(BIF_P) == NIL) { diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index 43fc910054..a44caa36db 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -383,7 +383,7 @@ static void doit_node_link_net_exits(ErtsLink *lnk, void *vnecp) Eterm *hp = erts_alloc_message_heap(3,&bp,&ohp,rp,&rp_locks); tup = TUPLE2(hp, am_nodedown, name); erts_queue_message(rp, &rp_locks, bp, tup, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -755,7 +755,7 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message) UseTmpHeapNoproc(5); if (SEQ_TRACE_TOKEN(sender) != NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag #endif ) { @@ -808,7 +808,7 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message) UseTmpHeapNoproc(6); if (SEQ_TRACE_TOKEN(sender) != NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag #endif ) { @@ -864,7 +864,7 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote, UseTmpHeapNoproc(6); if (token != NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES && token != am_have_dt_utag #endif ) { @@ -3111,7 +3111,7 @@ send_nodes_mon_msg(Process *rp, ASSERT(hend == hp); erts_queue_message(rp, rp_locksp, bp, msg, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); diff --git a/erts/emulator/beam/dtrace-wrapper.h b/erts/emulator/beam/dtrace-wrapper.h index b633058e90..9d1e55fc43 100644 --- a/erts/emulator/beam/dtrace-wrapper.h +++ b/erts/emulator/beam/dtrace-wrapper.h @@ -42,7 +42,7 @@ #define DTRACE_CHARBUF(name, size) \ char name##_BUFFER[size], *name = name##_BUFFER -#ifdef HAVE_DTRACE +#if defined(USE_DYNAMIC_TRACE) && defined(USE_VM_PROBES) #include "erlang_dtrace.h" @@ -87,7 +87,7 @@ STAP_PROBE10(provider,probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9),(parm10)) #endif /* STAP_PROBE_ADDR */ -#else /* HAVE_DTRACE */ +#else /* USE_DYNAMIC_TRACE && USE_VM_PROBES */ /* Render all macros to do nothing */ #define DTRACE_ENABLED(name) 0 @@ -104,6 +104,6 @@ #define DTRACE11(name, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ do {} while (0) -#endif /* HAVE_DTRACE */ +#endif /* USE_DYNAMIC_TRACE && USE_VM_PROBES */ #endif /* __DTRACE_WRAPPER_H */ diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index d575e30092..8130d5c576 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -3002,7 +3002,7 @@ reply_alloc_info(void *vair) } erts_queue_message(rp, &rp_locks, bp, msg, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c index b58c5ab761..bcfdacb91c 100644 --- a/erts/emulator/beam/erl_bif_ddll.c +++ b/erts/emulator/beam/erl_bif_ddll.c @@ -1763,7 +1763,7 @@ static void notify_proc(Process *proc, Eterm ref, Eterm driver_name, Eterm type, mess = TUPLE5(hp,type,r,am_driver,driver_name,tag); } erts_queue_message(proc, &rp_locks, bp, mess, am_undefined -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 90bbb34927..618acc5117 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -115,7 +115,7 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE #ifdef VALGRIND " [valgrind-compiled]" #endif -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES " [dtrace]" #endif "\n"); diff --git a/erts/emulator/beam/erl_bif_timer.c b/erts/emulator/beam/erl_bif_timer.c index fbc2f08c09..0002f8374f 100644 --- a/erts/emulator/beam/erl_bif_timer.c +++ b/erts/emulator/beam/erl_bif_timer.c @@ -374,7 +374,7 @@ bif_timer_timeout(ErtsBifTimer* btm) } erts_queue_message(rp, &rp_locks, bp, message, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c index c518aa6866..1ef4b07c24 100644 --- a/erts/emulator/beam/erl_bif_trace.c +++ b/erts/emulator/beam/erl_bif_trace.c @@ -1744,13 +1744,13 @@ Eterm erts_seq_trace(Process *p, Eterm arg1, Eterm arg2, return THE_NON_VALUE; } if (build_result) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES old_value = (SEQ_TRACE_TOKEN(p) == am_have_dt_utag) ? NIL : SEQ_TRACE_TOKEN(p); #else old_value = SEQ_TRACE_TOKEN(p); #endif } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES SEQ_TRACE_TOKEN(p) = (DT_UTAG(p) != NIL) ? am_have_dt_utag : NIL; #else SEQ_TRACE_TOKEN(p) = NIL; @@ -1768,7 +1768,7 @@ new_seq_trace_token(Process* p) Eterm* hp; if (SEQ_TRACE_TOKEN(p) == NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES || SEQ_TRACE_TOKEN(p) == am_have_dt_utag #endif ) { @@ -1792,7 +1792,7 @@ BIF_RETTYPE erl_seq_trace_info(Process *p, Eterm item) } if (SEQ_TRACE_TOKEN(p) == NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES || SEQ_TRACE_TOKEN(p) == am_have_dt_utag #endif ) { @@ -1853,7 +1853,7 @@ BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1) BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1) { if (SEQ_TRACE_TOKEN(BIF_P) == NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag #endif ) { @@ -1876,7 +1876,7 @@ BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1) BIF_RETTYPE seq_trace_print_2(BIF_ALIST_2) { if (SEQ_TRACE_TOKEN(BIF_P) == NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag #endif ) { diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index eb05ceaaf1..be345e7c9b 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -2204,7 +2204,7 @@ restart: break; case matchIsSeqTrace: if (SEQ_TRACE_TOKEN(c_p) != NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES && SEQ_TRACE_TOKEN(c_p) != am_have_dt_utag #endif ) @@ -2232,7 +2232,7 @@ restart: break; case matchGetSeqToken: if (SEQ_TRACE_TOKEN(c_p) == NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES || SEQ_TRACE_TOKEN(c_p) == am_have_dt_utag #endif ) diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 6dfccfe52f..2e340a7ef1 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -1935,7 +1935,7 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset) roots[n].sz = 1; n++; } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES if (is_not_immed(p->dt_utag)) { roots[n].v = &p->dt_utag; roots[n].sz = 1; @@ -2478,7 +2478,7 @@ offset_mqueue(Process *p, Sint offs, char* area, Uint area_size) if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) { ERL_MESSAGE_TOKEN(mp) = offset_ptr(mesg, offs); } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES mesg = ERL_MESSAGE_DT_UTAG(mp); if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) { ERL_MESSAGE_DT_UTAG(mp) = offset_ptr(mesg, offs); @@ -2504,7 +2504,7 @@ offset_one_rootset(Process *p, Sint offs, char* area, Uint area_size, offset_heap_ptr(&p->fvalue, 1, offs, area, area_size); offset_heap_ptr(&p->ftrace, 1, offs, area, area_size); offset_heap_ptr(&p->seq_trace_token, 1, offs, area, area_size); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES offset_heap_ptr(&p->dt_utag, 1, offs, area, area_size); #endif offset_heap_ptr(&p->group_leader, 1, offs, area, area_size); diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c index 561570c30e..5eb2a69242 100644 --- a/erts/emulator/beam/erl_lock_check.c +++ b/erts/emulator/beam/erl_lock_check.c @@ -183,7 +183,7 @@ static erts_lc_lock_order_t erts_lock_order[] = { { "save_ops_lock", NULL }, #endif #endif -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES { "efile_drv dtrace mutex", NULL }, #endif { "mtrace_buf", NULL }, diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index dc59b9c2c4..5d4dcaef6d 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -394,7 +394,7 @@ erts_queue_dist_message(Process *rcvr, tok_label, tok_lastcnt, tok_serial); } erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -403,14 +403,14 @@ erts_queue_dist_message(Process *rcvr, /* Enqueue message on external format */ ERL_MESSAGE_TERM(mp) = THE_NON_VALUE; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ERL_MESSAGE_DT_UTAG(mp) = NIL; if (token == am_have_dt_utag) { ERL_MESSAGE_TOKEN(mp) = NIL; } else { #endif ERL_MESSAGE_TOKEN(mp) = token; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES } #endif mp->next = NULL; @@ -445,7 +445,7 @@ erts_queue_message(Process* receiver, ErlHeapFragment* bp, Eterm message, Eterm seq_trace_token -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , Eterm dt_utag #endif ) @@ -489,7 +489,7 @@ erts_queue_message(Process* receiver, ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = seq_trace_token; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ERL_MESSAGE_DT_UTAG(mp) = dt_utag; #endif mp->next = NULL; @@ -567,7 +567,7 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg) Sint offs; Uint sz; ErlHeapFragment *bp; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Eterm utag; #endif @@ -579,7 +579,7 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg) ErlHeapFragment *dbg_bp; Uint *dbg_hp, *dbg_thp_start; Uint dbg_term_sz, dbg_token_sz; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Eterm dbg_utag; Uint dbg_utag_sz; #endif @@ -588,11 +588,11 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg) bp = msg->data.heap_frag; term = ERL_MESSAGE_TERM(msg); token = ERL_MESSAGE_TOKEN(msg); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES utag = ERL_MESSAGE_DT_UTAG(msg); #endif if (!bp) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ASSERT(is_immed(term) && is_immed(token) && is_immed(utag)); #else ASSERT(is_immed(term) && is_immed(token)); @@ -604,7 +604,7 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg) dbg_term_sz = size_object(term); dbg_token_sz = size_object(token); dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dbg_utag_sz = size_object(utag); dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz + dbg_utag_sz ); #endif @@ -615,7 +615,7 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg) dbg_hp = dbg_bp->mem; dbg_term = copy_struct(term, dbg_term_sz, &dbg_hp, &dbg_bp->off_heap); dbg_token = copy_struct(token, dbg_token_sz, &dbg_hp, &dbg_bp->off_heap); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dbg_utag = copy_struct(utag, dbg_utag_sz, &dbg_hp, &dbg_bp->off_heap); #endif dbg_thp_start = *hpp; @@ -623,7 +623,7 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg) if (bp->next != NULL) { move_multi_frags(hpp, off_heap, bp, msg->m, -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES 3 #else 2 @@ -730,7 +730,7 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg) ASSERT(hp > ptr_val(ERL_MESSAGE_TERM(msg))); #endif } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES if (is_not_immed(utag)) { ASSERT(in_heapfrag(ptr_val(utag), bp)); ERL_MESSAGE_DT_UTAG(msg) = offset_ptr(utag, offs); @@ -806,7 +806,7 @@ copy_done: #ifdef HARD_DEBUG ASSERT(eq(ERL_MESSAGE_TERM(msg), dbg_term)); ASSERT(eq(ERL_MESSAGE_TOKEN(msg), dbg_token)); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ASSERT(eq(ERL_MESSAGE_DT_UTAG(msg), dbg_utag)); #endif free_message_buffer(dbg_bp); @@ -903,7 +903,7 @@ erts_send_message(Process* sender, Eterm* hp; Eterm stoken = SEQ_TRACE_TOKEN(sender); Uint seq_trace_size = 0; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Uint dt_utag_size = 0; Eterm utag = NIL; #endif @@ -912,7 +912,7 @@ erts_send_message(Process* sender, msize = size_object(message); BM_SWAP_TIMER(size,send); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES if (stoken != am_have_dt_utag) { #endif @@ -920,7 +920,7 @@ erts_send_message(Process* sender, seq_trace_output(stoken, message, SEQ_TRACE_SEND, receiver->id, sender); seq_trace_size = 6; /* TUPLE5 */ -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES } if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) { dt_utag_size = size_object(DT_UTAG(sender)); @@ -930,7 +930,7 @@ erts_send_message(Process* sender, #endif bp = new_message_buffer(msize + seq_trace_size -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES + dt_utag_size #endif ); @@ -943,21 +943,15 @@ erts_send_message(Process* sender, &bp->off_heap); message = copy_struct(message, msize, &hp, &bp->off_heap); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) { utag = copy_struct(DT_UTAG(sender), dt_utag_size, &hp, &bp->off_heap); - erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) Spreading tag (%T) with message %T!\r\n",sender->id, utag, message); - } -#if 0 - DT_UTAG_FLAGS(sender) &= ~DT_UTAG_SPREADING; - if (!(DT_UTAG_FLAGS(sender) & DT_UTAG_PERMANENT)) { - erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) Killing tag!\r\n",sender->id); - DT_UTAG(sender) = NIL; - if (SEQ_TRACE_TOKEN(sender) == am_have_dt_utag) { - SEQ_TRACE_TOKEN(sender) = NIL; - } - } +#ifdef DTRACE_TAG_HARDDEBUG + erts_fprintf(stderr, + "Dtrace -> (%T) Spreading tag (%T) with " + "message %T!\r\n",sender->id, utag, message); #endif + } #endif BM_MESSAGE_COPIED(msize); BM_SWAP_TIMER(copy,send); @@ -976,7 +970,7 @@ erts_send_message(Process* sender, bp, message, token -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , utag #endif ); @@ -1012,7 +1006,7 @@ erts_send_message(Process* sender, size_object(message)msize, tok_label, tok_lastcnt, tok_serial); ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = NIL; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ERL_MESSAGE_DT_UTAG(mp) = NIL; #endif mp->next = NULL; @@ -1057,7 +1051,7 @@ erts_send_message(Process* sender, mp->data.attached = NULL; ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = NIL; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ERL_MESSAGE_DT_UTAG(mp) = NIL; #endif mp->next = NULL; @@ -1094,7 +1088,7 @@ erts_send_message(Process* sender, DTRACE6(message_send, sender_name, receiver_name, msize, tok_label, tok_lastcnt, tok_serial); erts_queue_message(receiver, receiver_locks, bp, message, token -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -1121,7 +1115,7 @@ erts_send_message(Process* sender, (uint32_t)msize, tok_label, tok_lastcnt, tok_serial); ERL_MESSAGE_TERM(mp) = message; ERL_MESSAGE_TOKEN(mp) = NIL; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ERL_MESSAGE_DT_UTAG(mp) = NIL; #endif mp->next = NULL; @@ -1163,7 +1157,7 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp, ErlHeapFragment* bp = NULL; if (token != NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES && token != am_have_dt_utag #endif ) { @@ -1182,7 +1176,7 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp, seq_trace_output(token, save, SEQ_TRACE_SEND, to->id, NULL); temptoken = copy_struct(token, sz_token, &hp, &bp->off_heap); erts_queue_message(to, to_locksp, bp, save, temptoken -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -1203,7 +1197,7 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp, : copy_struct(from, sz_from, &hp, ohp)); save = TUPLE3(hp, am_EXIT, from_copy, mess); erts_queue_message(to, to_locksp, bp, save, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h index 98321dd2c6..7678c7c753 100644 --- a/erts/emulator/beam/erl_message.h +++ b/erts/emulator/beam/erl_message.h @@ -70,7 +70,7 @@ typedef struct erl_mesg { ErlHeapFragment *heap_frag; void *attached; } data; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Eterm m[3]; /* m[0] = message, m[1] = seq trace token, m[3] = dynamic trace user tag */ #else Eterm m[2]; /* m[0] = message, m[1] = seq trace token */ @@ -79,7 +79,7 @@ typedef struct erl_mesg { #define ERL_MESSAGE_TERM(mp) ((mp)->m[0]) #define ERL_MESSAGE_TOKEN(mp) ((mp)->m[1]) -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES #define ERL_MESSAGE_DT_UTAG(mp) ((mp)->m[2]) #endif @@ -229,7 +229,7 @@ ErlHeapFragment* erts_resize_message_buffer(ErlHeapFragment *, Uint, void free_message_buffer(ErlHeapFragment *); void erts_queue_dist_message(Process*, ErtsProcLocks*, ErtsDistExternal *, Eterm); void erts_queue_message(Process*, ErtsProcLocks*, ErlHeapFragment*, Eterm, Eterm -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , Eterm dt_utag #endif ); diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index ebc771b016..156783d057 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -352,7 +352,7 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, flush_env(env); /* Needed for ERTS_HOLE_CHECK */ } erts_queue_message(rp, &rp_locks, frags, msg, am_undefined -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 6771e00c7e..f678d4159d 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -680,7 +680,7 @@ reply_sched_wall_time(void *vswtrp) } erts_queue_message(rp, &rp_locks, bp, msg, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -7264,7 +7264,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). p->seq_trace_lastcnt = 0; p->seq_trace_clock = 0; SEQ_TRACE_TOKEN(p) = NIL; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES DT_UTAG(p) = NIL; DT_UTAG_FLAGS(p) = 0; #endif @@ -7860,7 +7860,7 @@ send_exit_message(Process *to, ErtsProcLocks *to_locksp, Eterm exit_term, Uint term_size, Eterm token) { if (token == NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES || token == am_have_dt_utag #endif ) { @@ -7872,7 +7872,7 @@ send_exit_message(Process *to, ErtsProcLocks *to_locksp, hp = erts_alloc_message_heap(term_size, &bp, &ohp, to, to_locksp); mess = copy_struct(exit_term, term_size, &hp, ohp); erts_queue_message(to, to_locksp, bp, mess, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -7892,7 +7892,7 @@ send_exit_message(Process *to, ErtsProcLocks *to_locksp, seq_trace_output(token, mess, SEQ_TRACE_SEND, to->id, NULL); temp_token = copy_struct(token, sz_token, &hp, &bp->off_heap); erts_queue_message(to, to_locksp, bp, mess, temp_token -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -8002,7 +8002,7 @@ send_exit_signal(Process *c_p, /* current process if and only if (ERTS_PROC_IS_TRAPPING_EXITS(rp) && (reason != am_kill || (flags & ERTS_XSIG_FLG_IGN_KILL))) { if (is_not_nil(token) -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES && token != am_have_dt_utag #endif && token_update) diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 35b31b1009..cff0783bc4 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -683,7 +683,7 @@ struct process { Uint seq_trace_lastcnt; Eterm seq_trace_token; /* Sequential trace token (tuple size 5 see below) */ -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Eterm dt_utag; /* Place to store the dynamc trace user tag */ Uint dt_utag_flags; /* flag field for the dt_utag */ #endif @@ -1002,7 +1002,7 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags; #define SEQ_TRACE_PRINT (1 << 2) #define SEQ_TRACE_TIMESTAMP (1 << 3) -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES #define DT_UTAG_PERMANENT (1 << 0) #define DT_UTAG_SPREADING (1 << 1) #define DT_UTAG(P) ((P)->dt_utag) diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index a4aed0122b..4261cd03be 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -125,7 +125,7 @@ do { \ enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE, (FPID), (TPID), (MSG), (BP)); \ } while(0) #else -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES #define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \ erts_queue_message((TPROC), NULL, (BP), (MSG), NIL, NIL) #else @@ -589,7 +589,7 @@ profile_send(Eterm from, Eterm message) { msg = copy_struct(message, sz, &hp, &bp->off_heap); erts_queue_message(profile_p, NULL, bp, msg, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -1004,7 +1004,7 @@ seq_trace_update_send(Process *p) Eterm seq_tracer = erts_get_system_seq_tracer(); ASSERT((is_tuple(SEQ_TRACE_TOKEN(p)) || is_nil(SEQ_TRACE_TOKEN(p)))); if ( (p->id == seq_tracer) || (SEQ_TRACE_TOKEN(p) == NIL) -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES || (SEQ_TRACE_TOKEN(p) == am_have_dt_utag) #endif ) { @@ -1192,7 +1192,7 @@ seq_trace_output_generic(Eterm token, Eterm msg, Uint type, erts_smp_mtx_unlock(&smq_mtx); #else erts_queue_message(tracer, NULL, bp, mess, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); /* trace_token must be NIL here */ @@ -2487,7 +2487,7 @@ monitor_long_gc(Process *p, Uint time) { enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp); #else erts_queue_message(monitor_p, NULL, bp, msg, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -2563,7 +2563,7 @@ monitor_large_heap(Process *p) { enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp); #else erts_queue_message(monitor_p, NULL, bp, msg, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -2597,7 +2597,7 @@ monitor_generic(Process *p, Eterm type, Eterm spec) { enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp); #else erts_queue_message(monitor_p, NULL, bp, msg, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -3387,7 +3387,7 @@ sys_msg_dispatcher_func(void *unused) else { queue_proc_msg: erts_queue_message(proc,&proc_locks,smqp->bp,smqp->msg,NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 75ea53c2b7..9425576980 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -1565,7 +1565,7 @@ deliver_result(Eterm sender, Eterm pid, Eterm res) res = copy_struct(res, sz_res, &hp, ohp); tuple = TUPLE2(hp, sender, res); erts_queue_message(rp, &rp_locks, bp, tuple, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -1658,7 +1658,7 @@ static void deliver_read_message(Port* prt, Eterm to, hp += 3; erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -1815,7 +1815,7 @@ deliver_vec_message(Port* prt, /* Port */ hp += 3; erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -2785,7 +2785,7 @@ void driver_report_exit(int ix, int status) tuple = TUPLE2(hp, prt->id, tuple); erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); @@ -3339,7 +3339,7 @@ driver_deliver_term(ErlDrvPort port, } /* send message */ erts_queue_message(rp, &rp_locks, bp, mess, am_undefined -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index 2efcd19162..5ab51fab50 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -1698,7 +1698,7 @@ static int do_send_to_logger(Eterm tag, Eterm gleader, char *buf, int len) } #else erts_queue_message(p, NULL /* only used for smp build */, bp, tuple3, NIL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , NIL #endif ); diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 62b582f76a..53cdb13db0 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -123,7 +123,7 @@ static ErlDrvSysInfo sys_info; /* For explanation of this var, see comment for same var in erl_async.c */ static unsigned gcc_optimizer_hack = 0; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES #define DTRACE_EFILE_BUFSIZ 128 @@ -148,11 +148,11 @@ typedef struct { } dt_private; dt_private *get_dt_private(int); -#else /* HAVE_DTRACE */ +#else /* USE_VM_PROBES */ #define DTRACE_INVOKE_SETUP(op) do {} while (0) #define DTRACE_INVOKE_SETUP_BY_NAME(op) do {} while (0) #define DTRACE_INVOKE_RETURN(op) do {} while (0) -#endif /* HAVE_DTRACE */ +#endif /* USE_VM_PROBES */ /* #define TRACE 1 */ #ifdef TRACE @@ -208,7 +208,7 @@ dt_private *get_dt_private(int); #ifdef FILENAMES_16BIT -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES #error 16bit characters in filenames and dtrace in combination is not supported. #endif # define FILENAME_BYTELEN(Str) filename_len_16bit(Str) @@ -326,7 +326,7 @@ typedef struct { ErlDrvPDL q_mtx; /* Mutex for the driver queue, known by the emulator. Also used for mutual exclusion when accessing field(s) below. */ size_t write_buffered; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES int idnum; /* Unique ID # for this driver thread/desc */ char port_str[DTRACE_TERM_BUF_SIZE]; #endif @@ -427,7 +427,7 @@ struct t_data void (*free)(void *); int again; int reply; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES int sched_i1; Uint64 sched_i2; char sched_utag[DTRACE_EFILE_BUFSIZ+1]; @@ -727,10 +727,10 @@ file_init(void) : 0); driver_system_info(&sys_info, sizeof(ErlDrvSysInfo)); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES erts_mtx_init(&dt_driver_mutex, "efile_drv dtrace mutex"); pthread_key_create(&dt_driver_key, NULL); -#endif /* HAVE_DTRACE */ +#endif /* USE_VM_PROBES */ return 0; } @@ -771,10 +771,10 @@ file_start(ErlDrvPort port, char* command) desc->write_error = 0; MUTEX_INIT(desc->q_mtx, port); /* Refc is one, referenced by emulator now */ desc->write_buffered = 0; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dtrace_drvport_str(port, desc->port_str); get_dt_private(0); /* throw away return value */ -#endif /* HAVE_DTRACE */ +#endif /* USE_VM_PROBES */ return (ErlDrvData) desc; } @@ -2025,7 +2025,7 @@ static void cq_execute(file_descriptor *desc) { static struct t_data *async_write(file_descriptor *desc, int *errp, int reply, Uint32 reply_size -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ,Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3 #endif ) { @@ -2041,7 +2041,7 @@ static struct t_data *async_write(file_descriptor *desc, int *errp, d->c.writev.port = desc->port; d->c.writev.q_mtx = desc->q_mtx; d->c.writev.size = desc->write_buffered; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES if (dt_i1 != NULL) { *dt_i1 = d->fd; *dt_i2 = d->flags; @@ -2060,12 +2060,12 @@ static struct t_data *async_write(file_descriptor *desc, int *errp, } static int flush_write(file_descriptor *desc, int *errp -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_private *dt_priv, char *dt_utag #endif ) { int result = 0; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; #endif struct t_data *d = NULL; @@ -2073,7 +2073,7 @@ static int flush_write(file_descriptor *desc, int *errp MUTEX_LOCK(desc->q_mtx); if (desc->write_buffered > 0) { if ((d = async_write(desc, errp, 0, 0 -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ,&dt_i1, &dt_i2, &dt_i3 #endif )) == NULL) { @@ -2081,7 +2081,7 @@ static int flush_write(file_descriptor *desc, int *errp } } MUTEX_UNLOCK(desc->q_mtx); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES if (d != NULL) { d->sched_i1 = dt_priv->thread_num; d->sched_i2 = dt_priv->tag; @@ -2098,7 +2098,7 @@ static int flush_write(file_descriptor *desc, int *errp dt_utag, FILE_WRITE, NULL, NULL, dt_i1, dt_i2, dt_i3, 0, desc->port_str); } -#endif /* HAVE_DTRACE */ +#endif /* USE_VM_PROBES */ return result; } @@ -2112,13 +2112,13 @@ static int check_write_error(file_descriptor *desc, int *errp) { } static int flush_write_check_error(file_descriptor *desc, int *errp -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_private *dt_priv, char *dt_utag #endif ) { int r; if ( (r = flush_write(desc, errp -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif )) != 0) { @@ -2131,7 +2131,7 @@ static int flush_write_check_error(file_descriptor *desc, int *errp static struct t_data *async_lseek(file_descriptor *desc, int *errp, int reply, Sint64 offset, int origin -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3 #endif ) { @@ -2146,7 +2146,7 @@ static struct t_data *async_lseek(file_descriptor *desc, int *errp, int reply, d->reply = reply; d->c.lseek.offset = offset; d->c.lseek.origin = origin; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES if (dt_i1 != NULL) { *dt_i1 = d->fd; *dt_i2 = d->c.lseek.offset; @@ -2170,13 +2170,13 @@ static void flush_read(file_descriptor *desc) { } static int lseek_flush_read(file_descriptor *desc, int *errp -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES ,dt_private *dt_priv, char *dt_utag #endif ) { int r = 0; size_t read_size = desc->read_size; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; #endif struct t_data *d; @@ -2185,13 +2185,13 @@ static int lseek_flush_read(file_descriptor *desc, int *errp if (read_size != 0) { if ((d = async_lseek(desc, errp, 0, -((ssize_t)read_size), EFILE_SEEK_CUR -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , &dt_i1, &dt_i2, &dt_i3 #endif )) == NULL) { r = -1; } else { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES d->sched_i1 = dt_priv->thread_num; d->sched_i2 = dt_priv->tag; d->sched_utag[0] = '\0'; @@ -2206,7 +2206,7 @@ static int lseek_flush_read(file_descriptor *desc, int *errp DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++, dt_utag, FILE_LSEEK, NULL, NULL, dt_i1, dt_i2, dt_i3, 0, desc->port_str); -#endif /* HAVE_DTRACE */ +#endif /* USE_VM_PROBES */ } } return r; @@ -2224,7 +2224,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) struct t_data *d = (struct t_data *) data; char header[5]; /* result code + count */ char resbuf[RESBUFSIZE]; /* Result buffer. */ -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES 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; @@ -2235,7 +2235,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) strncpy(sched_utag, d->sched_utag, DTRACE_EFILE_BUFSIZ); sched_utag[DTRACE_EFILE_BUFSIZ] = '\0'; } -#endif /* HAVE_DTRACE */ +#endif /* USE_VM_PROBES */ TRACE_C('r'); @@ -2438,7 +2438,7 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) if (d->reply) { TRACE_C('K'); reply_ok(desc); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES result_ok = 1; #endif } @@ -2520,7 +2520,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) char* name; /* Points to the filename in buf. */ int command; struct t_data *d = NULL; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES char *dt_utag = NULL; char *dt_s1 = NULL, *dt_s2 = NULL; Sint64 dt_i1 = 0; @@ -2528,7 +2528,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) Sint64 dt_i3 = 0; Sint64 dt_i4 = 0; dt_private *dt_priv = get_dt_private(0); -#endif /* HAVE_DTRACE */ +#endif /* USE_VM_PROBES */ TRACE_C('o'); @@ -2543,7 +2543,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = d->b; dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; #endif @@ -2558,7 +2558,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = d->b; dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; #endif @@ -2573,7 +2573,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = d->b; dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; #endif @@ -2594,7 +2594,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_COPY(d->b, name); FILENAME_COPY(d->b + namelen, new_name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = d->b; dt_s2 = d->b + namelen; dt_utag = buf + namelen + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; @@ -2612,7 +2612,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = d->b; dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; #endif @@ -2627,7 +2627,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); d->drive = *(uchar*)buf; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = buf + 1; #endif d->command = command; @@ -2645,7 +2645,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = d->b; dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; #endif @@ -2673,7 +2673,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) dir_handle = NULL; resbuf[0] = FILE_RESP_LFNAME; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = name; dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; #endif @@ -2710,7 +2710,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) reply_error(desc, &errInfo); return; } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++, dt_utag, command, name, dt_s2, dt_i1, dt_i2, dt_i3, dt_i4, desc->port_str); @@ -2727,7 +2727,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d->flags = get_int32((uchar*)buf); name = buf+4; FILENAME_COPY(d->b, name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i1 = d->flags; dt_s1 = d->b; dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; @@ -2744,7 +2744,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data)); d->fd = fd; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = name; dt_i1 = fd; #endif @@ -2760,7 +2760,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data)); d->fd = fd; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = name; dt_i1 = fd; #endif @@ -2780,7 +2780,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_COPY(d->b, name); d->fd = fd; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; if (command == FILE_LSTAT) { dt_s1 = d->b; @@ -2801,7 +2801,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d->flags = desc->flags; d->fd = fd; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = name; dt_i1 = fd; dt_i2 = d->flags; @@ -2826,7 +2826,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d->info.cTime = (time_t)((Sint64)get_int64(buf + 7 * 4)); FILENAME_COPY(d->b, buf + 9*4); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i1 = d->info.mode; dt_i2 = d->info.uid; dt_i3 = d->info.gid; @@ -2845,7 +2845,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); FILENAME_COPY(d->b, name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = d->b; dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; #endif @@ -2860,7 +2860,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); FILENAME_COPY(d->b, name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = d->b; dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; #endif @@ -2884,7 +2884,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_COPY(d->b, name); FILENAME_COPY(d->b + namelen, new_name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = d->b; dt_s2 = d->b + namelen; dt_utag = buf + namelen + FILENAME_BYTELEN(dt_s2) + FILENAME_CHARSIZE; @@ -2910,7 +2910,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_COPY(d->b, name); FILENAME_COPY(d->b + namelen, new_name); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_s1 = d->b; dt_s2 = d->b + namelen; dt_utag = buf + namelen + FILENAME_BYTELEN(dt_s2) + FILENAME_CHARSIZE; @@ -2936,7 +2936,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d->c.fadvise.offset = get_int64((uchar*) buf); d->c.fadvise.length = get_int64(((uchar*) buf) + sizeof(Sint64)); d->c.fadvise.advise = get_int32(((uchar*) buf) + 2 * sizeof(Sint64)); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i1 = d->fd; dt_i2 = d->c.fadvise.offset; dt_i3 = d->c.fadvise.length; @@ -2956,7 +2956,7 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) done: if (d) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES d->sched_i1 = dt_priv->thread_num; d->sched_i2 = dt_priv->tag; d->sched_utag[0] = '\0'; @@ -2985,7 +2985,7 @@ file_flush(ErlDrvData e) { #ifdef DEBUG int r; #endif -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); #endif @@ -2999,7 +2999,7 @@ file_flush(ErlDrvData e) { r = #endif flush_write(desc, NULL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, (desc->d == NULL) ? NULL : desc->d->sched_utag #endif ); @@ -3044,7 +3044,7 @@ static void file_timeout(ErlDrvData e) { file_descriptor *desc = (file_descriptor *)e; enum e_timer timer_state = desc->timer_state; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); #endif @@ -3065,7 +3065,7 @@ file_timeout(ErlDrvData e) { int r = #endif flush_write(desc, NULL -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, (desc->d == NULL) ? NULL : desc->d->sched_utag #endif ); @@ -3090,7 +3090,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { int p, q; int err; struct t_data *d = NULL; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; Sint64 dt_i4 = 0; char *dt_utag = NULL; @@ -3116,12 +3116,12 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { switch (command) { case FILE_CLOSE: { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = EV_CHAR_P(ev, p, q); #endif flush_read(desc); if (flush_write_check_error(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3136,7 +3136,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->reply = !0; d->fd = desc->fd; d->flags = desc->flags; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i1 = d->fd; dt_i2 = d->flags; #endif @@ -3162,11 +3162,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = EV_CHAR_P(ev, p, q); #endif if (flush_write_check_error(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3178,7 +3178,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { /* We have allocated a buffer for line mode but should not really have a read-ahead buffer... */ if (lseek_flush_read(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3262,7 +3262,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->c.read.bin_offset = desc->read_offset + desc->read_size; d->c.read.bin_size = desc->read_binp->orig_size - d->c.read.bin_offset; d->c.read.size = size; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i1 = d->fd; dt_i2 = d->flags; dt_i3 = d->c.read.size; @@ -3284,11 +3284,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { * allocated binary + dealing with offsets and lengts are done in file_async ready * for this OP. */ -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = EV_CHAR_P(ev, p, q); #endif if (flush_write_check_error(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3296,7 +3296,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if (ev->size != 1 -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES + FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE #endif ) { @@ -3355,14 +3355,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->c.read_line.binp = desc->read_binp; d->c.read_line.read_offset = desc->read_offset; d->c.read_line.read_size = desc->read_size; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i1 = d->fd; dt_i2 = d->flags; dt_i3 = d->c.read_line.read_offset; #endif #if !ALWAYS_READ_LINE_AHEAD d->c.read_line.read_ahead = (desc->read_bufsize > 0); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i4 = d->c.read_line.read_ahead; #endif #endif @@ -3378,13 +3378,13 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { ErlDrvSizeT skip = 1; ErlDrvSizeT size = ev->size - skip; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = EV_CHAR_P(ev, p, q); skip += FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE; size = ev->size - skip; #endif if (lseek_flush_read(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3415,7 +3415,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } } else { if ((d = async_write(desc, &err, !0, size -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , &dt_i1, &dt_i2, &dt_i3 #endif )) == NULL) { @@ -3433,7 +3433,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { This is handled specially in prim_file.erl */ Uint32 i, j, n; size_t total; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES char dt_tmp; int dt_utag_bytes = 1; @@ -3447,7 +3447,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } #endif if (ev->size < 1+4 -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES + dt_utag_bytes #endif || !EV_GET_UINT32(ev, &n, &p, &q)) { @@ -3456,7 +3456,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if (lseek_flush_read(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3464,7 +3464,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if (flush_write_check_error(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3481,7 +3481,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if (ev->size < 1+4+8*(2*n) -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES + dt_utag_bytes #endif ) { @@ -3499,7 +3499,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->reply = !0; d->fd = desc->fd; d->flags = desc->flags; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i1 = d->fd; dt_i2 = d->flags; #endif @@ -3540,7 +3540,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } } d->c.pwritev.size = total; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i3 = d->c.pwritev.size; #endif d->c.pwritev.free_size = 0; @@ -3550,7 +3550,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_Uint(desc, 0); } else { ErlDrvSizeT skip = 1 + 4 + 8 * (2*n) -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES + dt_utag_bytes #endif ; @@ -3580,7 +3580,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { register void * void_ptr; Uint32 i, n; ErlIOVec *res_ev; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES char dt_tmp; int dt_utag_bytes = 1; /* This will work for UTF-8, but not for UTF-16 - extra reminder here */ @@ -3593,7 +3593,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } #endif if (lseek_flush_read(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3601,7 +3601,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if (flush_write_check_error(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3609,7 +3609,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if (ev->size < 1+8 -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES + dt_utag_bytes #endif || !EV_GET_UINT32(ev, &n, &p, &q) @@ -3619,7 +3619,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if (ev->size < 1+8+8*(2*n) -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES + dt_utag_bytes #endif ) { @@ -3642,7 +3642,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->reply = !0; d->fd = desc->fd; d->flags = desc->flags; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i1 = d->fd; dt_i2 = d->flags; #endif @@ -3673,7 +3673,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else size = ((size_t)sizeH<<32) | sizeL; #endif -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i3 += size; #endif if (! (res_ev->binv[i] = driver_alloc_binary(size))) { @@ -3732,11 +3732,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = EV_CHAR_P(ev, p, q); #endif if (lseek_flush_read(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3744,7 +3744,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if (flush_write_check_error(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3752,7 +3752,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if ((d = async_lseek(desc, &err, !0, offset, origin -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , &dt_i1, &dt_i2, &dt_i3 #endif )) == NULL) { @@ -3768,7 +3768,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, ENOENT); goto done; } -#ifndef HAVE_DTRACE +#ifndef USE_VM_PROBES /* In the dtrace case, the iov has an extra element, the dtrace utag - we will need another test to see that the filename is in a single buffer: */ @@ -3794,7 +3794,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->reply = !0; /* Copy name */ FILENAME_COPY(d->b, filename); -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES { char dt_tmp; @@ -3848,11 +3848,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_utag = EV_CHAR_P(ev, p, q); #endif if (lseek_flush_read(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3860,7 +3860,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if (flush_write_check_error(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -3883,7 +3883,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->flags = desc->flags; d->c.preadv.offsets[0] = hdr_offset; d->c.preadv.size = max_size; -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i1 = d->fd; dt_i2 = d->flags; dt_i3 = d->c.preadv.offsets[0]; @@ -3910,7 +3910,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i1 = opt; dt_utag = EV_CHAR_P(ev, p, q); #endif @@ -3918,7 +3918,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { case FILE_OPT_DELAYED_WRITE: { Uint32 sizeH, sizeL, delayH, delayL; if (ev->size != 1+1+4*sizeof(Uint32) -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES + FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE #endif || !EV_GET_UINT32(ev, &sizeH, &p, &q) @@ -3947,7 +3947,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else desc->write_delay = ((unsigned long)delayH << 32) | delayL; #endif -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i2 = desc->write_delay; #endif TRACE_C('K'); @@ -3956,7 +3956,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { case FILE_OPT_READ_AHEAD: { Uint32 sizeH, sizeL; if (ev->size != 1+1+2*sizeof(Uint32) -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES + FILENAME_BYTELEN(dt_utag)+FILENAME_CHARSIZE #endif || !EV_GET_UINT32(ev, &sizeH, &p, &q) @@ -3974,7 +3974,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else desc->read_bufsize = ((size_t)sizeH << 32) | sizeL; #endif -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_i2 = desc->read_bufsize; #endif TRACE_C('K'); @@ -4064,7 +4064,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } /* switch(command) */ if (lseek_flush_read(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -4072,7 +4072,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { goto done; } if (flush_write_check_error(desc, &err -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES , dt_priv, dt_utag #endif ) < 0) { @@ -4094,7 +4094,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { done: if (d != NULL) { -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES /* * If d == NULL, then either: * 1). There was an error of some sort, or @@ -4119,7 +4119,7 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { cq_execute(desc); } -#ifdef HAVE_DTRACE +#ifdef USE_VM_PROBES dt_private * get_dt_private(int base) { @@ -4135,4 +4135,4 @@ get_dt_private(int base) } return dt_priv; } -#endif /* HAVE_DTRACE */ +#endif /* USE_VM_PROBES */ -- cgit v1.2.3 From db4ddca4d9709965121fba9a1f9cc68226f35a0c Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Mon, 5 Mar 2012 17:29:03 +0100 Subject: Correct some errors in the user tag spreading --- erts/emulator/beam/beam_emu.c | 2 +- erts/emulator/beam/dist.c | 4 ++-- erts/emulator/beam/erl_message.c | 6 +++--- erts/emulator/drivers/common/efile_drv.c | 18 +++++++++++++----- 4 files changed, 19 insertions(+), 11 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 763d15e101..8cfcbd0fb8 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -1963,7 +1963,7 @@ void process_main(void) dtrace_proc_str(c_p, receiver_name); token2 = SEQ_TRACE_TOKEN(c_p); - if (token2 != NIL) { + if (token2 != NIL && token2 != am_have_dt_utag) { tok_label = signed_val(SEQ_TRACE_T_LABEL(token2)); tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token2)); tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token2)); diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index a44caa36db..e93176ba4e 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -769,7 +769,7 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message) erts_snprintf(sender_name, sizeof(sender_name), "%T", sender->id); erts_snprintf(receiver_name, sizeof(receiver_name), "%T", remote); msize = size_object(message); - if (token != NIL) { + if (token != NIL && token != am_have_dt_utag) { tok_label = signed_val(SEQ_TRACE_T_LABEL(token)); tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token)); tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); @@ -823,7 +823,7 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message) erts_snprintf(receiver_name, sizeof(receiver_name), "{%T,%s}", remote_name, node_name); msize = size_object(message); - if (token != NIL) { + if (token != NIL && token != am_have_dt_utag) { tok_label = signed_val(SEQ_TRACE_T_LABEL(token)); tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token)); tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index 5d4dcaef6d..7de30d25ed 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -384,7 +384,7 @@ erts_queue_dist_message(Process *rcvr, DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE); dtrace_proc_str(rcvr, receiver_name); - if (token != NIL) { + if (token != NIL && token != am_have_dt_utag) { tok_label = signed_val(SEQ_TRACE_T_LABEL(token)); tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token)); tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); @@ -419,7 +419,7 @@ erts_queue_dist_message(Process *rcvr, DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE); dtrace_proc_str(rcvr, receiver_name); - if (token != NIL) { + if (token != NIL && token != am_have_dt_utag) { tok_label = signed_val(SEQ_TRACE_T_LABEL(token)); tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token)); tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); @@ -957,7 +957,7 @@ erts_send_message(Process* sender, BM_SWAP_TIMER(copy,send); if (DTRACE_ENABLED(message_send)) { - if (stoken != NIL) { + if (stoken != NIL && stoken != am_have_dt_utag) { tok_label = signed_val(SEQ_TRACE_T_LABEL(stoken)); tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(stoken)); tok_serial = signed_val(SEQ_TRACE_T_SERIAL(stoken)); diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 53cdb13db0..b33a8d210b 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -2711,9 +2711,15 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) return; } #ifdef USE_VM_PROBES - DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++, + if (dt_utag != NULL && dt_utag[0] == '\0') { + dt_utag = NULL; + } + + DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag, dt_utag, command, name, dt_s2, dt_i1, dt_i2, dt_i3, dt_i4, desc->port_str); + DTRACE6(efile_drv_return, dt_priv->thread_num, dt_priv->tag++, + dt_utag, command, 1, 0); #endif TRACE_C('R'); driver_output2(desc->port, resbuf, 1, NULL, 0); @@ -3806,8 +3812,6 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { ; dt_s1 = d->b; dt_utag = EV_CHAR_P(ev, p, q); - if (*dt_utag != 0) - fprintf(stderr,"dt_utag = %s\r\n",dt_utag); } #endif d->c.read_file.binp = NULL; @@ -4108,8 +4112,12 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->sched_i2 = dt_priv->tag; d->sched_utag[0] = '\0'; if (dt_utag != NULL) { - strncpy(d->sched_utag, dt_utag, sizeof(d->sched_utag) - 1); - d->sched_utag[sizeof(d->sched_utag) - 1] = '\0'; + if (dt_utag[0] == '\0') { + dt_utag = NULL; + } else { + strncpy(d->sched_utag, dt_utag, sizeof(d->sched_utag) - 1); + d->sched_utag[sizeof(d->sched_utag) - 1] = '\0'; + } } DTRACE11(efile_drv_entry, dt_priv->thread_num, dt_priv->tag++, dt_utag, command, dt_s1, NULL, dt_i1, dt_i2, dt_i3, dt_i4, -- cgit v1.2.3 From 326e098659de187099451bf20a33c3e6181b4141 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Fri, 9 Mar 2012 17:20:49 +0100 Subject: Ifdef all dynamic trace code --- erts/emulator/beam/beam_emu.c | 33 ++++++++++++++--------- erts/emulator/beam/copy.c | 2 ++ erts/emulator/beam/dist.c | 46 +++++++++++++++++++++++++-------- erts/emulator/beam/erl_async.c | 4 +++ erts/emulator/beam/erl_bif_port.c | 7 ++++- erts/emulator/beam/erl_gc.c | 15 ++++++++--- erts/emulator/beam/erl_message.c | 36 +++++++++++++++++--------- erts/emulator/beam/erl_nif.c | 4 +++ erts/emulator/beam/erl_port_task.c | 4 +++ erts/emulator/beam/erl_process.c | 8 ++++++ erts/emulator/beam/io.c | 39 +++++++++++++++++++++++++++- erts/emulator/sys/common/erl_check_io.c | 6 +++++ 12 files changed, 164 insertions(+), 40 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 8cfcbd0fb8..5c5d9fd049 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -1122,6 +1122,7 @@ init_emulator(void) #endif /* USE_VM_PROBES */ +#ifdef USE_VM_PROBES void dtrace_drvport_str(ErlDrvPort drvport, char *port_buf) { @@ -1131,7 +1132,7 @@ dtrace_drvport_str(ErlDrvPort drvport, char *port_buf) port_channel_no(port->id), port_number(port->id)); } - +#endif /* * process_main() is called twice: * The first call performs some initialisation, including exporting @@ -1304,6 +1305,7 @@ void process_main(void) SWAPIN; ASSERT(VALID_INSTR(next)); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(process_scheduled)) { DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(fun_buf, DTRACE_TERM_BUF_SIZE); @@ -1325,7 +1327,7 @@ void process_main(void) DTRACE2(process_scheduled, process_buf, fun_buf); } - +#endif Goto(next); } @@ -1591,13 +1593,16 @@ void process_main(void) OpCase(return): { +#ifdef USE_VM_PROBES BeamInstr* fptr; +#endif SET_I(c_p->cp); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(function_return) && (fptr = find_function_from_pc(c_p->cp))) { DTRACE_RETURN(c_p, (Eterm)fptr[0], (Eterm)fptr[1], (Uint)fptr[2]); } - +#endif /* * We must clear the CP to make sure that a stale value do not * create a false module dependcy preventing code upgrading. @@ -1954,12 +1959,13 @@ void process_main(void) } #endif } +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(message_receive)) { Eterm token2 = NIL; DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE); - ERTS_DECLARE_DUMMY(Sint tok_label) = 0; - ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0; - ERTS_DECLARE_DUMMY(Sint tok_serial) = 0; + Sint tok_label = 0; + Sint tok_lastcnt = 0; + Sint tok_serial = 0; dtrace_proc_str(c_p, receiver_name); token2 = SEQ_TRACE_TOKEN(c_p); @@ -1972,6 +1978,7 @@ void process_main(void) receiver_name, size_object(ERL_MESSAGE_TERM(msgp)), c_p->msg.len - 1, tok_label, tok_lastcnt, tok_serial); } +#endif UNLINK_MESSAGE(c_p, msgp); JOIN_MESSAGE(c_p); CANCEL_TIMER(c_p); @@ -3332,7 +3339,6 @@ void process_main(void) BifFunction vbf; DTRACE_NIF_ENTRY(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]); - c_p->current = I-3; /* current and vbf set to please handle_error */ SWAPOUT; c_p->fcalls = FCALLS - 1; @@ -3356,7 +3362,6 @@ void process_main(void) ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); DTRACE_NIF_RETURN(c_p, (Eterm)I[-3], (Eterm)I[-2], (Uint)I[-1]); - goto apply_bif_or_nif_epilogue; OpCase(apply_bif): @@ -6082,13 +6087,14 @@ apply(Process* p, Eterm module, Eterm function, Eterm args, Eterm* reg) save_calls(p, ep); } +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(function_entry) && ep->address) { BeamInstr *fptr = find_function_from_pc(ep->address); if (fptr) { DTRACE_CALL(p, (Eterm)fptr[0], (Eterm)fptr[1], (Uint)fptr[2]); } } - +#endif return ep->address; } @@ -6138,13 +6144,14 @@ fixed_apply(Process* p, Eterm* reg, Uint arity) save_calls(p, ep); } +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(function_entry)) { BeamInstr *fptr = find_function_from_pc(ep->address); if (fptr) { DTRACE_CALL(p, (Eterm)fptr[0], (Eterm)fptr[1], (Uint)fptr[2]); } } - +#endif return ep->address; } @@ -6194,6 +6201,7 @@ erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* re c_p->max_arg_reg = sizeof(c_p->def_arg_reg)/sizeof(c_p->def_arg_reg[0]); } +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(process_hibernate)) { DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); @@ -6201,7 +6209,7 @@ erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* re process_name, mfa); DTRACE2(process_hibernate, process_name, mfa); } - +#endif /* * Arrange for the process to be resumed at the given MFA with * the stack cleared. @@ -6276,6 +6284,7 @@ call_fun(Process* p, /* Current process. */ code_ptr = fe->address; actual_arity = (int) code_ptr[-1]; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(function_entry)) { BeamInstr *fptr = find_function_from_pc(code_ptr); @@ -6283,7 +6292,7 @@ call_fun(Process* p, /* Current process. */ DTRACE_CALL(p, fe->module, (Eterm)fptr[1], actual_arity); } } - +#endif if (actual_arity == arity+num_free) { if (num_free == 0) { return code_ptr; diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c index 4ee60807d9..2c355fadfa 100644 --- a/erts/emulator/beam/copy.c +++ b/erts/emulator/beam/copy.c @@ -60,12 +60,14 @@ copy_object(Eterm obj, Process* to) Eterm* hp = HAlloc(to, size); Eterm res; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(copy_object)) { DTRACE_CHARBUF(proc_name, 64); erts_snprintf(proc_name, sizeof(proc_name), "%T", to->id); DTRACE2(copy_object, proc_name, size); } +#endif res = copy_struct(obj, size, &hp, &to->off_heap); #ifdef DEBUG if (eq(obj, res) == 0) { diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index e93176ba4e..802feaeb1c 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -745,13 +745,15 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message) Eterm token = NIL; Process *sender = dsdp->proc; int res; - 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; +#ifdef USE_VM_PROBES + Sint tok_label = 0; + Sint tok_lastcnt = 0; + Sint tok_serial = 0; + Uint msize = 0; DTRACE_CHARBUF(node_name, 64); DTRACE_CHARBUF(sender_name, 64); DTRACE_CHARBUF(receiver_name, 64); +#endif UseTmpHeapNoproc(5); if (SEQ_TRACE_TOKEN(sender) != NIL @@ -763,6 +765,7 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message) token = SEQ_TRACE_TOKEN(sender); seq_trace_output(token, message, SEQ_TRACE_SEND, remote, sender); } +#ifdef USE_VM_PROBES *node_name = *sender_name = *receiver_name = '\0'; if (DTRACE_ENABLED(message_send) || DTRACE_ENABLED(message_send_remote)) { erts_snprintf(node_name, sizeof(node_name), "%T", dsdp->dep->sysname); @@ -775,6 +778,7 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message) tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); } } +#endif if (token != NIL) ctl = TUPLE4(&ctl_heap[0], @@ -798,13 +802,15 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message) Eterm token = NIL; Process *sender = dsdp->proc; int res; - 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; +#ifdef USE_VM_PROBES + Sint tok_label = 0; + Sint tok_lastcnt = 0; + Sint tok_serial = 0; + Uint32 msize = 0; DTRACE_CHARBUF(node_name, 64); DTRACE_CHARBUF(sender_name, 64); DTRACE_CHARBUF(receiver_name, 128); +#endif UseTmpHeapNoproc(6); if (SEQ_TRACE_TOKEN(sender) != NIL @@ -816,6 +822,7 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message) token = SEQ_TRACE_TOKEN(sender); seq_trace_output(token, message, SEQ_TRACE_SEND, remote_name, sender); } +#ifdef USE_VM_PROBES *node_name = *sender_name = *receiver_name = '\0'; if (DTRACE_ENABLED(message_send) || DTRACE_ENABLED(message_send_remote)) { erts_snprintf(node_name, sizeof(node_name), "%T", dsdp->dep->sysname); @@ -829,6 +836,7 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message) tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); } } +#endif if (token != NIL) ctl = TUPLE5(&ctl_heap[0], make_small(DOP_REG_SEND_TT), @@ -853,14 +861,16 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote, Eterm ctl; DeclareTmpHeapNoproc(ctl_heap,6); int res; +#ifdef USE_VM_PROBES Process *sender = dsdp->proc; - ERTS_DECLARE_DUMMY(Sint tok_label) = 0; - ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0; - ERTS_DECLARE_DUMMY(Sint tok_serial) = 0; + Sint tok_label = 0; + Sint tok_lastcnt = 0; + Sint tok_serial = 0; DTRACE_CHARBUF(node_name, 64); DTRACE_CHARBUF(sender_name, 64); DTRACE_CHARBUF(remote_name, 128); DTRACE_CHARBUF(reason_str, 128); +#endif UseTmpHeapNoproc(6); if (token != NIL @@ -875,6 +885,7 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote, } else { ctl = TUPLE4(&ctl_heap[0], make_small(DOP_EXIT), local, remote, reason); } +#ifdef USE_VM_PROBES *node_name = *sender_name = *remote_name = '\0'; if (DTRACE_ENABLED(process_exit_signal_remote)) { erts_snprintf(node_name, sizeof(node_name), "%T", dsdp->dep->sysname); @@ -888,6 +899,7 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote, tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token)); } } +#endif DTRACE7(process_exit_signal_remote, sender_name, node_name, remote_name, reason_str, tok_label, tok_lastcnt, tok_serial); /* forced, i.e ignore busy */ @@ -1706,6 +1718,7 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy) if (!(dep->qflgs & ERTS_DE_QFLG_BUSY)) { if (suspended) resume = 1; /* was busy when we started, but isn't now */ +#ifdef USE_VM_PROBES if (resume && DTRACE_ENABLED(dist_port_not_busy)) { DTRACE_CHARBUF(port_str, 64); DTRACE_CHARBUF(remote_str, 64); @@ -1716,6 +1729,7 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy) DTRACE3(dist_port_not_busy, erts_this_node_sysname, port_str, remote_str); } +#endif } else { /* Enqueue suspended process on dist entry */ @@ -1765,6 +1779,7 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy) } if (suspended) { +#ifdef USE_VM_PROBES if (!resume && DTRACE_ENABLED(dist_port_busy)) { DTRACE_CHARBUF(port_str, 64); DTRACE_CHARBUF(remote_str, 64); @@ -1776,6 +1791,7 @@ dsig_send(ErtsDSigData *dsdp, Eterm ctl, Eterm msg, int force_busy) DTRACE4(dist_port_busy, erts_this_node_sysname, port_str, remote_str, pid_str); } +#endif if (!resume && erts_system_monitor_flags.busy_dist_port) monitor_generic(c_p, am_busy_dist_port, cid); return ERTS_DSIG_SEND_YIELD; @@ -1799,6 +1815,7 @@ dist_port_command(Port *prt, ErtsDistOutputBuf *obuf) "(%beu bytes) passed.\n", size); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(dist_output)) { DTRACE_CHARBUF(port_str, 64); DTRACE_CHARBUF(remote_str, 64); @@ -1809,6 +1826,7 @@ dist_port_command(Port *prt, ErtsDistOutputBuf *obuf) DTRACE4(dist_output, erts_this_node_sysname, port_str, remote_str, size); } +#endif prt->caller = NIL; fpe_was_unmasked = erts_block_fpe(); (*prt->drv_ptr->output)((ErlDrvData) prt->drv_data, @@ -1851,6 +1869,7 @@ dist_port_commandv(Port *prt, ErtsDistOutputBuf *obuf) ASSERT(prt->drv_ptr->outputv); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(dist_outputv)) { DTRACE_CHARBUF(port_str, 64); DTRACE_CHARBUF(remote_str, 64); @@ -1861,6 +1880,7 @@ dist_port_commandv(Port *prt, ErtsDistOutputBuf *obuf) DTRACE4(dist_outputv, erts_this_node_sysname, port_str, remote_str, size); } +#endif prt->caller = NIL; fpe_was_unmasked = erts_block_fpe(); (*prt->drv_ptr->outputv)((ErlDrvData) prt->drv_data, &eiov); @@ -2180,6 +2200,7 @@ erts_dist_command(Port *prt, int reds_limit) void erts_dist_port_not_busy(Port *prt) { +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(dist_port_not_busy)) { DTRACE_CHARBUF(port_str, 64); DTRACE_CHARBUF(remote_str, 64); @@ -2190,6 +2211,7 @@ erts_dist_port_not_busy(Port *prt) DTRACE3(dist_port_not_busy, erts_this_node_sysname, port_str, remote_str); } +#endif erts_schedule_dist_command(prt, NULL); } @@ -3127,6 +3149,7 @@ send_nodes_mon_msgs(Process *c_p, Eterm what, Eterm node, Eterm type, Eterm reas ASSERT(is_immed(what)); ASSERT(is_immed(node)); ASSERT(is_immed(type)); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(dist_monitor)) { DTRACE_CHARBUF(what_str, 12); DTRACE_CHARBUF(node_str, 64); @@ -3140,6 +3163,7 @@ send_nodes_mon_msgs(Process *c_p, Eterm what, Eterm node, Eterm type, Eterm reas DTRACE5(dist_monitor, erts_this_node_sysname, what_str, node_str, type_str, reason_str); } +#endif ERTS_SMP_LC_ASSERT(!c_p || (erts_proc_lc_my_proc_locks(c_p) diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c index b8cb3c6cc4..f0e98b33a5 100644 --- a/erts/emulator/beam/erl_async.c +++ b/erts/emulator/beam/erl_async.c @@ -270,6 +270,7 @@ static ERTS_INLINE void async_add(ErtsAsync *a, ErtsAsyncQ* q) #endif erts_thr_q_enqueue(&q->thr_q, a); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(aio_pool_add)) { DTRACE_CHARBUF(port_str, 16); @@ -278,6 +279,7 @@ static ERTS_INLINE void async_add(ErtsAsync *a, ErtsAsyncQ* q) len = -1; DTRACE2(aio_pool_add, port_str, len); } +#endif gcc_optimizer_hack++; } @@ -301,6 +303,7 @@ static ERTS_INLINE ErtsAsync *async_get(ErtsThrQ_t *q, if (saved_fin_deq) erts_thr_q_append_finalize_dequeue_data(&a->q.fin_deq, &fin_deq); #endif +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(aio_pool_get)) { DTRACE_CHARBUF(port_str, 16); @@ -309,6 +312,7 @@ static ERTS_INLINE ErtsAsync *async_get(ErtsThrQ_t *q, len = -1; DTRACE2(aio_pool_get, port_str, len); } +#endif return a; } diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index 8caa64b97d..3056319809 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -344,6 +344,7 @@ port_call(Process* c_p, Eterm arg1, Eterm arg2, Eterm arg3) __FILE__, __LINE__, endp - (bytes + size)); } erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(driver_call)) { DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); @@ -352,6 +353,7 @@ port_call(Process* c_p, Eterm arg1, Eterm arg2, Eterm arg3) dtrace_port_str(p, port_str); DTRACE5(driver_call, process_str, port_str, p->name, op, real_size); } +#endif prc = (char *) port_resp; fpe_was_unmasked = erts_block_fpe(); ret = drv->call((ErlDrvData)p->drv_data, @@ -548,6 +550,7 @@ BIF_RETTYPE port_connect_2(BIF_ALIST_2) prt->connected = pid; /* internal pid */ erts_smp_port_unlock(prt); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(port_connect)) { DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); @@ -558,6 +561,7 @@ BIF_RETTYPE port_connect_2(BIF_ALIST_2) dtrace_proc_str(rp, newprocess_str); DTRACE4(port_connect, process_str, port_str, prt->name, newprocess_str); } +#endif BIF_RET(am_true); } @@ -923,6 +927,7 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_nump) erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN); port_num = erts_open_driver(driver, p->id, name_buf, &opts, err_nump); +#ifdef USE_VM_PROBES if (port_num >= 0 && DTRACE_ENABLED(port_open)) { DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); @@ -931,7 +936,7 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_nump) erts_snprintf(port_str, sizeof(port_str), "%T", erts_port[port_num].id); DTRACE3(port_open, process_str, name_buf, port_str); } - +#endif erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN); if (port_num < 0) { diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 2e340a7ef1..82f2dc6091 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -350,8 +350,9 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj) Uint reclaimed_now = 0; int done = 0; Uint ms1, s1, us1; +#ifdef USE_VM_PROBES DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); - +#endif if (IS_TRACED_FL(p, F_TRACE_GC)) { trace_gc(p, am_gc_start); } @@ -371,7 +372,7 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj) if (GEN_GCS(p) >= MAX_GEN_GCS(p)) { FLAGS(p) |= F_NEED_FULLSWEEP; } - +#ifdef USE_VM_PROBES *pidbuf = '\0'; if (DTRACE_ENABLED(gc_major_start) || DTRACE_ENABLED(gc_major_end) @@ -379,7 +380,7 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj) || DTRACE_ENABLED(gc_minor_end)) { dtrace_proc_str(p, pidbuf); } - +#endif /* * Test which type of GC to do. */ @@ -1132,12 +1133,14 @@ do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj) sys_memcpy(n_heap + new_sz - n, p->stop, n * sizeof(Eterm)); p->stop = n_heap + new_sz - n; +#ifdef USE_VM_PROBES if (HEAP_SIZE(p) != new_sz && DTRACE_ENABLED(process_heap_grow)) { DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); dtrace_proc_str(p, pidbuf); DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz); } +#endif ERTS_HEAP_FREE(ERTS_ALC_T_HEAP, (void*)HEAP_START(p), @@ -1360,12 +1363,14 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl) sys_memcpy(n_heap + new_sz - n, p->stop, n * sizeof(Eterm)); p->stop = n_heap + new_sz - n; +#ifdef USE_VM_PROBES if (HEAP_SIZE(p) != new_sz && DTRACE_ENABLED(process_heap_grow)) { DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); dtrace_proc_str(p, pidbuf); DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz); } +#endif ERTS_HEAP_FREE(ERTS_ALC_T_HEAP, (void *) HEAP_START(p), @@ -2044,12 +2049,14 @@ grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj) HEAP_START(p) = new_heap; } +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(process_heap_grow)) { DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); dtrace_proc_str(p, pidbuf); DTRACE3(process_heap_grow, pidbuf, HEAP_SIZE(p), new_sz); } +#endif HEAP_SIZE(p) = new_sz; } @@ -2089,12 +2096,14 @@ shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj) HEAP_START(p) = new_heap; } +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(process_heap_shrink)) { DTRACE_CHARBUF(pidbuf, DTRACE_TERM_BUF_SIZE); dtrace_proc_str(p, pidbuf); DTRACE3(process_heap_shrink, pidbuf, HEAP_SIZE(p), new_sz); } +#endif HEAP_SIZE(p) = new_sz; } diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index 7de30d25ed..4cdf2d7d09 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -336,9 +336,11 @@ erts_queue_dist_message(Process *rcvr, Eterm token) { ErlMessage* mp; - ERTS_DECLARE_DUMMY(Sint tok_label) = 0; - ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0; - ERTS_DECLARE_DUMMY(Sint tok_serial) = 0; +#ifdef USE_VM_PROBES + Sint tok_label = 0; + Sint tok_lastcnt = 0; + Sint tok_serial = 0; +#endif #ifdef ERTS_SMP ErtsProcLocks need_locks; #endif @@ -380,6 +382,7 @@ erts_queue_dist_message(Process *rcvr, message_free(mp); msg = erts_msg_distext2heap(rcvr, rcvr_locks, &mbuf, &token, dist_ext); if (is_value(msg)) +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(message_queued)) { DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE); @@ -393,6 +396,7 @@ erts_queue_dist_message(Process *rcvr, receiver_name, size_object(msg), rcvr->msg.len, tok_label, tok_lastcnt, tok_serial); } +#endif erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token #ifdef USE_VM_PROBES , NIL @@ -415,6 +419,7 @@ erts_queue_dist_message(Process *rcvr, #endif mp->next = NULL; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(message_queued)) { DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE); @@ -431,6 +436,7 @@ erts_queue_dist_message(Process *rcvr, DTRACE6(message_queued, receiver_name, -1, rcvr->msg.len + 1, tok_label, tok_lastcnt, tok_serial); } +#endif mp->data.dist_ext = dist_ext; LINK_MESSAGE(rcvr, mp); @@ -515,11 +521,12 @@ erts_queue_message(Process* receiver, LINK_MESSAGE(receiver, mp); #endif +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(message_queued)) { DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE); - ERTS_DECLARE_DUMMY(Sint tok_label) = 0; - ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0; - ERTS_DECLARE_DUMMY(Sint tok_serial) = 0; + Sint tok_label = 0; + Sint tok_lastcnt = 0; + Sint tok_serial = 0; dtrace_proc_str(receiver, receiver_name); if (seq_trace_token != NIL && is_tuple(seq_trace_token)) { @@ -531,7 +538,7 @@ erts_queue_message(Process* receiver, receiver_name, size_object(message), receiver->msg.len, tok_label, tok_lastcnt, tok_serial); } - +#endif notify_new_message(receiver); if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) { @@ -884,21 +891,24 @@ erts_send_message(Process* sender, Uint msize; ErlHeapFragment* bp = NULL; Eterm token = NIL; +#ifdef USE_VM_PROBES DTRACE_CHARBUF(sender_name, 64); DTRACE_CHARBUF(receiver_name, 64); - ERTS_DECLARE_DUMMY(Sint tok_label) = 0; - ERTS_DECLARE_DUMMY(Sint tok_lastcnt) = 0; - ERTS_DECLARE_DUMMY(Sint tok_serial) = 0; - + Sint tok_label = 0; + Sint tok_lastcnt = 0; + Sint tok_serial = 0; +#endif BM_STOP_TIMER(system); BM_MESSAGE(message,sender,receiver); BM_START_TIMER(send); + #ifdef USE_VM_PROBES *sender_name = *receiver_name = '\0'; - if (DTRACE_ENABLED(message_send)) { + if (DTRACE_ENABLED(message_send)) { erts_snprintf(sender_name, sizeof(sender_name), "%T", sender->id); erts_snprintf(receiver_name, sizeof(receiver_name), "%T", receiver->id); } +#endif if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) { Eterm* hp; Eterm stoken = SEQ_TRACE_TOKEN(sender); @@ -956,6 +966,7 @@ erts_send_message(Process* sender, BM_MESSAGE_COPIED(msize); BM_SWAP_TIMER(copy,send); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(message_send)) { if (stoken != NIL && stoken != am_have_dt_utag) { tok_label = signed_val(SEQ_TRACE_T_LABEL(stoken)); @@ -965,6 +976,7 @@ erts_send_message(Process* sender, DTRACE6(message_send, sender_name, receiver_name, msize, tok_label, tok_lastcnt, tok_serial); } +#endif erts_queue_message(receiver, receiver_locks, bp, diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 156783d057..40f2fde578 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -66,7 +66,9 @@ static void add_readonly_check(ErlNifEnv*, unsigned char* ptr, unsigned sz); static int is_offheap(const ErlOffHeap* off_heap); #endif +#ifdef USE_VM_PROBES void dtrace_nifenv_str(ErlNifEnv *, char *); +#endif #define MIN_HEAP_FRAG_SZ 200 static Eterm* alloc_heap_heavy(ErlNifEnv* env, unsigned need, Eterm* hp); @@ -1784,10 +1786,12 @@ void erl_nif_init() resource_type_list.name = THE_NON_VALUE; } +#ifdef USE_VM_PROBES void dtrace_nifenv_str(ErlNifEnv *env, char *process_buf) { dtrace_pid_str(env->proc->id, process_buf); } +#endif #ifdef READONLY_CHECK /* Use checksums to assert that NIFs do not write into inspected binaries diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index 25bba5cf17..a8cb4563d6 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -62,6 +62,7 @@ do { \ (P)->sched.next = NULL; \ } while (0) +#ifdef USE_VM_PROBES #define DTRACE_DRIVER(PROBE_NAME, PP) \ if (DTRACE_ENABLED(driver_ready_input)) { \ DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); \ @@ -71,6 +72,9 @@ do { \ dtrace_port_str(PP, port_str); \ DTRACE3(PROBE_NAME, process_str, port_str, PP->name); \ } +#else +#define DTRACE_DRIVER(PROBE_NAME, PP) do {} while(0) +#endif erts_smp_atomic_t erts_port_task_outstanding_io_tasks; diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index f678d4159d..ff4e9c3d88 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -6219,12 +6219,14 @@ Process *schedule(Process *p, int calls) int actual_reds; int reds; +#ifdef USE_VM_PROBES if (p != NULL && DTRACE_ENABLED(process_unscheduled)) { DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE); dtrace_proc_str(p, process_buf); DTRACE1(process_unscheduled, process_buf); } +#endif if (ERTS_USE_MODIFIED_TIMING()) { context_reds = ERTS_MODIFIED_TIMING_CONTEXT_REDS; @@ -7400,6 +7402,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). VERBOSE(DEBUG_PROCESSES, ("Created a new process: %T\n",p->id)); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(process_spawn)) { DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); @@ -7407,6 +7410,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). dtrace_fun_decode(p, mod, func, arity, process_name, mfa); DTRACE2(process_spawn, process_name, mfa); } +#endif error: @@ -7988,6 +7992,7 @@ send_exit_signal(Process *c_p, /* current process if and only ASSERT(reason != THE_NON_VALUE); +#ifdef USE_VM_PROBES if(DTRACE_ENABLED(process_exit_signal) && is_pid(from)) { DTRACE_CHARBUF(sender_str, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(receiver_str, DTRACE_TERM_BUF_SIZE); @@ -7998,6 +8003,7 @@ send_exit_signal(Process *c_p, /* current process if and only erts_snprintf(reason_buf, sizeof(reason_buf) - 1, "%T", reason); DTRACE3(process_exit_signal, sender_str, receiver_str, reason_buf); } +#endif if (ERTS_PROC_IS_TRAPPING_EXITS(rp) && (reason != am_kill || (flags & ERTS_XSIG_FLG_IGN_KILL))) { @@ -8430,6 +8436,7 @@ erts_do_exit_process(Process* p, Eterm reason) p->arity = 0; /* No live registers */ p->fvalue = reason; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(process_exit)) { DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(reason_buf, 256); @@ -8438,6 +8445,7 @@ erts_do_exit_process(Process* p, Eterm reason) erts_snprintf(reason_buf, sizeof(reason_buf) - 1, "%T", reason); DTRACE2(process_exit, process_buf, reason_buf); } +#endif #ifdef ERTS_SMP ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p); diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 9425576980..8a2a43bebd 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -181,6 +181,7 @@ typedef struct line_buf_context { #define LINEBUF_INITIAL 100 +#ifdef USE_VM_PROBES #define DTRACE_FORMAT_COMMON_PID_AND_PORT(PID, PORT) \ DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); \ DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); \ @@ -193,7 +194,7 @@ typedef struct line_buf_context { \ dtrace_proc_str((PID), process_str); \ dtrace_port_str((PORT), port_str); - +#endif /* The 'number' field in a port now has two parts: the lowest bits contain the index in the port table, and the higher bits are a counter @@ -653,10 +654,12 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */ trace_sched_ports_where(port, am_in, am_start); } port->caller = pid; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(driver_start)) { DTRACE_FORMAT_COMMON_PID_AND_PORT(pid, port) DTRACE3(driver_start, process_str, driver->name, port_str); } +#endif fpe_was_unmasked = erts_block_fpe(); drv_data = (*driver->start)((ErlDrvPort)(port_ix), name, opts); @@ -1188,10 +1191,12 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list) ev.size = size; /* total size */ ev.iov = ivp; ev.binv = bvp; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(driver_outputv)) { DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p) DTRACE4(driver_outputv, process_str, port_str, p->name, size); } +#endif fpe_was_unmasked = erts_block_fpe(); (*drv->outputv)((ErlDrvData)p->drv_data, &ev); erts_unblock_fpe(fpe_was_unmasked); @@ -1211,17 +1216,21 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list) buf = erts_alloc(ERTS_ALC_T_TMP, size+1); r = io_list_to_buf(list, buf, size); +#ifdef USE_VM_PROBES if(DTRACE_ENABLED(port_command)) { DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p) DTRACE4(port_command, process_str, port_str, p->name, "command"); } +#endif if (r >= 0) { size -= r; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(driver_output)) { DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p) DTRACE4(driver_output, process_str, port_str, p->name, size); } +#endif fpe_was_unmasked = erts_block_fpe(); (*drv->output)((ErlDrvData)p->drv_data, buf, size); erts_unblock_fpe(fpe_was_unmasked); @@ -1245,10 +1254,12 @@ int erts_write_to_port(Eterm caller_id, Port *p, Eterm list) */ buf = erts_alloc(ERTS_ALC_T_TMP, size+1); r = io_list_to_buf(list, buf, size); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(driver_output)) { DTRACE_FORMAT_COMMON_PID_AND_PORT(caller_id, p) DTRACE4(driver_output, process_str, port_str, p->name, size); } +#endif fpe_was_unmasked = erts_block_fpe(); (*drv->output)((ErlDrvData)p->drv_data, buf, size); erts_unblock_fpe(fpe_was_unmasked); @@ -1857,10 +1868,12 @@ static void flush_port(Port *p) ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p)); if (p->drv_ptr->flush != NULL) { +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(driver_flush)) { DTRACE_FORMAT_COMMON_PID_AND_PORT(p->connected, p) DTRACE3(driver_flush, process_str, port_str, p->name); } +#endif if (IS_TRACED_FL(p, F_TRACE_SCHED_PORTS)) { trace_sched_ports_where(p, am_in, am_flush); } @@ -1916,10 +1929,12 @@ terminate_port(Port *prt) drv = prt->drv_ptr; if ((drv != NULL) && (drv->stop != NULL)) { int fpe_was_unmasked = erts_block_fpe(); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(driver_stop)) { DTRACE_FORMAT_COMMON_PID_AND_PORT(prt->connected, prt) DTRACE3(driver_stop, process_str, drv->name, port_str); } +#endif (*drv->stop)((ErlDrvData)prt->drv_data); erts_unblock_fpe(fpe_was_unmasked); #ifdef ERTS_SMP @@ -2081,6 +2096,7 @@ erts_do_exit_port(Port *p, Eterm from, Eterm reason) rreason = (reason == am_kill) ? am_killed : reason; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(port_exit)) { DTRACE_CHARBUF(from_str, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); @@ -2091,6 +2107,7 @@ erts_do_exit_port(Port *p, Eterm from, Eterm reason) erts_snprintf(rreason_str, sizeof(rreason_str), "%T", rreason); DTRACE4(port_exit, from_str, port_str, p->name, rreason_str); } +#endif if ((p->status & (ERTS_PORT_SFLGS_DEAD | ERTS_PORT_SFLG_EXITING @@ -2193,10 +2210,12 @@ void erts_port_command(Process *proc, erts_port_status_bor_set(port, ERTS_PORT_SFLG_SEND_CLOSED); erts_do_exit_port(port, pid, am_normal); +#ifdef USE_VM_PROBES if(DTRACE_ENABLED(port_command)) { DTRACE_FORMAT_COMMON_PROC_AND_PORT(proc, port) DTRACE4(port_command, process_str, port_str, port->name, "close"); } +#endif goto done; } else if (is_tuple_arity(tp[2], 2)) { tp = tuple_val(tp[2]); @@ -2204,10 +2223,12 @@ void erts_port_command(Process *proc, if (erts_write_to_port(caller_id, port, tp[2]) == 0) goto done; } else if ((tp[1] == am_connect) && is_internal_pid(tp[2])) { +#ifdef USE_VM_PROBES if(DTRACE_ENABLED(port_command)) { DTRACE_FORMAT_COMMON_PROC_AND_PORT(proc, port) DTRACE4(port_command, process_str, port_str, port->name, "connect"); } +#endif port->connected = tp[2]; deliver_result(port->id, pid, am_connected); goto done; @@ -2310,12 +2331,14 @@ erts_port_control(Process* p, Port* prt, Uint command, Eterm iolist) erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN); ERTS_SMP_CHK_NO_PROC_LOCKS; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(port_control) || DTRACE_ENABLED(driver_control)) { DTRACE_FORMAT_COMMON_PROC_AND_PORT(p, prt); DTRACE4(port_control, process_str, port_str, prt->name, command); DTRACE5(driver_control, process_str, port_str, prt->name, command, to_len); } +#endif /* * Call the port's control routine. @@ -2457,7 +2480,9 @@ print_port_info(int to, void *arg, int i) void set_busy_port(ErlDrvPort port_num, int on) { +#ifdef USE_VM_PROBES DTRACE_CHARBUF(port_str, 16); +#endif ERTS_SMP_CHK_NO_PROC_LOCKS; @@ -2466,22 +2491,26 @@ set_busy_port(ErlDrvPort port_num, int on) if (on) { erts_port_status_bor_set(&erts_port[port_num], ERTS_PORT_SFLG_PORT_BUSY); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(port_busy)) { erts_snprintf(port_str, sizeof(port_str), "%T", erts_port[port_num].id); DTRACE1(port_busy, port_str); } +#endif } else { ErtsProcList* plp = erts_port[port_num].suspended; erts_port_status_band_set(&erts_port[port_num], ~ERTS_PORT_SFLG_PORT_BUSY); erts_port[port_num].suspended = NULL; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(port_not_busy)) { erts_snprintf(port_str, sizeof(port_str), "%T", erts_port[port_num].id); DTRACE1(port_not_busy, port_str); } +#endif if (erts_port[port_num].dist_entry) { /* * Processes suspended on distribution ports are @@ -2499,6 +2528,7 @@ set_busy_port(ErlDrvPort port_num, int on) */ if (plp) { +#ifdef USE_VM_PROBES /* * Hrm, for blocked dist ports, plp always seems to be NULL. * That's not so fun. @@ -2519,6 +2549,7 @@ set_busy_port(ErlDrvPort port_num, int on) DTRACE2(process_port_unblocked, pid_str, port_str); } } +#endif /* First proc should be resumed last */ if (plp->next) { erts_resume_processes(plp->next); @@ -2565,12 +2596,14 @@ void erts_raw_port_command(Port* p, byte* buf, Uint len) p->drv_ptr->name ? p->drv_ptr->name : "unknown"); p->caller = NIL; +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(driver_output)) { DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); dtrace_port_str(p, port_str); DTRACE4(driver_output, "-raw-", port_str, p->name, len); } +#endif fpe_was_unmasked = erts_block_fpe(); (*p->drv_ptr->output)((ErlDrvData)p->drv_data, (char*) buf, (int) len); erts_unblock_fpe(fpe_was_unmasked); @@ -2586,10 +2619,12 @@ int async_ready(Port *p, void* data) ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p)); ASSERT(!(p->status & ERTS_PORT_SFLGS_DEAD)); if (p->drv_ptr->ready_async != NULL) { +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(driver_ready_async)) { DTRACE_FORMAT_COMMON_PID_AND_PORT(p->connected, p) DTRACE3(driver_ready_async, process_str, port_str, p->name); } +#endif (*p->drv_ptr->ready_async)((ErlDrvData)p->drv_data, data); need_free = 0; #ifdef ERTS_SMP @@ -4573,10 +4608,12 @@ void erts_fire_port_monitor(Port *prt, Eterm ref) ASSERT(callback != NULL); ref_to_driver_monitor(ref,&drv_monitor); DRV_MONITOR_UNLOCK_PDL(prt); +#ifdef USE_VM_PROBES if (DTRACE_ENABLED(driver_process_exit)) { DTRACE_FORMAT_COMMON_PID_AND_PORT(prt->connected, prt) DTRACE3(driver_process_exit, process_str, port_str, prt->name); } +#endif fpe_was_unmasked = erts_block_fpe(); (*callback)((ErlDrvData) (prt->drv_data), &drv_monitor); erts_unblock_fpe(fpe_was_unmasked); diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c index cb7ef95f00..1d173a758a 100644 --- a/erts/emulator/sys/common/erl_check_io.c +++ b/erts/emulator/sys/common/erl_check_io.c @@ -498,7 +498,9 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix, ErtsDrvEventState *state; int wake_poller; int ret; +#ifdef USE_VM_PROBES DTRACE_CHARBUF(name, 64); +#endif ERTS_SMP_LC_ASSERT(erts_drvport2port(ix) && erts_lc_is_port_locked(erts_drvport2port(ix))); @@ -528,8 +530,10 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix, if (IS_FD_UNKNOWN(state)) { /* fast track to stop_select callback */ stop_select_fn = erts_drvport2port(ix)->drv_ptr->stop_select; +#ifdef USE_VM_PROBES strncpy(name, erts_drvport2port(ix)->drv_ptr->name, sizeof(name)-1); name[sizeof(name)-1] = '\0'; +#endif ret = 0; goto done_unknown; } @@ -666,8 +670,10 @@ ERTS_CIO_EXPORT(driver_select)(ErlDrvPort ix, /* Safe to close fd now as it is not in pollset or there was no need to eject fd (kernel poll) */ stop_select_fn = drv_ptr->stop_select; +#ifdef USE_VM_PROBES strncpy(name, erts_drvport2port(ix)->drv_ptr->name, sizeof(name)-1); name[sizeof(name)-1] = '\0'; +#endif } else { /* Not safe to close fd, postpone stop_select callback. */ -- cgit v1.2.3 From c7f21d552b8034baecf8e7d078da5c9243826d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 9 Mar 2012 15:53:29 +0100 Subject: beam_makeops: Add a simple preprocessor --- erts/emulator/utils/beam_makeops | 54 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops index 58c36c3bdc..ea57000c82 100755 --- a/erts/emulator/utils/beam_makeops +++ b/erts/emulator/utils/beam_makeops @@ -28,6 +28,7 @@ my $verbose = 0; my $hot = 1; my $num_file_opcodes = 0; my $wordsize = 32; +my %defs; # Defines (from command line). # This is shift counts and mask for the packer. my $WHOLE_WORD = ''; @@ -95,6 +96,12 @@ my %unnumbered; my %is_transformed; +# +# Pre-processor. +# +my @if_val; +my @if_line; + # # Code transformations. # @@ -223,6 +230,7 @@ while (@ARGV && $ARGV[0] =~ /^-(.*)/) { ($outdir = shift), next if /^outdir/; ($wordsize = shift), next if /^wordsize/; ($verbose = 1), next if /^v/; + ($defs{$1} = $2), next if /^D(\w+)=(\w+)/; die "$0: Bad option: -$_\n"; } @@ -239,7 +247,43 @@ while (<>) { } next if /^\s*$/; next if /^\#/; - + + # + # Handle %if. + # + if (/^\%if (\w+)/) { + my $name = $1; + my $val = $defs{$name}; + defined $val or error("'$name' is undefined"); + push @if_val, $val; + push @if_line, $.; + next; + } elsif (/^\%unless (\w+)/) { + my $name = $1; + my $val = $defs{$name}; + defined $val or error("'$name' is undefined"); + push @if_val, !$val; + push @if_line, $.; + next; + } elsif (/^\%else$/) { + unless (@if_line) { + error("%else without a preceding %if/%unless"); + } + $if_line[$#if_line] = $.; + $if_val[$#if_val] = !$if_val[$#if_val]; + next; + } elsif (/^\%endif$/) { + unless (@if_line) { + error("%endif without a preceding %if/%unless/%else"); + } + pop @if_val; + pop @if_line; + next; + } + if (@if_val and not $if_val[$#if_val]) { + next; + } + # # Handle assignments. # @@ -349,7 +393,13 @@ while (<>) { $unnumbered{$name,$arity} = 1; } } continue { - close(ARGV) if eof(ARGV); + if (eof(ARGV)) { + close(ARGV); + if (@if_line) { + error("Unterminated %if/%unless/%else at " . + "line $if_line[$#if_line]\n"); + } + } } $num_file_opcodes = @gen_opname; -- cgit v1.2.3 From c79e1106853bcfdabe7325a7073ce911ef75afaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 9 Mar 2012 14:47:23 +0100 Subject: If VM probes are not enabled, short-circuit calls to probe BIFs --- erts/emulator/Makefile.in | 2 ++ erts/emulator/beam/ops.tab | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) (limited to 'erts/emulator') diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index d8fad98de2..2efbe2d57e 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -25,6 +25,7 @@ ENABLE_ALLOC_TYPE_VARS = @ENABLE_ALLOC_TYPE_VARS@ HIPE_ENABLED=@HIPE_ENABLED@ DTRACE_ENABLED=@DTRACE_ENABLED@ DTRACE_ENABLED_2STEP=@DTRACE_ENABLED_2STEP@ +USE_VM_PROBES=@USE_VM_PROBES@ LIBS = @LIBS@ Z_LIB=@Z_LIB@ NO_INLINE_FUNCTIONS=false @@ -508,6 +509,7 @@ $(TTF_DIR)/OPCODES-GENERATED: $(OPCODE_TABLES) utils/beam_makeops LANG=C $(PERL) utils/beam_makeops \ -wordsize @EXTERNAL_WORD_SIZE@ \ -outdir $(TTF_DIR) \ + -DUSE_VM_PROBES=$(if $(USE_VM_PROBES),1,0) \ -emulator $(OPCODE_TABLES) && echo $? >$(TTF_DIR)/OPCODES-GENERATED GENERATE += $(TTF_DIR)/OPCODES-GENERATED diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab index fc53a88a3a..edc935e1ff 100644 --- a/erts/emulator/beam/ops.tab +++ b/erts/emulator/beam/ops.tab @@ -882,6 +882,95 @@ call_ext u==3 u$func:erlang:hibernate/3 => i_hibernate call_ext_last u==3 u$func:erlang:hibernate/3 D => i_hibernate call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate +# +# If VM probes are not enabled, we want to short-circult calls to +# the utag BIFs to make them as cheap as possible. +# + +%unless USE_VM_PROBES + +call_ext Arity u$func:erlang:get_utag/0 => \ + move a=am_undefined r +call_ext_last Arity u$func:erlang:get_utag/0 D => \ + move a=am_undefined r | deallocate D | return +call_ext_only Arity u$func:erlang:get_utag/0 => \ + move a=am_undefined r | return + +move Any r | call_ext Arity u$func:erlang:put_utag/1 => \ + move a=am_undefined r +move Any r | call_ext_last Arity u$func:erlang:put_utag/1 D => \ + move a=am_undefined r | deallocate D | return +move Any r | call_ext_only Arity u$func:erlang:put_utag/1 => \ + move a=am_undefined r | return +call_ext Arity u$func:erlang:put_utag/1 => \ + move a=am_undefined r +call_ext_last Arity u$func:erlang:put_utag/1 D => \ + move a=am_undefined r | deallocate D | return +call_ext_only Arity u$func:erlang:put_utag/1 => \ + move a=am_undefined r | return + +call_ext Arity u$func:erlang:get_utag_data/0 => \ + move a=am_undefined r +call_ext_last Arity u$func:erlang:get_utag_data/0 D => \ + move a=am_undefined r | deallocate D | return +call_ext_only Arity u$func:erlang:get_utag_data/0 => \ + move a=am_undefined r | return + +move Any r | call_ext Arity u$func:erlang:spread_utag/1 => \ + move a=am_true r +move Any r | call_ext_last Arity u$func:erlang:spread_utag/1 D => \ + move a=am_true r | deallocate D | return +move Any r | call_ext_only Arity u$func:erlang:spread_utag/1 => \ + move a=am_true r | return +call_ext Arity u$func:erlang:spread_utag/1 => \ + move a=am_true r +call_ext_last Arity u$func:erlang:spread_utag/1 D => \ + move a=am_true r | deallocate D | return +call_ext_only Arity u$func:erlang:spread_utag/1 => \ + move a=am_true r | return + +move Any r | call_ext Arity u$func:erlang:restore_utag/1 => \ + move a=am_true r +move Any r | call_ext_last Arity u$func:erlang:restore_utag/1 D => \ + move a=am_true r | deallocate D | return +move Any r | call_ext_only Arity u$func:erlang:restore_utag/1 => \ + move a=am_true r | return +call_ext Arity u$func:erlang:restore_utag/1 => \ + move a=am_true r +call_ext_last Arity u$func:erlang:restore_utag/1 D => \ + move a=am_true r | deallocate D | return +call_ext_only Arity u$func:erlang:restore_utag/1 => \ + move a=am_true r | return + +move Any r | call_ext Arity u$func:erlang:prepend_vm_utag_data/1 => \ + move Any r +move Any r | call_ext_last Arity u$func:erlang:prepend_vm_utag_data/1 D => \ + move Any r | deallocate D | return +move Any r | call_ext_only Arity u$func:erlang:prepend_vm_utag_data/1 => \ + move Any r | return +call_ext Arity u$func:erlang:prepend_vm_utag_data/1 => +call_ext_last Arity u$func:erlang:prepend_vm_utag_data/1 D => \ + deallocate D | return +call_ext_only Arity u$func:erlang:prepend_vm_utag_data/1 => \ + return + +move Any r | call_ext Arity u$func:erlang:append_vm_utag_data/1 => \ + move Any r +move Any r | call_ext_last Arity u$func:erlang:append_vm_utag_data/1 D => \ + move Any r | deallocate D | return +move Any r | call_ext_only Arity u$func:erlang:append_vm_utag_data/1 => \ + move Any r | return +call_ext Arity u$func:erlang:append_vm_utag_data/1 => +call_ext_last Arity u$func:erlang:append_vm_utag_data/1 D => \ + deallocate D | return +call_ext_only Arity u$func:erlang:append_vm_utag_data/1 => \ + return + +# Can happen after one of the transformations above. +move Discarded r | move Something r => move Something r + +%endif + # # The general case for BIFs that have no special instructions. # A BIF used in the tail must be followed by a return instruction. -- cgit v1.2.3 From 560cea59eeee117f0170772d4edee820b6fc96d9 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Wed, 21 Mar 2012 14:54:00 +0100 Subject: Rename dyntrace BIFs to more suiting names --- erts/emulator/beam/bif.c | 14 ++++----- erts/emulator/beam/bif.tab | 14 ++++----- erts/emulator/beam/ops.tab | 74 +++++++++++++++++++++++----------------------- 3 files changed, 51 insertions(+), 51 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 2adc713959..39d4582435 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -4647,7 +4647,7 @@ BIF_RETTYPE get_module_info_2(BIF_ALIST_2) BIF_RET(ret); } -BIF_RETTYPE put_utag_1(BIF_ALIST_1) +BIF_RETTYPE dt_put_tag_1(BIF_ALIST_1) { #ifdef USE_VM_PROBES Eterm otag; @@ -4675,7 +4675,7 @@ BIF_RETTYPE put_utag_1(BIF_ALIST_1) #endif } -BIF_RETTYPE get_utag_0(BIF_ALIST_0) +BIF_RETTYPE dt_get_tag_0(BIF_ALIST_0) { #ifdef USE_VM_PROBES BIF_RET((DT_UTAG(BIF_P) == NIL || !(DT_UTAG_FLAGS(BIF_P) & DT_UTAG_PERMANENT)) ? am_undefined : DT_UTAG(BIF_P)); @@ -4683,7 +4683,7 @@ BIF_RETTYPE get_utag_0(BIF_ALIST_0) BIF_RET(am_undefined); #endif } -BIF_RETTYPE get_utag_data_0(BIF_ALIST_0) +BIF_RETTYPE dt_get_tag_data_0(BIF_ALIST_0) { #ifdef USE_VM_PROBES BIF_RET((DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P)); @@ -4691,7 +4691,7 @@ BIF_RETTYPE get_utag_data_0(BIF_ALIST_0) BIF_RET(am_undefined); #endif } -BIF_RETTYPE prepend_vm_utag_data_1(BIF_ALIST_1) +BIF_RETTYPE dt_prepend_vm_tag_data_1(BIF_ALIST_1) { #ifdef USE_VM_PROBES Eterm b; @@ -4718,7 +4718,7 @@ BIF_RETTYPE prepend_vm_utag_data_1(BIF_ALIST_1) BIF_RET(BIF_ARG_1); #endif } -BIF_RETTYPE append_vm_utag_data_1(BIF_ALIST_1) +BIF_RETTYPE dt_append_vm_tag_data_1(BIF_ALIST_1) { #ifdef USE_VM_PROBES Eterm b; @@ -4745,7 +4745,7 @@ BIF_RETTYPE append_vm_utag_data_1(BIF_ALIST_1) BIF_RET(BIF_ARG_1); #endif } -BIF_RETTYPE spread_utag_1(BIF_ALIST_1) +BIF_RETTYPE dt_spread_tag_1(BIF_ALIST_1) { #ifdef USE_VM_PROBES Eterm ret; @@ -4779,7 +4779,7 @@ BIF_RETTYPE spread_utag_1(BIF_ALIST_1) BIF_RET(am_true); #endif } -BIF_RETTYPE restore_utag_1(BIF_ALIST_1) +BIF_RETTYPE dt_restore_tag_1(BIF_ALIST_1) { #ifdef USE_VM_PROBES Eterm *tpl; diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index 7940544156..8a85e102d1 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -820,16 +820,16 @@ bif erlang:posixtime_to_universaltime/1 # # The dtrace BIF's are always present, but give dummy results if dynamic trace is not enabled in the build -bif erlang:put_utag/1 -bif erlang:get_utag/0 -bif erlang:get_utag_data/0 -bif erlang:spread_utag/1 -bif erlang:restore_utag/1 +bif erlang:dt_put_tag/1 +bif erlang:dt_get_tag/0 +bif erlang:dt_get_tag_data/0 +bif erlang:dt_spread_tag/1 +bif erlang:dt_restore_tag/1 # These are dummies even with enabled dynamic trace unless vm probes are enabled. # They are also internal, for dtrace tags sent to the VM's own drivers (efile) -bif erlang:prepend_vm_utag_data/1 -bif erlang:append_vm_utag_data/1 +bif erlang:dt_prepend_vm_tag_data/1 +bif erlang:dt_append_vm_tag_data/1 # # Obsolete diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab index edc935e1ff..b2fc571032 100644 --- a/erts/emulator/beam/ops.tab +++ b/erts/emulator/beam/ops.tab @@ -884,86 +884,86 @@ call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate # # If VM probes are not enabled, we want to short-circult calls to -# the utag BIFs to make them as cheap as possible. +# the dt tag BIFs to make them as cheap as possible. # %unless USE_VM_PROBES -call_ext Arity u$func:erlang:get_utag/0 => \ +call_ext Arity u$func:erlang:dt_get_tag/0 => \ move a=am_undefined r -call_ext_last Arity u$func:erlang:get_utag/0 D => \ +call_ext_last Arity u$func:erlang:dt_get_tag/0 D => \ move a=am_undefined r | deallocate D | return -call_ext_only Arity u$func:erlang:get_utag/0 => \ +call_ext_only Arity u$func:erlang:dt_get_tag/0 => \ move a=am_undefined r | return -move Any r | call_ext Arity u$func:erlang:put_utag/1 => \ +move Any r | call_ext Arity u$func:erlang:dt_put_tag/1 => \ move a=am_undefined r -move Any r | call_ext_last Arity u$func:erlang:put_utag/1 D => \ +move Any r | call_ext_last Arity u$func:erlang:dt_put_tag/1 D => \ move a=am_undefined r | deallocate D | return -move Any r | call_ext_only Arity u$func:erlang:put_utag/1 => \ +move Any r | call_ext_only Arity u$func:erlang:dt_put_tag/1 => \ move a=am_undefined r | return -call_ext Arity u$func:erlang:put_utag/1 => \ +call_ext Arity u$func:erlang:dt_put_tag/1 => \ move a=am_undefined r -call_ext_last Arity u$func:erlang:put_utag/1 D => \ +call_ext_last Arity u$func:erlang:dt_put_tag/1 D => \ move a=am_undefined r | deallocate D | return -call_ext_only Arity u$func:erlang:put_utag/1 => \ +call_ext_only Arity u$func:erlang:dt_put_tag/1 => \ move a=am_undefined r | return -call_ext Arity u$func:erlang:get_utag_data/0 => \ +call_ext Arity u$func:erlang:dt_get_tag_data/0 => \ move a=am_undefined r -call_ext_last Arity u$func:erlang:get_utag_data/0 D => \ +call_ext_last Arity u$func:erlang:dt_get_tag_data/0 D => \ move a=am_undefined r | deallocate D | return -call_ext_only Arity u$func:erlang:get_utag_data/0 => \ +call_ext_only Arity u$func:erlang:dt_get_tag_data/0 => \ move a=am_undefined r | return -move Any r | call_ext Arity u$func:erlang:spread_utag/1 => \ +move Any r | call_ext Arity u$func:erlang:dt_spread_tag/1 => \ move a=am_true r -move Any r | call_ext_last Arity u$func:erlang:spread_utag/1 D => \ +move Any r | call_ext_last Arity u$func:erlang:dt_spread_tag/1 D => \ move a=am_true r | deallocate D | return -move Any r | call_ext_only Arity u$func:erlang:spread_utag/1 => \ +move Any r | call_ext_only Arity u$func:erlang:dt_spread_tag/1 => \ move a=am_true r | return -call_ext Arity u$func:erlang:spread_utag/1 => \ +call_ext Arity u$func:erlang:dt_spread_tag/1 => \ move a=am_true r -call_ext_last Arity u$func:erlang:spread_utag/1 D => \ +call_ext_last Arity u$func:erlang:dt_spread_tag/1 D => \ move a=am_true r | deallocate D | return -call_ext_only Arity u$func:erlang:spread_utag/1 => \ +call_ext_only Arity u$func:erlang:dt_spread_tag/1 => \ move a=am_true r | return -move Any r | call_ext Arity u$func:erlang:restore_utag/1 => \ +move Any r | call_ext Arity u$func:erlang:dt_restore_tag/1 => \ move a=am_true r -move Any r | call_ext_last Arity u$func:erlang:restore_utag/1 D => \ +move Any r | call_ext_last Arity u$func:erlang:dt_restore_tag/1 D => \ move a=am_true r | deallocate D | return -move Any r | call_ext_only Arity u$func:erlang:restore_utag/1 => \ +move Any r | call_ext_only Arity u$func:erlang:dt_restore_tag/1 => \ move a=am_true r | return -call_ext Arity u$func:erlang:restore_utag/1 => \ +call_ext Arity u$func:erlang:dt_restore_tag/1 => \ move a=am_true r -call_ext_last Arity u$func:erlang:restore_utag/1 D => \ +call_ext_last Arity u$func:erlang:dt_restore_tag/1 D => \ move a=am_true r | deallocate D | return -call_ext_only Arity u$func:erlang:restore_utag/1 => \ +call_ext_only Arity u$func:erlang:dt_restore_tag/1 => \ move a=am_true r | return -move Any r | call_ext Arity u$func:erlang:prepend_vm_utag_data/1 => \ +move Any r | call_ext Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \ move Any r -move Any r | call_ext_last Arity u$func:erlang:prepend_vm_utag_data/1 D => \ +move Any r | call_ext_last Arity u$func:erlang:dt_prepend_vm_tag_data/1 D => \ move Any r | deallocate D | return -move Any r | call_ext_only Arity u$func:erlang:prepend_vm_utag_data/1 => \ +move Any r | call_ext_only Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \ move Any r | return -call_ext Arity u$func:erlang:prepend_vm_utag_data/1 => -call_ext_last Arity u$func:erlang:prepend_vm_utag_data/1 D => \ +call_ext Arity u$func:erlang:dt_prepend_vm_tag_data/1 => +call_ext_last Arity u$func:erlang:dt_prepend_vm_tag_data/1 D => \ deallocate D | return -call_ext_only Arity u$func:erlang:prepend_vm_utag_data/1 => \ +call_ext_only Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \ return -move Any r | call_ext Arity u$func:erlang:append_vm_utag_data/1 => \ +move Any r | call_ext Arity u$func:erlang:dt_append_vm_tag_data/1 => \ move Any r -move Any r | call_ext_last Arity u$func:erlang:append_vm_utag_data/1 D => \ +move Any r | call_ext_last Arity u$func:erlang:dt_append_vm_tag_data/1 D => \ move Any r | deallocate D | return -move Any r | call_ext_only Arity u$func:erlang:append_vm_utag_data/1 => \ +move Any r | call_ext_only Arity u$func:erlang:dt_append_vm_tag_data/1 => \ move Any r | return -call_ext Arity u$func:erlang:append_vm_utag_data/1 => -call_ext_last Arity u$func:erlang:append_vm_utag_data/1 D => \ +call_ext Arity u$func:erlang:dt_append_vm_tag_data/1 => +call_ext_last Arity u$func:erlang:dt_append_vm_tag_data/1 D => \ deallocate D | return -call_ext_only Arity u$func:erlang:append_vm_utag_data/1 => \ +call_ext_only Arity u$func:erlang:dt_append_vm_tag_data/1 => \ return # Can happen after one of the transformations above. -- cgit v1.2.3 From 19a36b917d8c7c2dc061ee5b41738fa8b315d70b Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Fri, 9 Mar 2012 15:51:51 +0100 Subject: Update slogan and add system_info for dynamic trace --- erts/emulator/beam/erl_bif_info.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 618acc5117..041eac240d 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -115,8 +115,11 @@ static char erts_system_version[] = ("Erlang " ERLANG_OTP_RELEASE #ifdef VALGRIND " [valgrind-compiled]" #endif -#ifdef USE_VM_PROBES +#ifdef USE_DTRACE " [dtrace]" +#endif +#ifdef USE_SYSTEMTAP + " [systemtap]" #endif "\n"); @@ -2723,6 +2726,24 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1) #endif BIF_RET(am_true); } + else if (ERTS_IS_ATOM_STR("dynamic_trace", BIF_ARG_1)) { +#if defined(USE_DTRACE) + DECL_AM(dtrace); + BIF_RET(AM_dtrace); +#elif defined(USE_SYSTEMTAP) + DECL_AM(systemtap); + BIF_RET(AM_systemtap); +#else + BIF_RET(am_none); +#endif + } + else if (ERTS_IS_ATOM_STR("dynamic_trace_probes", BIF_ARG_1)) { +#if defined(USE_VM_PROBES) + BIF_RET(am_true); +#else + BIF_RET(am_false); +#endif + } #ifdef ERTS_SMP else if (ERTS_IS_ATOM_STR("thread_progress", BIF_ARG_1)) { erts_thr_progress_dbg_print_state(); -- cgit v1.2.3 From 062b599f16ff74e0ae6495b09df85bfd8560afdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Tue, 20 Mar 2012 12:30:28 +0100 Subject: erl_process.c: Fix probe for process exit --- erts/emulator/beam/erl_process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index ff4e9c3d88..95d408f79d 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -8439,10 +8439,10 @@ erts_do_exit_process(Process* p, Eterm reason) #ifdef USE_VM_PROBES if (DTRACE_ENABLED(process_exit)) { DTRACE_CHARBUF(process_buf, DTRACE_TERM_BUF_SIZE); - DTRACE_CHARBUF(reason_buf, 256); + DTRACE_CHARBUF(reason_buf, DTRACE_TERM_BUF_SIZE); dtrace_proc_str(p, process_buf); - erts_snprintf(reason_buf, sizeof(reason_buf) - 1, "%T", reason); + erts_snprintf(reason_buf, DTRACE_TERM_BUF_SIZE - 1, "%T", reason); DTRACE2(process_exit, process_buf, reason_buf); } #endif -- cgit v1.2.3 From 654983b39f9aaaf2297ab1cd4b60243ea119bcdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 21 Mar 2012 10:42:19 +0100 Subject: Don't try to "clean up" generated fun names The fun names may look ugly, but if we clean them up we can't distinguish calls to the function defining the fun and to the fun itself. --- erts/emulator/beam/global.h | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 7f12004b43..b000e2c5d4 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -2007,32 +2007,12 @@ 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); + erts_snprintf(mfa_buf, DTRACE_TERM_BUF_SIZE, "%T:%T/%d", + module, function, arity); } #endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */ -- cgit v1.2.3 From e3163d8482c01bd61a76c3c69adfd45df94b8f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 21 Mar 2012 11:28:35 +0100 Subject: Add probes for all kind of calls --- erts/emulator/beam/beam_emu.c | 59 +++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 22 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 5c5d9fd049..6a758f6e19 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -1052,6 +1052,10 @@ init_emulator(void) #endif #ifdef USE_VM_PROBES +# define USE_VM_CALL_PROBES +#endif + +#ifdef USE_VM_CALL_PROBES #define DTRACE_CALL(p, m, f, a) \ if (DTRACE_ENABLED(function_entry)) { \ @@ -1504,6 +1508,7 @@ void process_main(void) /* FALL THROUGH */ OpCase(i_call_only_f): { SET_I((BeamInstr *) Arg(0)); + DTRACE_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]); Dispatch(); } @@ -1515,6 +1520,7 @@ void process_main(void) RESTORE_CP(E); E = ADD_BYTE_OFFSET(E, Arg(1)); SET_I((BeamInstr *) Arg(0)); + DTRACE_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]); Dispatch(); } @@ -1526,6 +1532,7 @@ void process_main(void) OpCase(i_call_f): { SET_CP(c_p, I+2); SET_I((BeamInstr *) Arg(0)); + DTRACE_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]); Dispatch(); } @@ -1542,6 +1549,12 @@ void process_main(void) * is not loaded, it points to code which will invoke the error handler * (see lb_call_error_handler below). */ +#ifdef USE_VM_CALL_PROBES + if (DTRACE_ENABLED(function_entry)) { + BeamInstr* fp = (BeamInstr *) (((Export *) Arg(0))->address); + DTRACE_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]); + } +#endif Dispatchx(); OpCase(i_move_call_ext_cre): { @@ -1551,6 +1564,12 @@ void process_main(void) /* FALL THROUGH */ OpCase(i_call_ext_e): SET_CP(c_p, I+2); +#ifdef USE_VM_CALL_PROBES + if (DTRACE_ENABLED(function_entry)) { + BeamInstr* fp = (BeamInstr *) (((Export *) Arg(0))->address); + DTRACE_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]); + } +#endif Dispatchx(); OpCase(i_move_call_ext_only_ecr): { @@ -1558,6 +1577,12 @@ void process_main(void) } /* FALL THROUGH */ OpCase(i_call_ext_only_e): +#ifdef USE_VM_CALL_PROBES + if (DTRACE_ENABLED(function_entry)) { + BeamInstr* fp = (BeamInstr *) (((Export *) Arg(0))->address); + DTRACE_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]); + } +#endif Dispatchx(); OpCase(init_y): { @@ -1593,12 +1618,12 @@ void process_main(void) OpCase(return): { -#ifdef USE_VM_PROBES +#ifdef USE_VM_CALL_PROBES BeamInstr* fptr; #endif SET_I(c_p->cp); -#ifdef USE_VM_PROBES +#ifdef USE_VM_CALL_PROBES if (DTRACE_ENABLED(function_return) && (fptr = find_function_from_pc(c_p->cp))) { DTRACE_RETURN(c_p, (Eterm)fptr[0], (Eterm)fptr[1], (Uint)fptr[2]); } @@ -6087,12 +6112,10 @@ apply(Process* p, Eterm module, Eterm function, Eterm args, Eterm* reg) save_calls(p, ep); } -#ifdef USE_VM_PROBES - if (DTRACE_ENABLED(function_entry) && ep->address) { - BeamInstr *fptr = find_function_from_pc(ep->address); - if (fptr) { - DTRACE_CALL(p, (Eterm)fptr[0], (Eterm)fptr[1], (Uint)fptr[2]); - } +#ifdef USE_VM_CALL_PROBES + if (DTRACE_ENABLED(function_entry)) { + BeamInstr *fptr = (BeamInstr *) ep->address; + DTRACE_CALL(p, (Eterm)fptr[-3], (Eterm)fptr[-2], (Uint)fptr[-1]); } #endif return ep->address; @@ -6144,12 +6167,10 @@ fixed_apply(Process* p, Eterm* reg, Uint arity) save_calls(p, ep); } -#ifdef USE_VM_PROBES +#ifdef USE_VM_CALL_PROBES if (DTRACE_ENABLED(function_entry)) { - BeamInstr *fptr = find_function_from_pc(ep->address); - if (fptr) { - DTRACE_CALL(p, (Eterm)fptr[0], (Eterm)fptr[1], (Uint)fptr[2]); - } + BeamInstr *fptr = (BeamInstr *) ep->address; + DTRACE_CALL(p, (Eterm)fptr[-3], (Eterm)fptr[-2], (Uint)fptr[-1]); } #endif return ep->address; @@ -6284,16 +6305,10 @@ call_fun(Process* p, /* Current process. */ code_ptr = fe->address; actual_arity = (int) code_ptr[-1]; -#ifdef USE_VM_PROBES - if (DTRACE_ENABLED(function_entry)) { - BeamInstr *fptr = find_function_from_pc(code_ptr); - - if (fptr) { - DTRACE_CALL(p, fe->module, (Eterm)fptr[1], actual_arity); - } - } -#endif if (actual_arity == arity+num_free) { + DTRACE_CALL(p, (Eterm)code_ptr[-3], + (Eterm)code_ptr[-2], + code_ptr[-1]); if (num_free == 0) { return code_ptr; } else { -- cgit v1.2.3 From 848f6e541f779e13f7d99bbd0c99ac37a9bd56e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 21 Mar 2012 12:00:05 +0100 Subject: Correct calculation of stack depth in call/return probes --- erts/emulator/beam/beam_emu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 6a758f6e19..69a3d7e81a 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -1061,8 +1061,7 @@ init_emulator(void) if (DTRACE_ENABLED(function_entry)) { \ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ - int depth = (STACK_START(p) - STACK_TOP(p)) \ - / sizeof(Eterm*); \ + int depth = STACK_START(p) - STACK_TOP(p); \ dtrace_fun_decode(p, m, f, a, \ process_name, mfa); \ DTRACE3(function_entry, process_name, mfa, depth); \ @@ -1072,8 +1071,7 @@ init_emulator(void) if (DTRACE_ENABLED(function_return)) { \ DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ - int depth = (STACK_START(p) - STACK_TOP(p)) \ - / sizeof(Eterm*); \ + int depth = STACK_START(p) - STACK_TOP(p); \ dtrace_fun_decode(p, m, f, a, \ process_name, mfa); \ DTRACE3(function_return, process_name, mfa, depth); \ -- cgit v1.2.3 From 1e653c3539423e4cfdeab1d232483bcac0e8b073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 21 Mar 2012 14:26:47 +0100 Subject: Use distinct function-entry probes for local and global calls It seems useful to be able to filter out (for example) just the global calls. --- erts/emulator/beam/beam_emu.c | 71 ++++++++++++++++++++++---------------- erts/emulator/beam/erlang_dtrace.d | 14 ++++++-- 2 files changed, 53 insertions(+), 32 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 69a3d7e81a..8b4f067b98 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -1057,14 +1057,24 @@ init_emulator(void) #ifdef USE_VM_CALL_PROBES -#define DTRACE_CALL(p, m, f, a) \ - if (DTRACE_ENABLED(function_entry)) { \ - DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ - DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ - int depth = STACK_START(p) - STACK_TOP(p); \ - dtrace_fun_decode(p, m, f, a, \ - process_name, mfa); \ - DTRACE3(function_entry, process_name, mfa, depth); \ +#define DTRACE_LOCAL_CALL(p, m, f, a) \ + if (DTRACE_ENABLED(local_function_entry)) { \ + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ + int depth = STACK_START(p) - STACK_TOP(p); \ + dtrace_fun_decode(p, m, f, a, \ + process_name, mfa); \ + DTRACE3(local_function_entry, process_name, mfa, depth); \ + } + +#define DTRACE_GLOBAL_CALL(p, m, f, a) \ + if (DTRACE_ENABLED(global_function_entry)) { \ + DTRACE_CHARBUF(process_name, DTRACE_TERM_BUF_SIZE); \ + DTRACE_CHARBUF(mfa, DTRACE_TERM_BUF_SIZE); \ + int depth = STACK_START(p) - STACK_TOP(p); \ + dtrace_fun_decode(p, m, f, a, \ + process_name, mfa); \ + DTRACE3(global_function_entry, process_name, mfa, depth); \ } #define DTRACE_RETURN(p, m, f, a) \ @@ -1115,12 +1125,13 @@ init_emulator(void) #else /* USE_VM_PROBES */ -#define DTRACE_CALL(p, m, f, a) do {} while (0) -#define DTRACE_RETURN(p, m, f, a) do {} while (0) -#define DTRACE_BIF_ENTRY(p, m, f, a) do {} while (0) -#define DTRACE_BIF_RETURN(p, m, f, a) do {} while (0) -#define DTRACE_NIF_ENTRY(p, m, f, a) do {} while (0) -#define DTRACE_NIF_RETURN(p, m, f, a) do {} while (0) +#define DTRACE_LOCAL_CALL(p, m, f, a) do {} while (0) +#define DTRACE_GLOBAL_CALL(p, m, f, a) do {} while (0) +#define DTRACE_RETURN(p, m, f, a) do {} while (0) +#define DTRACE_BIF_ENTRY(p, m, f, a) do {} while (0) +#define DTRACE_BIF_RETURN(p, m, f, a) do {} while (0) +#define DTRACE_NIF_ENTRY(p, m, f, a) do {} while (0) +#define DTRACE_NIF_RETURN(p, m, f, a) do {} while (0) #endif /* USE_VM_PROBES */ @@ -1506,7 +1517,7 @@ void process_main(void) /* FALL THROUGH */ OpCase(i_call_only_f): { SET_I((BeamInstr *) Arg(0)); - DTRACE_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]); + DTRACE_LOCAL_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]); Dispatch(); } @@ -1518,7 +1529,7 @@ void process_main(void) RESTORE_CP(E); E = ADD_BYTE_OFFSET(E, Arg(1)); SET_I((BeamInstr *) Arg(0)); - DTRACE_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]); + DTRACE_LOCAL_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]); Dispatch(); } @@ -1530,7 +1541,7 @@ void process_main(void) OpCase(i_call_f): { SET_CP(c_p, I+2); SET_I((BeamInstr *) Arg(0)); - DTRACE_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]); + DTRACE_LOCAL_CALL(c_p, (Eterm)I[-3], (Eterm)I[-2], I[-1]); Dispatch(); } @@ -1548,9 +1559,9 @@ void process_main(void) * (see lb_call_error_handler below). */ #ifdef USE_VM_CALL_PROBES - if (DTRACE_ENABLED(function_entry)) { + if (DTRACE_ENABLED(global_function_entry)) { BeamInstr* fp = (BeamInstr *) (((Export *) Arg(0))->address); - DTRACE_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]); + DTRACE_GLOBAL_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]); } #endif Dispatchx(); @@ -1563,9 +1574,9 @@ void process_main(void) OpCase(i_call_ext_e): SET_CP(c_p, I+2); #ifdef USE_VM_CALL_PROBES - if (DTRACE_ENABLED(function_entry)) { + if (DTRACE_ENABLED(global_function_entry)) { BeamInstr* fp = (BeamInstr *) (((Export *) Arg(0))->address); - DTRACE_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]); + DTRACE_GLOBAL_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]); } #endif Dispatchx(); @@ -1576,9 +1587,9 @@ void process_main(void) /* FALL THROUGH */ OpCase(i_call_ext_only_e): #ifdef USE_VM_CALL_PROBES - if (DTRACE_ENABLED(function_entry)) { + if (DTRACE_ENABLED(global_function_entry)) { BeamInstr* fp = (BeamInstr *) (((Export *) Arg(0))->address); - DTRACE_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]); + DTRACE_GLOBAL_CALL(c_p, (Eterm)fp[-3], (Eterm)fp[-2], fp[-1]); } #endif Dispatchx(); @@ -6111,9 +6122,9 @@ apply(Process* p, Eterm module, Eterm function, Eterm args, Eterm* reg) } #ifdef USE_VM_CALL_PROBES - if (DTRACE_ENABLED(function_entry)) { + if (DTRACE_ENABLED(global_function_entry)) { BeamInstr *fptr = (BeamInstr *) ep->address; - DTRACE_CALL(p, (Eterm)fptr[-3], (Eterm)fptr[-2], (Uint)fptr[-1]); + DTRACE_GLOBAL_CALL(p, (Eterm)fptr[-3], (Eterm)fptr[-2], (Uint)fptr[-1]); } #endif return ep->address; @@ -6166,9 +6177,9 @@ fixed_apply(Process* p, Eterm* reg, Uint arity) } #ifdef USE_VM_CALL_PROBES - if (DTRACE_ENABLED(function_entry)) { + if (DTRACE_ENABLED(global_function_entry)) { BeamInstr *fptr = (BeamInstr *) ep->address; - DTRACE_CALL(p, (Eterm)fptr[-3], (Eterm)fptr[-2], (Uint)fptr[-1]); + DTRACE_GLOBAL_CALL(p, (Eterm)fptr[-3], (Eterm)fptr[-2], (Uint)fptr[-1]); } #endif return ep->address; @@ -6304,7 +6315,7 @@ call_fun(Process* p, /* Current process. */ actual_arity = (int) code_ptr[-1]; if (actual_arity == arity+num_free) { - DTRACE_CALL(p, (Eterm)code_ptr[-3], + DTRACE_LOCAL_CALL(p, (Eterm)code_ptr[-3], (Eterm)code_ptr[-2], code_ptr[-1]); if (num_free == 0) { @@ -6399,7 +6410,7 @@ call_fun(Process* p, /* Current process. */ actual_arity = (int) ep->code[2]; if (arity == actual_arity) { - DTRACE_CALL(p, ep->code[0], ep->code[1], (Uint)ep->code[2]); + DTRACE_GLOBAL_CALL(p, ep->code[0], ep->code[1], (Uint)ep->code[2]); return ep->address; } else { /* @@ -6475,7 +6486,7 @@ call_fun(Process* p, /* Current process. */ reg[1] = function; reg[2] = args; } - DTRACE_CALL(p, module, function, arity); + DTRACE_GLOBAL_CALL(p, module, function, arity); return ep->address; } else { badfun: diff --git a/erts/emulator/beam/erlang_dtrace.d b/erts/emulator/beam/erlang_dtrace.d index d8508426f4..587e51cb67 100644 --- a/erts/emulator/beam/erlang_dtrace.d +++ b/erts/emulator/beam/erlang_dtrace.d @@ -149,13 +149,23 @@ provider erlang { /* PID, Module, Function, Arity */ /** - * Fired whenever a user function is being called. + * Fired whenever a user function is being called locally. * * @param p the PID (string form) of the process * @param mfa the m:f/a of the function * @param depth the stack depth */ - probe function__entry(char *p, char *mfa, int depth); + probe local__function__entry(char *p, char *mfa, int depth); + + /** + * Fired whenever a user function is called externally + * (through an export entry). + * + * @param p the PID (string form) of the process + * @param mfa the m:f/a of the function + * @param depth the stack depth + */ + probe global__function__entry(char *p, char *mfa, int depth); /** * Fired whenever a user function returns. -- cgit v1.2.3