Greetings, Currently, libunwind may "give up" and produce an incomplete stack trace if two threads are both using libunwind to collect their stack traces.
Attached patch implements a new configure option --enable-cache-wait, which lets libunwind to wait for dwarf cache to become available. Thanks, -- Paul Pluzhnikov commit f7c22c16a0640f63c22a79864ca136cb9820f97e Author: Paul Pluzhnikov <[email protected]> Date: Mon Sep 21 13:25:57 2009 -0700 New configure option: when rs_cache is busy in another thread, wait for it. diff --git a/configure.in b/configure.in index 6e55563..57254c2 100644 --- a/configure.in +++ b/configure.in @@ -146,6 +146,12 @@ if test x$enable_block_signals = xyes; then AC_DEFINE([CONFIG_BLOCK_SIGNALS], [], [Block signals before mutex operations]) fi +AC_ARG_ENABLE(cache_wait, +[ --enable-cache-wait Wait for cache, rather than giving incomplete stack], +[enable_cache_wait=$enableval], [enable_cache_wait=no]) +if test x$enable_cache_wait = xyes; then + AC_DEFINE([CONFIG_CACHE_WAIT], [], [Wait for cache]) +fi LIBUNWIND___THREAD diff --git a/include/dwarf.h b/include/dwarf.h index c7c757e..cf0cf5a 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -312,7 +312,8 @@ typedef unsigned char unw_hash_index_t; struct dwarf_rs_cache { -#ifdef HAVE_ATOMIC_OPS_H +#if (defined(HAVE_ATOMIC_OPS_H) || defined(HAVE_ATOMIC_H)) \ + && !defined(CONFIG_CACHE_WAIT) AO_TS_t busy; /* is the rs-cache busy? */ #else pthread_mutex_t lock; diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 3969cb3..3a15344 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -481,20 +481,18 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp) if (caching == UNW_CACHE_NONE) return NULL; -#ifdef HAVE_ATOMIC_H +#if defined(HAVE_ATOMIC_H) && !defined(CONFIG_CACHE_WAIT) if (!spin_trylock_irqsave (&cache->busy, *saved_maskp)) return NULL; -#else -# ifdef HAVE_ATOMIC_OPS_H +#elif defined(HAVE_ATOMIC_OPS_H) && !defined(CONFIG_CACHE_WAIT) if (AO_test_and_set (&cache->busy) == AO_TS_SET) return NULL; -# else +#else if (likely (caching == UNW_CACHE_GLOBAL)) { Debug (16, "%s: acquiring lock\n", __FUNCTION__); lock_acquire (&cache->lock, *saved_maskp); } -# endif #endif if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation)) @@ -513,15 +511,13 @@ put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache, assert (as->caching_policy != UNW_CACHE_NONE); Debug (16, "unmasking signals/interrupts and releasing lock\n"); -#ifdef HAVE_ATOMIC_H +#if defined(HAVE_ATOMIC_H) && !defined(CONFIG_CACHE_WAIT) spin_unlock_irqrestore (&cache->busy, *saved_maskp); -#else -# ifdef HAVE_ATOMIC_OPS_H +#elif defined(HAVE_ATOMIC_OPS_H) && !defined(CONFIG_CACHE_WAIT) AO_CLEAR (&cache->busy); -# else +#else if (likely (as->caching_policy == UNW_CACHE_GLOBAL)) lock_release (&cache->lock, *saved_maskp); -# endif #endif } _______________________________________________ Libunwind-devel mailing list [email protected] http://lists.nongnu.org/mailman/listinfo/libunwind-devel
