Add utrace(2)-based tracing (--enable-utrace).
diff --git a/INSTALL b/INSTALL
index c0ae106..8a825df 100644
--- a/INSTALL
+++ b/INSTALL
@@ -119,6 +119,10 @@
--disable-experimental
Disable support for the experimental API (*allocm()).
+--enable-utrace
+ Enable utrace(2)-based allocation tracing. This feature is not broadly
+ portable (FreeBSD has it, but Linux and OS X do not).
+
--enable-xmalloc
Enable support for optional immediate termination due to out-of-memory
errors, as is commonly implemented by "xmalloc" wrapper function for malloc.
diff --git a/configure.ac b/configure.ac
index 16f0378..8e94b5c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -699,6 +699,34 @@
fi
AC_SUBST([enable_fill])
+dnl Disable utrace(2)-based tracing by default.
+AC_ARG_ENABLE([utrace],
+ [AS_HELP_STRING([--enable-utrace], [Enable utrace(2)-based tracing])],
+[if test "x$enable_utrace" = "xno" ; then
+ enable_utrace="0"
+else
+ enable_utrace="1"
+fi
+],
+[enable_utrace="0"]
+)
+JE_COMPILABLE([utrace(2)], [
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+], [
+ utrace((void *)0, 0);
+], [je_cv_utrace])
+if test "x${je_cv_utrace}" = "xno" ; then
+ enable_utrace="0"
+fi
+if test "x$enable_utrace" = "x1" ; then
+ AC_DEFINE([JEMALLOC_UTRACE], [ ])
+fi
+AC_SUBST([enable_utrace])
+
dnl Do not support the xmalloc option by default.
AC_ARG_ENABLE([xmalloc],
[AS_HELP_STRING([--enable-xmalloc], [Support xmalloc option])],
@@ -1061,6 +1089,7 @@
AC_MSG_RESULT([tcache : ${enable_tcache}])
AC_MSG_RESULT([fill : ${enable_fill}])
AC_MSG_RESULT([xmalloc : ${enable_xmalloc}])
+AC_MSG_RESULT([utrace : ${enable_utrace}])
AC_MSG_RESULT([dss : ${enable_dss}])
AC_MSG_RESULT([lazy_lock : ${enable_lazy_lock}])
AC_MSG_RESULT([tls : ${enable_tls}])
diff --git a/doc/jemalloc.xml.in b/doc/jemalloc.xml.in
index 7a2d033..8ae8262 100644
--- a/doc/jemalloc.xml.in
+++ b/doc/jemalloc.xml.in
@@ -712,6 +712,16 @@
<varlistentry>
<term>
+ <mallctl>config.utrace</mallctl>
+ (<type>bool</type>)
+ <literal>r-</literal>
+ </term>
+ <listitem><para><option>--enable-utrace</option> was specified during
+ build configuration.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
<mallctl>config.xmalloc</mallctl>
(<type>bool</type>)
<literal>r-</literal>
@@ -826,6 +836,19 @@
</para></listitem>
</varlistentry>
+ <varlistentry id="opt.utrace">
+ <term>
+ <mallctl>opt.utrace</mallctl>
+ (<type>bool</type>)
+ <literal>r-</literal>
+ [<option>--enable-utrace</option>]
+ </term>
+ <listitem><para>Allocation tracing based on
+ <citerefentry><refentrytitle>utrace</refentrytitle>
+ <manvolnum>2</manvolnum></citerefentry> enabled/disabled. This option
+ is disabled by default.</para></listitem>
+ </varlistentry>
+
<varlistentry id="opt.xmalloc">
<term>
<mallctl>opt.xmalloc</mallctl>
@@ -1958,6 +1981,8 @@
<manvolnum>2</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sbrk</refentrytitle>
<manvolnum>2</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>utrace</refentrytitle>
+ <manvolnum>2</manvolnum></citerefentry>,
<citerefentry><refentrytitle>alloca</refentrytitle>
<manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>atexit</refentrytitle>
diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in
index c8e4019..66dd357 100644
--- a/include/jemalloc/internal/jemalloc_internal.h.in
+++ b/include/jemalloc/internal/jemalloc_internal.h.in
@@ -36,6 +36,10 @@
#define JEMALLOC_NO_DEMANGLE
#include "../jemalloc@install_suffix@.h"
+#ifdef JEMALLOC_UTRACE
+#include <sys/ktrace.h>
+#endif
+
#include "jemalloc/internal/private_namespace.h"
#ifdef JEMALLOC_CC_SILENCE
@@ -114,6 +118,13 @@
false
#endif
;
+static const bool config_utrace =
+#ifdef JEMALLOC_UTRACE
+ true
+#else
+ false
+#endif
+ ;
static const bool config_xmalloc =
#ifdef JEMALLOC_XMALLOC
true
@@ -332,6 +343,7 @@
extern bool opt_abort;
extern bool opt_junk;
+extern bool opt_utrace;
extern bool opt_xmalloc;
extern bool opt_zero;
extern size_t opt_narenas;
diff --git a/include/jemalloc/internal/private_namespace.h b/include/jemalloc/internal/private_namespace.h
index ed34e32..de3042e 100644
--- a/include/jemalloc/internal/private_namespace.h
+++ b/include/jemalloc/internal/private_namespace.h
@@ -173,6 +173,7 @@
#define opt_prof_leak JEMALLOC_N(opt_prof_leak)
#define opt_stats_print JEMALLOC_N(opt_stats_print)
#define opt_tcache JEMALLOC_N(opt_tcache)
+#define opt_utrace JEMALLOC_N(opt_utrace)
#define opt_xmalloc JEMALLOC_N(opt_xmalloc)
#define opt_zero JEMALLOC_N(opt_zero)
#define pow2_ceil JEMALLOC_N(pow2_ceil)
diff --git a/include/jemalloc/jemalloc_defs.h.in b/include/jemalloc/jemalloc_defs.h.in
index 040753a..8e7442d 100644
--- a/include/jemalloc/jemalloc_defs.h.in
+++ b/include/jemalloc/jemalloc_defs.h.in
@@ -154,6 +154,9 @@
/* Support the experimental API. */
#undef JEMALLOC_EXPERIMENTAL
+/* Support utrace(2)-based tracing. */
+#undef JEMALLOC_UTRACE
+
/* Support optional abort() on OOM. */
#undef JEMALLOC_XMALLOC
diff --git a/src/ctl.c b/src/ctl.c
index df7affd..1aaf197 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -56,6 +56,7 @@
CTL_PROTO(config_stats)
CTL_PROTO(config_tcache)
CTL_PROTO(config_tls)
+CTL_PROTO(config_utrace)
CTL_PROTO(config_xmalloc)
CTL_PROTO(opt_abort)
CTL_PROTO(opt_lg_chunk)
@@ -64,6 +65,7 @@
CTL_PROTO(opt_stats_print)
CTL_PROTO(opt_junk)
CTL_PROTO(opt_zero)
+CTL_PROTO(opt_utrace)
CTL_PROTO(opt_xmalloc)
CTL_PROTO(opt_tcache)
CTL_PROTO(opt_lg_tcache_max)
@@ -176,6 +178,7 @@
{NAME("stats"), CTL(config_stats)},
{NAME("tcache"), CTL(config_tcache)},
{NAME("tls"), CTL(config_tls)},
+ {NAME("utrace"), CTL(config_utrace)},
{NAME("xmalloc"), CTL(config_xmalloc)}
};
@@ -187,6 +190,7 @@
{NAME("stats_print"), CTL(opt_stats_print)},
{NAME("junk"), CTL(opt_junk)},
{NAME("zero"), CTL(opt_zero)},
+ {NAME("utrace"), CTL(opt_utrace)},
{NAME("xmalloc"), CTL(opt_xmalloc)},
{NAME("tcache"), CTL(opt_tcache)},
{NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)},
@@ -1080,6 +1084,7 @@
CTL_RO_BOOL_CONFIG_GEN(config_stats)
CTL_RO_BOOL_CONFIG_GEN(config_tcache)
CTL_RO_BOOL_CONFIG_GEN(config_tls)
+CTL_RO_BOOL_CONFIG_GEN(config_utrace)
CTL_RO_BOOL_CONFIG_GEN(config_xmalloc)
/******************************************************************************/
@@ -1091,6 +1096,7 @@
CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, bool)
CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
+CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)
CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
diff --git a/src/jemalloc.c b/src/jemalloc.c
index a531a21..e051020 100644
--- a/src/jemalloc.c
+++ b/src/jemalloc.c
@@ -21,6 +21,7 @@
bool opt_abort = false;
bool opt_junk = false;
#endif
+bool opt_utrace = false;
bool opt_xmalloc = false;
bool opt_zero = false;
size_t opt_narenas = 0;
@@ -50,6 +51,26 @@
/* Used to avoid initialization races. */
static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER;
+typedef struct {
+ void *p; /* Input pointer (as in realloc(p, s)). */
+ size_t s; /* Request size. */
+ void *r; /* Result pointer. */
+} malloc_utrace_t;
+
+#ifdef JEMALLOC_UTRACE
+# define UTRACE(a, b, c) do { \
+ if (opt_utrace) { \
+ malloc_utrace_t ut; \
+ ut.p = (a); \
+ ut.s = (b); \
+ ut.r = (c); \
+ utrace(&ut, sizeof(ut)); \
+ } \
+} while (0)
+#else
+# define UTRACE(a, b, c)
+#endif
+
/******************************************************************************/
/* Function prototypes for non-inline static functions. */
@@ -483,6 +504,9 @@
CONF_HANDLE_BOOL(opt_junk, junk)
CONF_HANDLE_BOOL(opt_zero, zero)
}
+ if (config_utrace) {
+ CONF_HANDLE_BOOL(opt_utrace, utrace)
+ }
if (config_xmalloc) {
CONF_HANDLE_BOOL(opt_xmalloc, xmalloc)
}
@@ -759,6 +783,7 @@
assert(usize == isalloc(ret));
thread_allocated_tsd_get()->allocated += usize;
}
+ UTRACE(0, size, ret);
return (ret);
}
@@ -852,6 +877,7 @@
}
if (config_prof && opt_prof && result != NULL)
prof_malloc(result, usize, cnt);
+ UTRACE(0, size, result);
return (ret);
}
@@ -951,6 +977,7 @@
assert(usize == isalloc(ret));
thread_allocated_tsd_get()->allocated += usize;
}
+ UTRACE(0, num_size, ret);
return (ret);
}
@@ -1075,6 +1102,7 @@
ta->allocated += usize;
ta->deallocated += old_size;
}
+ UTRACE(ptr, size, ret);
return (ret);
}
@@ -1083,6 +1111,7 @@
je_free(void *ptr)
{
+ UTRACE(ptr, 0, 0);
if (ptr != NULL) {
size_t usize;
@@ -1310,6 +1339,7 @@
assert(usize == isalloc(p));
thread_allocated_tsd_get()->allocated += usize;
}
+ UTRACE(0, size, p);
return (ALLOCM_SUCCESS);
OOM:
if (config_xmalloc && opt_xmalloc) {
@@ -1318,6 +1348,7 @@
abort();
}
*ptr = NULL;
+ UTRACE(0, size, 0);
return (ALLOCM_ERR_OOM);
}
@@ -1404,16 +1435,20 @@
ta->allocated += usize;
ta->deallocated += old_size;
}
+ UTRACE(p, size, q);
return (ALLOCM_SUCCESS);
ERR:
- if (no_move)
+ if (no_move) {
+ UTRACE(p, size, q);
return (ALLOCM_ERR_NOT_MOVED);
+ }
OOM:
if (config_xmalloc && opt_xmalloc) {
malloc_write("<jemalloc>: Error in rallocm(): "
"out of memory\n");
abort();
}
+ UTRACE(p, size, 0);
return (ALLOCM_ERR_OOM);
}
@@ -1448,6 +1483,7 @@
assert(ptr != NULL);
assert(malloc_initialized || IS_INITIALIZER);
+ UTRACE(ptr, 0, 0);
if (config_stats)
usize = isalloc(ptr);
if (config_prof && opt_prof) {
diff --git a/src/stats.c b/src/stats.c
index 83baf56..0cd70b0 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -383,6 +383,7 @@
OPT_WRITE_BOOL(stats_print)
OPT_WRITE_BOOL(junk)
OPT_WRITE_BOOL(zero)
+ OPT_WRITE_BOOL(utrace)
OPT_WRITE_BOOL(xmalloc)
OPT_WRITE_BOOL(tcache)
OPT_WRITE_SSIZE_T(lg_tcache_max)