summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilian Wolff <mail@milianw.de>2018-05-04 21:55:52 +0200
committerMilian Wolff <mail@milianw.de>2018-05-07 21:38:19 +0200
commitcd8c5d70d4358aee3dc9fee53e9870d0501cc6db (patch)
tree75c29c70501c52b61d4aaddf8009d4676a15dae0
parent3d473e183da99d9965112e45ab43f4d06c01ccab (diff)
downloadlibunwind-cd8c5d70d4358aee3dc9fee53e9870d0501cc6db.tar.gz
Optionally use a thread-local cache for valid memory
When libunwind is compiled with per-thread-caches, then also make the cache of valid memory addresses thread-local.
-rw-r--r--src/x86_64/Ginit.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c
index 21d8c496..669e9edb 100644
--- a/src/x86_64/Ginit.c
+++ b/src/x86_64/Ginit.c
@@ -174,8 +174,45 @@ tdep_init_mem_validate (void)
}
/* Cache of already validated addresses */
-#if HAVE_ATOMIC_OPS_H
+#if defined(HAVE___THREAD) && HAVE___THREAD
#define NLGA 4
+// thread-local variant
+static __thread unw_word_t last_good_addr[NLGA];
+static __thread int lga_victim;
+
+static int
+is_cached_valid_mem(unw_word_t addr)
+{
+ int i;
+ for (i = 0; i < NLGA; i++)
+ {
+ if (addr == &last_good_addr[i])
+ return 1;
+ }
+ return 0;
+}
+
+static void
+cache_valid_mem(unw_word_t addr)
+{
+ int i, victim;
+ victim = lga_victim;
+ for (i = 0; i < NLGA; i++) {
+ if (last_good_addr[victim] == 0) {
+ last_good_addr[victim] = addr;
+ return;
+ }
+ victim = (victim + 1) % NLGA;
+ }
+
+ /* All slots full. Evict the victim. */
+ last_good_addr[victim] = addr;
+ victim = (victim + 1) % NLGA;
+ lga_victim = victim;
+}
+
+#elif HAVE_ATOMIC_OPS_H
+// global, thread safe variant
static AO_T last_good_addr[NLGA];
static AO_T lga_victim;
@@ -209,6 +246,7 @@ cache_valid_mem(unw_word_t addr)
AO_store(&lga_victim, victim);
}
#else
+// disabled, no cache
static int
is_cached_valid_mem(unw_word_t addr UNUSED)
{