diff --git a/INSTALL b/INSTALL index c0ae106a..8a825df9 100644 --- a/INSTALL +++ b/INSTALL @@ -119,6 +119,10 @@ any of the following arguments (not a definitive list) to 'configure': --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 16f03784..8e94b5c9 100644 --- a/configure.ac +++ b/configure.ac @@ -699,6 +699,34 @@ if test "x$enable_fill" = "x1" ; then 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 +#include +#include +#include +#include +], [ + 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([prof-gcc : ${enable_prof_gcc}]) 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 7a2d033d..8ae82621 100644 --- a/doc/jemalloc.xml.in +++ b/doc/jemalloc.xml.in @@ -710,6 +710,16 @@ for (i = 0; i < nbins; i++) { build configuration. + + + config.utrace + (bool) + r- + + was specified during + build configuration. + + config.xmalloc @@ -826,6 +836,19 @@ for (i = 0; i < nbins; i++) { + + + opt.utrace + (bool) + r- + [] + + Allocation tracing based on + utrace + 2 enabled/disabled. This option + is disabled by default. + + opt.xmalloc @@ -1958,6 +1981,8 @@ malloc_conf = "lg_chunk:24";]]> 2, sbrk 2, + utrace + 2, alloca 3, atexit diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in index c8e40198..66dd357f 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 +#endif + #include "jemalloc/internal/private_namespace.h" #ifdef JEMALLOC_CC_SILENCE @@ -114,6 +118,13 @@ static const bool config_tls = 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 @@ typedef struct { 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 ed34e328..de3042eb 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 040753a6..8e7442d6 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 df7affdc..1aaf1971 100644 --- a/src/ctl.c +++ b/src/ctl.c @@ -56,6 +56,7 @@ CTL_PROTO(config_prof_libunwind) 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_lg_dirty_mult) 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 @@ static const ctl_node_t config_node[] = { {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 @@ static const ctl_node_t opt_node[] = { {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_prof_libunwind) 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_lg_dirty_mult, opt_lg_dirty_mult, ssize_t) 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 a531a216..e0510209 100644 --- a/src/jemalloc.c +++ b/src/jemalloc.c @@ -21,6 +21,7 @@ bool opt_junk = false; 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 @@ static bool malloc_initializer = NO_INITIALIZER; /* 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 @@ malloc_conf_init(void) 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 @@ OOM: assert(usize == isalloc(ret)); thread_allocated_tsd_get()->allocated += usize; } + UTRACE(0, size, ret); return (ret); } @@ -852,6 +877,7 @@ RETURN: } if (config_prof && opt_prof && result != NULL) prof_malloc(result, usize, cnt); + UTRACE(0, size, result); return (ret); } @@ -951,6 +977,7 @@ RETURN: assert(usize == isalloc(ret)); thread_allocated_tsd_get()->allocated += usize; } + UTRACE(0, num_size, ret); return (ret); } @@ -1075,6 +1102,7 @@ RETURN: ta->allocated += usize; ta->deallocated += old_size; } + UTRACE(ptr, size, ret); return (ret); } @@ -1083,6 +1111,7 @@ void je_free(void *ptr) { + UTRACE(ptr, 0, 0); if (ptr != NULL) { size_t usize; @@ -1310,6 +1339,7 @@ je_allocm(void **ptr, size_t *rsize, size_t size, int flags) 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 @@ OOM: abort(); } *ptr = NULL; + UTRACE(0, size, 0); return (ALLOCM_ERR_OOM); } @@ -1404,16 +1435,20 @@ je_rallocm(void **ptr, size_t *rsize, size_t size, size_t extra, int flags) 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(": Error in rallocm(): " "out of memory\n"); abort(); } + UTRACE(p, size, 0); return (ALLOCM_ERR_OOM); } @@ -1448,6 +1483,7 @@ je_dallocm(void *ptr, int flags) 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 83baf568..0cd70b0d 100644 --- a/src/stats.c +++ b/src/stats.c @@ -383,6 +383,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque, 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)