summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert Wesarg <bert.wesarg@tu-dresden.de>2017-03-27 10:24:26 +0200
committerDave Watson <davejwatson@fb.com>2017-08-15 10:34:28 -0700
commit57257060c9d56cf9d1a499d71e3ca1eb51cd279d (patch)
treef1866aeb297333db23283a1b50c40e52f5ab7b22
parentac1427d87fd9254366d9e262c5b9f35676f3cc10 (diff)
downloadlibunwind-57257060c9d56cf9d1a499d71e3ca1eb51cd279d.tar.gz
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.
-rw-r--r--configure.ac11
-rw-r--r--include/dwarf.h7
-rw-r--r--include/libunwind_i.h9
-rw-r--r--include/tdep-tilegx/libunwind_i.h4
-rw-r--r--src/aarch64/Ginit.c2
-rw-r--r--src/arm/Ginit.c2
-rw-r--r--src/dwarf/Gparser.c12
-rw-r--r--src/hppa/Ginit.c2
-rw-r--r--src/ia64/Ginit.c2
-rw-r--r--src/ia64/Gscript.c4
-rw-r--r--src/mi/Gset_cache_size.c6
-rw-r--r--src/mi/Gset_caching_policy.c2
-rw-r--r--src/mips/Ginit.c2
-rw-r--r--src/ppc32/Ginit.c2
-rw-r--r--src/ppc64/Ginit.c2
-rw-r--r--src/sh/Ginit.c2
-rw-r--r--src/tilegx/Ginit.c2
-rw-r--r--src/x86/Ginit.c2
-rw-r--r--src/x86_64/Ginit.c2
-rw-r--r--tests/Gperf-simple.c2
-rw-r--r--tests/Gperf-trace.c2
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 <link.h>
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 ");