summaryrefslogtreecommitdiffstats
path: root/jemalloc/src
diff options
context:
space:
mode:
authorje@facebook.com <je@facebook.com>2010-06-05 00:36:05 (GMT)
committerJason Evans <je@fb.com>2011-03-24 00:45:57 (GMT)
commitadc675c8ef55b59bb2facf795a3c26411cfbf3ed (patch)
tree1145a5a34ac23de60b74a0be597efff7b5698705 /jemalloc/src
parent38d9210c464c4ad49655a4da6bc84ea4fbec83d2 (diff)
downloadjemalloc-adc675c8ef55b59bb2facf795a3c26411cfbf3ed.zip
jemalloc-adc675c8ef55b59bb2facf795a3c26411cfbf3ed.tar.gz
jemalloc-adc675c8ef55b59bb2facf795a3c26411cfbf3ed.tar.bz2
Add support for libunwind backtrace caching.
Use libunwind's unw_tdep_trace() if it is available.
Diffstat (limited to 'jemalloc/src')
-rw-r--r--jemalloc/src/prof.c94
1 files changed, 79 insertions, 15 deletions
diff --git a/jemalloc/src/prof.c b/jemalloc/src/prof.c
index 8370042..537c5c1 100644
--- a/jemalloc/src/prof.c
+++ b/jemalloc/src/prof.c
@@ -44,6 +44,12 @@ pthread_key_t prof_tdata_tsd;
static ckh_t bt2ctx;
static malloc_mutex_t bt2ctx_mtx;
+#ifdef JEMALLOC_PROF_LIBUNWIND_CACHE
+static __thread unw_tdep_cache_t *libunwind_cache_tls
+ JEMALLOC_ATTR(tls_model("initial-exec"));
+static pthread_key_t libunwind_cache_tsd;
+#endif
+
static malloc_mutex_t prof_dump_seq_mtx;
static uint64_t prof_dump_seq;
static uint64_t prof_dump_iseq;
@@ -95,6 +101,9 @@ static void prof_bt_hash(const void *key, unsigned minbits, size_t *hash1,
size_t *hash2);
static bool prof_bt_keycomp(const void *k1, const void *k2);
static void prof_tdata_cleanup(void *arg);
+#ifdef JEMALLOC_PROF_LIBUNWIND_CACHE
+static void libunwind_cache_thread_cleanup(void *arg);
+#endif
/******************************************************************************/
@@ -177,6 +186,11 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max)
unw_cursor_t cursor;
unsigned i;
int err;
+#ifdef JEMALLOC_PROF_LIBUNWIND_CACHE
+ unw_tdep_cache_t *cache;
+ int len = nignore + 1 + max;
+ void* vec[len];
+#endif
assert(bt->len == 0);
assert(bt->vec != NULL);
@@ -185,24 +199,53 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore, unsigned max)
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
- /* Throw away (nignore+1) stack frames, if that many exist. */
- for (i = 0; i < nignore + 1; i++) {
- err = unw_step(&cursor);
- if (err <= 0)
- return;
+#ifdef JEMALLOC_PROF_LIBUNWIND_CACHE
+ cache = libunwind_cache_tls;
+ if (cache == NULL) {
+ cache = unw_tdep_make_frame_cache(imalloc, idalloc);
+ if (cache != NULL) {
+ libunwind_cache_tls = cache;
+ pthread_setspecific(libunwind_cache_tsd, cache);
+ }
}
+ if (cache != NULL && unw_tdep_trace(&cursor, vec, &len, cache) >= 0) {
+ /*
+ * The trace cache successfully looked up the backtrace.
+ * Discard the first (nignore+1) elements when copying the
+ * result, since there was no way to tell unw_tdep_trace() to
+ * skip those frames.
+ */
+ assert(len >= nignore + 1);
+ len -= nignore + 1;
+ if (len > 0) {
+ memcpy(bt->vec, &vec[nignore + 1], sizeof(void *) *
+ len);
+ bt->len = len;
+ }
+ } else {
+#endif
+ /* Throw away (nignore+1) stack frames, if that many exist. */
+ for (i = 0; i < nignore + 1; i++) {
+ err = unw_step(&cursor);
+ if (err <= 0)
+ return;
+ }
- /*
- * Iterate over stack frames until there are no more, or until no space
- * remains in bt.
- */
- for (i = 0; i < max; i++) {
- unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *)&bt->vec[i]);
- bt->len++;
- err = unw_step(&cursor);
- if (err <= 0)
- break;
+ /*
+ * Iterate over stack frames until there are no more, or until
+ * no space remains in bt.
+ */
+ for (i = 0; i < max; i++) {
+ unw_get_reg(&cursor, UNW_REG_IP,
+ (unw_word_t *)&bt->vec[i]);
+ bt->len++;
+ err = unw_step(&cursor);
+ if (err <= 0)
+ break;
+ }
+#ifdef JEMALLOC_PROF_LIBUNWIND_CACHE
}
+#endif
}
#endif
#ifdef JEMALLOC_PROF_LIBGCC
@@ -1156,6 +1199,19 @@ prof_tdata_cleanup(void *arg)
}
}
+#ifdef JEMALLOC_PROF_LIBUNWIND_CACHE
+static void
+libunwind_cache_thread_cleanup(void *arg)
+{
+ unw_tdep_cache_t *cache = libunwind_cache_tls;
+
+ if (cache != NULL) {
+ unw_tdep_free_frame_cache(cache);
+ libunwind_cache_tls = NULL;
+ }
+}
+#endif
+
void
prof_boot0(void)
{
@@ -1208,6 +1264,14 @@ prof_boot2(void)
"<jemalloc>: Error in pthread_key_create()\n");
abort();
}
+#ifdef JEMALLOC_PROF_LIBUNWIND_CACHE
+ if (pthread_key_create(&libunwind_cache_tsd,
+ libunwind_cache_thread_cleanup) != 0) {
+ malloc_write(
+ "<jemalloc>: Error in pthread_key_create()\n");
+ abort();
+ }
+#endif
prof_bt_max = (1U << opt_lg_prof_bt_max);
if (malloc_mutex_init(&prof_dump_seq_mtx))