From 57257060c9d56cf9d1a499d71e3ca1eb51cd279d Mon Sep 17 00:00:00 2001 From: Bert Wesarg Date: Mon, 27 Mar 2017 10:24:26 +0200 Subject: [PATCH] Bring back support for UNW_CACHE_PER_THREAD. Needs to be build with --enable-per-thread-cache. Default caching policy is also UNW_CACHE_PER_THREAD than. --- configure.ac | 11 ++++++++++- include/dwarf.h | 7 ------- include/libunwind_i.h | 9 ++++----- include/tdep-tilegx/libunwind_i.h | 4 ---- src/aarch64/Ginit.c | 2 +- src/arm/Ginit.c | 2 +- src/dwarf/Gparser.c | 12 ++++++++++++ src/hppa/Ginit.c | 2 +- src/ia64/Ginit.c | 2 +- src/ia64/Gscript.c | 4 ++-- src/mi/Gset_cache_size.c | 6 ++++++ src/mi/Gset_caching_policy.c | 2 +- src/mips/Ginit.c | 2 +- src/ppc32/Ginit.c | 2 +- src/ppc64/Ginit.c | 2 +- src/sh/Ginit.c | 2 +- src/tilegx/Ginit.c | 2 +- src/x86/Ginit.c | 2 +- src/x86_64/Ginit.c | 2 +- tests/Gperf-simple.c | 2 ++ tests/Gperf-trace.c | 2 ++ 21 files changed, 50 insertions(+), 31 deletions(-) diff --git a/configure.ac b/configure.ac index d4007535..1ce4583e 100644 --- a/configure.ac +++ b/configure.ac @@ -298,7 +298,16 @@ fi AC_SUBST([LIBLZMA]) AM_CONDITIONAL(HAVE_LZMA, test x$enable_minidebuginfo = xyes) -LIBUNWIND___THREAD +AC_MSG_CHECKING([whether to support UNW_CACHE_PER_THREAD]) +AC_ARG_ENABLE([per-thread-cache], +AS_HELP_STRING([--enable-per-thread-cache], [build with support for UNW_CACHE_PER_THREAD (which imposes a hight TLS memory usage) (default: disabled)])) +AC_MSG_RESULT([$enable_per_thread_cache]) +AS_IF([test x$enable_per_thread_cache = xyes], [ + LIBUNWIND___THREAD + AS_IF([test x$libc_cv_gcc___thread = xno], [ + AC_MSG_FAILURE([UNW_CACHE_PER_THREAD requires __thread]) + ]) +]) AC_MSG_CHECKING([for Intel compiler]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[#ifndef __INTEL_COMPILER diff --git a/include/dwarf.h b/include/dwarf.h index e8ffa66c..db2a7697 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -37,13 +37,6 @@ struct elf_dyn_info; # include "config.h" #endif -#ifdef HAVE___THREAD - /* For now, turn off per-thread caching. It uses up too much TLS - memory per thread even when the thread never uses libunwind at - all. */ -# undef HAVE___THREAD -#endif - #ifndef UNW_REMOTE_ONLY #if defined(HAVE_LINK_H) #include diff --git a/include/libunwind_i.h b/include/libunwind_i.h index ee2ea2fb..2b45ea9c 100644 --- a/include/libunwind_i.h +++ b/include/libunwind_i.h @@ -37,11 +37,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "compiler.h" -#ifdef HAVE___THREAD - /* For now, turn off per-thread caching. It uses up too much TLS - memory per thread even when the thread never uses libunwind at - all. */ -# undef HAVE___THREAD +#if defined(HAVE___THREAD) && HAVE___THREAD +#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_PER_THREAD +#else +#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_GLOBAL #endif /* Platform-independent libunwind-internal declarations. */ diff --git a/include/tdep-tilegx/libunwind_i.h b/include/tdep-tilegx/libunwind_i.h index 4a598f84..2cfed456 100644 --- a/include/tdep-tilegx/libunwind_i.h +++ b/include/tdep-tilegx/libunwind_i.h @@ -36,10 +36,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "mempool.h" #include "dwarf.h" -#ifdef HAVE___THREAD -# undef HAVE___THREAD -#endif - typedef struct { /* no Tilegx-specific fast trace */ diff --git a/src/aarch64/Ginit.c b/src/aarch64/Ginit.c index b9181ef0..667c4764 100644 --- a/src/aarch64/Ginit.c +++ b/src/aarch64/Ginit.c @@ -172,7 +172,7 @@ HIDDEN void aarch64_local_addr_space_init (void) { memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = dwarf_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/src/arm/Ginit.c b/src/arm/Ginit.c index a23124d7..2d0b2ca8 100644 --- a/src/arm/Ginit.c +++ b/src/arm/Ginit.c @@ -220,7 +220,7 @@ HIDDEN void arm_local_addr_space_init (void) { memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = arm_find_proc_info; local_addr_space.acc.put_unwind_info = arm_put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 25f2d2c6..e8eaeac8 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -606,7 +606,17 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp) if (caching == UNW_CACHE_NONE) return NULL; +#if defined(HAVE___THREAD) && HAVE___THREAD + if (likely (caching == UNW_CACHE_PER_THREAD)) + { + static __thread struct dwarf_rs_cache tls_cache __attribute__((tls_model("initial-exec"))); + Debug (16, "using TLS cache\n"); + cache = &tls_cache; + } + else +#else if (likely (caching == UNW_CACHE_GLOBAL)) +#endif { Debug (16, "acquiring lock\n"); lock_acquire (&cache->lock, *saved_maskp); @@ -615,6 +625,8 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp) if ((atomic_read (&as->cache_generation) != atomic_read (&cache->generation)) || !cache->hash) { + /* cache_size is only set in the global_cache, copy it over before flushing */ + cache->log_size = as->global_cache.log_size; if (dwarf_flush_rs_cache (cache) < 0) return NULL; cache->generation = as->cache_generation; diff --git a/src/hppa/Ginit.c b/src/hppa/Ginit.c index 89ad51ca..28779c39 100644 --- a/src/hppa/Ginit.c +++ b/src/hppa/Ginit.c @@ -179,7 +179,7 @@ HIDDEN void hppa_local_addr_space_init (void) { memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = dwarf_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/src/ia64/Ginit.c b/src/ia64/Ginit.c index 7b64f0c1..395450ec 100644 --- a/src/ia64/Ginit.c +++ b/src/ia64/Ginit.c @@ -361,7 +361,7 @@ ia64_local_addr_space_init (void) #elif defined(__hpux) local_addr_space.abi = ABI_HPUX; #endif - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = tdep_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/src/ia64/Gscript.c b/src/ia64/Gscript.c index e96e89e0..526aeaf2 100644 --- a/src/ia64/Gscript.c +++ b/src/ia64/Gscript.c @@ -45,7 +45,7 @@ enum ia64_script_insn_opcode IA64_INSN_MOVE_SCRATCH_NO_NAT /* like above, but clear NaT info */ }; -#ifdef HAVE___THREAD +#if defined(HAVE___THREAD) && HAVE___THREAD static __thread struct ia64_script_cache ia64_per_thread_cache = { #ifdef HAVE_ATOMIC_OPS_H @@ -105,7 +105,7 @@ get_script_cache (unw_addr_space_t as, intrmask_t *saved_maskp) if (!spin_trylock_irqsave (&cache->busy, *saved_maskp)) return NULL; #else -# ifdef HAVE___THREAD +# if defined(HAVE___THREAD) && HAVE___THREAD if (as->caching_policy == UNW_CACHE_PER_THREAD) cache = &ia64_per_thread_cache; # endif diff --git a/src/mi/Gset_cache_size.c b/src/mi/Gset_cache_size.c index 7ae1187a..a0d8b5bf 100644 --- a/src/mi/Gset_cache_size.c +++ b/src/mi/Gset_cache_size.c @@ -38,6 +38,12 @@ unw_set_cache_size (unw_addr_space_t as, size_t size, int flag) if (flag != 0) return -1; + /* Currently not supported for per-thread cache due to memory leak */ + /* A pthread-key destructor would work, but is not signal safe */ +#if defined(HAVE___THREAD) && HAVE___THREAD + return -1; +#endif + /* Round up to next power of two, slowly but portably */ while(power < size) { diff --git a/src/mi/Gset_caching_policy.c b/src/mi/Gset_caching_policy.c index 45ba1001..9df9eb82 100644 --- a/src/mi/Gset_caching_policy.c +++ b/src/mi/Gset_caching_policy.c @@ -31,7 +31,7 @@ unw_set_caching_policy (unw_addr_space_t as, unw_caching_policy_t policy) if (!tdep_init_done) tdep_init (); -#ifndef HAVE___THREAD +#if !(defined(HAVE___THREAD) && HAVE___THREAD) if (policy == UNW_CACHE_PER_THREAD) policy = UNW_CACHE_GLOBAL; #endif diff --git a/src/mips/Ginit.c b/src/mips/Ginit.c index 83b100fb..077a386c 100644 --- a/src/mips/Ginit.c +++ b/src/mips/Ginit.c @@ -195,7 +195,7 @@ mips_local_addr_space_init (void) # error Unsupported ABI #endif local_addr_space.addr_size = sizeof (void *); - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = dwarf_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/src/ppc32/Ginit.c b/src/ppc32/Ginit.c index f2e6e823..dc599b9d 100644 --- a/src/ppc32/Ginit.c +++ b/src/ppc32/Ginit.c @@ -201,7 +201,7 @@ HIDDEN void ppc32_local_addr_space_init (void) { memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = dwarf_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/src/ppc64/Ginit.c b/src/ppc64/Ginit.c index 3211cf4d..287ecf49 100644 --- a/src/ppc64/Ginit.c +++ b/src/ppc64/Ginit.c @@ -214,7 +214,7 @@ ppc64_local_addr_space_init (void) #else local_addr_space.abi = UNW_PPC64_ABI_ELFv1; #endif - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = dwarf_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/src/sh/Ginit.c b/src/sh/Ginit.c index b380db1d..0bfac490 100644 --- a/src/sh/Ginit.c +++ b/src/sh/Ginit.c @@ -171,7 +171,7 @@ HIDDEN void sh_local_addr_space_init (void) { memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = dwarf_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/src/tilegx/Ginit.c b/src/tilegx/Ginit.c index df3ffcaa..a0bb69d7 100644 --- a/src/tilegx/Ginit.c +++ b/src/tilegx/Ginit.c @@ -152,7 +152,7 @@ tilegx_local_addr_space_init (void) local_addr_space.abi = UNW_TILEGX_ABI_N64; local_addr_space.addr_size = sizeof (void *); - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = dwarf_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c index b05a08ed..876990fe 100644 --- a/src/x86/Ginit.c +++ b/src/x86/Ginit.c @@ -228,7 +228,7 @@ HIDDEN void x86_local_addr_space_init (void) { memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = dwarf_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c index 78275762..2bb238e1 100644 --- a/src/x86_64/Ginit.c +++ b/src/x86_64/Ginit.c @@ -273,7 +273,7 @@ HIDDEN void x86_64_local_addr_space_init (void) { memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; local_addr_space.acc.find_proc_info = dwarf_find_proc_info; local_addr_space.acc.put_unwind_info = put_unwind_info; local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; diff --git a/tests/Gperf-simple.c b/tests/Gperf-simple.c index 21734066..e1819182 100644 --- a/tests/Gperf-simple.c +++ b/tests/Gperf-simple.c @@ -249,6 +249,8 @@ main (int argc, char **argv) measure_init (); + doit ("default "); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE); doit ("no cache "); diff --git a/tests/Gperf-trace.c b/tests/Gperf-trace.c index cc4fac68..4d24fa5c 100644 --- a/tests/Gperf-trace.c +++ b/tests/Gperf-trace.c @@ -235,6 +235,8 @@ main (int argc, char **argv) measure_init (); + doit ("default "); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE); doit ("no cache ");