Improve backtracing-related configuration.

Clean up configuration for backtracing when profiling is enabled, and
document the configuration logic in INSTALL.

Disable libgcc-based backtracing except on x64 (where it is known to
work).

Add the --disable-prof-gcc option.
This commit is contained in:
Jason Evans 2011-03-15 22:23:12 -07:00
parent b602daa671
commit 77f350be08
4 changed files with 140 additions and 83 deletions

View File

@ -62,18 +62,23 @@ any of the following arguments (not a definitive list) to 'configure':
--enable-prof --enable-prof
Enable heap profiling and leak detection functionality. See the "opt.prof" Enable heap profiling and leak detection functionality. See the "opt.prof"
option documentation for usage details. option documentation for usage details. When enabled, there are several
approaches to backtracing, and the configure script chooses the first one
in the following list that appears to function correctly:
--disable-prof-libgcc + libunwind (requires --enable-prof-libunwind)
Disable the use of libgcc's backtracing functionality. Ordinarily, libgcc's + libgcc (unless --disable-prof-libgcc)
backtracing functionality is superior to the alternatives, but it may fail + gcc intrinsics (unless --disable-prof-gcc)
to capture backtraces on some systems.
--enable-prof-libunwind --enable-prof-libunwind
Use the libunwind library (http://www.nongnu.org/libunwind/) for stack Use the libunwind library (http://www.nongnu.org/libunwind/) for stack
backtracing. libunwind is quite slow, but it tends to work across a wider backtracing.
variety of system configurations than the default backtracing code, which is
based on libgcc functionality or gcc intrinsics. --disable-prof-libgcc
Disable the use of libgcc's backtracing functionality.
--disable-prof-gcc
Disable the use of gcc intrinsics for backtracing.
--with-static-libunwind=<libunwind.a> --with-static-libunwind=<libunwind.a>
Statically link against the specified libunwind.a rather than dynamically Statically link against the specified libunwind.a rather than dynamically

View File

@ -404,17 +404,12 @@ fi
], ],
[enable_prof="0"] [enable_prof="0"]
) )
AC_ARG_ENABLE([prof-libgcc], if test "x$enable_prof" = "x1" ; then
[AS_HELP_STRING([--disable-prof-libgcc], backtrace_method=""
[Do not use libgcc for backtracing])],
[if test "x$enable_prof_libgcc" = "xno" ; then
enable_prof_libgcc="0"
else else
enable_prof_libgcc="1" backtrace_method="N/A"
fi fi
],
[enable_prof_libgcc="1"]
)
AC_ARG_ENABLE([prof-libunwind], AC_ARG_ENABLE([prof-libunwind],
[AS_HELP_STRING([--enable-prof-libunwind], [Use libunwind for backtracing])], [AS_HELP_STRING([--enable-prof-libunwind], [Use libunwind for backtracing])],
[if test "x$enable_prof_libunwind" = "xno" ; then [if test "x$enable_prof_libunwind" = "xno" ; then
@ -438,10 +433,7 @@ else
fi, fi,
LUNWIND="-lunwind" LUNWIND="-lunwind"
) )
if test "x$enable_prof" = "x1" ; then if test "x$backtrace_method" = "x" -a "x$enable_prof_libunwind" = "x1" ; then
LIBS="$LIBS -lm"
AC_DEFINE([JEMALLOC_PROF], [ ])
if test "x$enable_prof_libunwind" = "x1" ; then
AC_CHECK_HEADERS([libunwind.h], , [enable_prof_libunwind="0"]) AC_CHECK_HEADERS([libunwind.h], , [enable_prof_libunwind="0"])
if test "x$LUNWIND" = "x-lunwind" ; then if test "x$LUNWIND" = "x-lunwind" ; then
AC_CHECK_LIB([unwind], [backtrace], [LIBS="$LIBS $LUNWIND"], AC_CHECK_LIB([unwind], [backtrace], [LIBS="$LIBS $LUNWIND"],
@ -450,26 +442,80 @@ if test "x$enable_prof" = "x1" ; then
LIBS="$LIBS $LUNWIND" LIBS="$LIBS $LUNWIND"
fi fi
if test "x${enable_prof_libunwind}" = "x1" ; then if test "x${enable_prof_libunwind}" = "x1" ; then
backtrace_method="libunwind"
AC_DEFINE([JEMALLOC_PROF_LIBUNWIND], [ ]) AC_DEFINE([JEMALLOC_PROF_LIBUNWIND], [ ])
fi fi
fi fi
fi
AC_SUBST([enable_prof])
dnl If libunwind isn't enabled, try to use libgcc rather than gcc intrinsics AC_ARG_ENABLE([prof-libgcc],
dnl for backtracing. [AS_HELP_STRING([--disable-prof-libgcc],
if test "x$enable_prof" = "x1" -a "x$enable_prof_libgcc" = "x1" ; then [Do not use libgcc for backtracing])],
if test "x$enable_prof_libunwind" = "x0" -a "x$GCC" = "xyes" ; then [if test "x$enable_prof_libgcc" = "xno" ; then
enable_prof_libgcc="0"
else
enable_prof_libgcc="1" enable_prof_libgcc="1"
fi
],
[enable_prof_libgcc="1"]
)
if test "x$backtrace_method" = "x" -a "x$enable_prof_libgcc" = "x1" \
-a "x$GCC" = "xyes" ; then
AC_CHECK_HEADERS([unwind.h], , [enable_prof_libgcc="0"]) AC_CHECK_HEADERS([unwind.h], , [enable_prof_libgcc="0"])
AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [LIBS="$LIBS -lgcc"], [enable_prof_libgcc="0"]) AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [LIBS="$LIBS -lgcc"], [enable_prof_libgcc="0"])
dnl The following is conservative, in that it only has entries for CPUs on
dnl which jemalloc has been tested.
AC_MSG_CHECKING([libgcc-based backtracing reliability on ${host_cpu}])
case "${host_cpu}" in
i[[3456]]86)
AC_MSG_RESULT([unreliable])
enable_prof_libgcc="0";
;;
x86_64)
AC_MSG_RESULT([reliable])
;;
*)
AC_MSG_RESULT([unreliable])
enable_prof_libgcc="0";
;;
esac
if test "x${enable_prof_libgcc}" = "x1" ; then if test "x${enable_prof_libgcc}" = "x1" ; then
backtrace_method="libgcc"
AC_DEFINE([JEMALLOC_PROF_LIBGCC], [ ]) AC_DEFINE([JEMALLOC_PROF_LIBGCC], [ ])
fi fi
else else
enable_prof_libgcc="0" enable_prof_libgcc="0"
fi fi
AC_ARG_ENABLE([prof-gcc],
[AS_HELP_STRING([--disable-prof-gcc],
[Do not use gcc intrinsics for backtracing])],
[if test "x$enable_prof_gcc" = "xno" ; then
enable_prof_gcc="0"
else
enable_prof_gcc="1"
fi fi
],
[enable_prof_gcc="1"]
)
if test "x$backtrace_method" = "x" -a "x$enable_prof_gcc" = "x1" \
-a "x$GCC" = "xyes" ; then
backtrace_method="gcc intrinsics"
AC_DEFINE([JEMALLOC_PROF_GCC], [ ])
else
enable_prof_gcc="0"
fi
if test "x$backtrace_method" = "x" ; then
backtrace_method="none (disabling profiling)"
enable_prof="0"
fi
AC_MSG_CHECKING([configured backtracing method])
AC_MSG_RESULT([$backtrace_method])
if test "x$enable_prof" = "x1" ; then
LIBS="$LIBS -lm"
AC_DEFINE([JEMALLOC_PROF], [ ])
fi
AC_SUBST([enable_prof])
dnl Enable tiny allocations by default. dnl Enable tiny allocations by default.
AC_ARG_ENABLE([tiny], AC_ARG_ENABLE([tiny],
@ -810,8 +856,9 @@ AC_MSG_RESULT([cc-silence : ${enable_cc_silence}])
AC_MSG_RESULT([debug : ${enable_debug}]) AC_MSG_RESULT([debug : ${enable_debug}])
AC_MSG_RESULT([stats : ${enable_stats}]) AC_MSG_RESULT([stats : ${enable_stats}])
AC_MSG_RESULT([prof : ${enable_prof}]) AC_MSG_RESULT([prof : ${enable_prof}])
AC_MSG_RESULT([prof-libgcc : ${enable_prof_libgcc}])
AC_MSG_RESULT([prof-libunwind : ${enable_prof_libunwind}]) AC_MSG_RESULT([prof-libunwind : ${enable_prof_libunwind}])
AC_MSG_RESULT([prof-libgcc : ${enable_prof_libgcc}])
AC_MSG_RESULT([prof-gcc : ${enable_prof_gcc}])
AC_MSG_RESULT([tiny : ${enable_tiny}]) AC_MSG_RESULT([tiny : ${enable_tiny}])
AC_MSG_RESULT([tcache : ${enable_tcache}]) AC_MSG_RESULT([tcache : ${enable_tcache}])
AC_MSG_RESULT([fill : ${enable_fill}]) AC_MSG_RESULT([fill : ${enable_fill}])

View File

@ -53,6 +53,9 @@
/* Use libgcc for profile backtracing if defined. */ /* Use libgcc for profile backtracing if defined. */
#undef JEMALLOC_PROF_LIBGCC #undef JEMALLOC_PROF_LIBGCC
/* Use gcc intrinsics for profile backtracing if defined. */
#undef JEMALLOC_PROF_GCC
/* /*
* JEMALLOC_TINY enables support for tiny objects, which are smaller than one * JEMALLOC_TINY enables support for tiny objects, which are smaller than one
* quantum. * quantum.

View File

@ -3,15 +3,15 @@
#ifdef JEMALLOC_PROF #ifdef JEMALLOC_PROF
/******************************************************************************/ /******************************************************************************/
#ifdef JEMALLOC_PROF_LIBGCC
#include <unwind.h>
#endif
#ifdef JEMALLOC_PROF_LIBUNWIND #ifdef JEMALLOC_PROF_LIBUNWIND
#define UNW_LOCAL_ONLY #define UNW_LOCAL_ONLY
#include <libunwind.h> #include <libunwind.h>
#endif #endif
#ifdef JEMALLOC_PROF_LIBGCC
#include <unwind.h>
#endif
/******************************************************************************/ /******************************************************************************/
/* Data. */ /* Data. */
@ -169,39 +169,7 @@ prof_leave(void)
prof_gdump(); prof_gdump();
} }
#ifdef JEMALLOC_PROF_LIBGCC #ifdef JEMALLOC_PROF_LIBUNWIND
static _Unwind_Reason_Code
prof_unwind_init_callback(struct _Unwind_Context *context, void *arg)
{
return (_URC_NO_REASON);
}
static _Unwind_Reason_Code
prof_unwind_callback(struct _Unwind_Context *context, void *arg)
{
prof_unwind_data_t *data = (prof_unwind_data_t *)arg;
if (data->nignore > 0)
data->nignore--;
else {
data->bt->vec[data->bt->len] = (void *)_Unwind_GetIP(context);
data->bt->len++;
if (data->bt->len == data->max)
return (_URC_END_OF_STACK);
}
return (_URC_NO_REASON);
}
void
prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max)
{
prof_unwind_data_t data = {bt, nignore, max};
_Unwind_Backtrace(prof_unwind_callback, &data);
}
#elif defined(JEMALLOC_PROF_LIBUNWIND)
void void
prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max) prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max)
{ {
@ -236,7 +204,41 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max)
break; break;
} }
} }
#else #endif
#ifdef JEMALLOC_PROF_LIBGCC
static _Unwind_Reason_Code
prof_unwind_init_callback(struct _Unwind_Context *context, void *arg)
{
return (_URC_NO_REASON);
}
static _Unwind_Reason_Code
prof_unwind_callback(struct _Unwind_Context *context, void *arg)
{
prof_unwind_data_t *data = (prof_unwind_data_t *)arg;
if (data->nignore > 0)
data->nignore--;
else {
data->bt->vec[data->bt->len] = (void *)_Unwind_GetIP(context);
data->bt->len++;
if (data->bt->len == data->max)
return (_URC_END_OF_STACK);
}
return (_URC_NO_REASON);
}
void
prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max)
{
prof_unwind_data_t data = {bt, nignore, max};
_Unwind_Backtrace(prof_unwind_callback, &data);
}
#endif
#ifdef JEMALLOC_PROF_GCC
void void
prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max) prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max)
{ {