mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-30 10:37:37 +01:00
[dwarf] Need to guard against multiple threads accessing the rs cache.
Signed-off-by: Arun Sharma <arun.sharma@google.com>
This commit is contained in:
parent
8cdd8bfed8
commit
4312719cbc
1 changed files with 61 additions and 7 deletions
|
@ -472,10 +472,36 @@ flush_rs_cache (struct dwarf_rs_cache *cache)
|
||||||
cache->hash[i] = -1;
|
cache->hash[i] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dwarf_rs_cache *
|
static inline struct dwarf_rs_cache *
|
||||||
get_rs_cache (unw_addr_space_t as)
|
get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
|
||||||
{
|
{
|
||||||
struct dwarf_rs_cache *cache = &as->global_cache;
|
struct dwarf_rs_cache *cache = &as->global_cache;
|
||||||
|
unw_caching_policy_t caching = as->caching_policy;
|
||||||
|
|
||||||
|
if (caching == UNW_CACHE_NONE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_ATOMIC_H
|
||||||
|
if (!spin_trylock_irqsave (&cache->busy, *saved_maskp))
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
# ifdef HAVE___THREAD
|
||||||
|
if (as->caching_policy == UNW_CACHE_PER_THREAD)
|
||||||
|
cache = &dwarf_per_thread_cache;
|
||||||
|
# endif
|
||||||
|
# ifdef HAVE_ATOMIC_OPS_H
|
||||||
|
if (AO_test_and_set (&cache->busy) == AO_TS_SET)
|
||||||
|
return NULL;
|
||||||
|
# else
|
||||||
|
sigprocmask (SIG_SETMASK, &unwi_full_mask, saved_maskp);
|
||||||
|
if (likely (caching == UNW_CACHE_GLOBAL))
|
||||||
|
{
|
||||||
|
Debug (16, "%s: acquiring lock\n", __FUNCTION__);
|
||||||
|
mutex_lock (&cache->lock);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
|
if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
|
||||||
{
|
{
|
||||||
flush_rs_cache (cache);
|
flush_rs_cache (cache);
|
||||||
|
@ -485,6 +511,26 @@ get_rs_cache (unw_addr_space_t as)
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache,
|
||||||
|
intrmask_t *saved_maskp)
|
||||||
|
{
|
||||||
|
assert (as->caching_policy != UNW_CACHE_NONE);
|
||||||
|
|
||||||
|
Debug (16, "unmasking signals/interrupts and releasing lock\n");
|
||||||
|
#ifdef HAVE_ATOMIC_H
|
||||||
|
spin_unlock_irqrestore (&cache->busy, *saved_maskp);
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_ATOMIC_OPS_H
|
||||||
|
AO_CLEAR (&cache->busy);
|
||||||
|
# else
|
||||||
|
if (likely (as->caching_policy == UNW_CACHE_GLOBAL))
|
||||||
|
mutex_unlock (&cache->lock);
|
||||||
|
sigprocmask (SIG_SETMASK, saved_maskp, NULL);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static inline unw_hash_index_t
|
static inline unw_hash_index_t
|
||||||
hash (unw_word_t ip)
|
hash (unw_word_t ip)
|
||||||
{
|
{
|
||||||
|
@ -763,12 +809,15 @@ dwarf_find_save_locs (struct dwarf_cursor *c)
|
||||||
dwarf_state_record_t sr;
|
dwarf_state_record_t sr;
|
||||||
dwarf_reg_state_t *rs, *rs1;
|
dwarf_reg_state_t *rs, *rs1;
|
||||||
struct dwarf_rs_cache *cache;
|
struct dwarf_rs_cache *cache;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
intrmask_t saved_mask;
|
||||||
|
|
||||||
if (c->as->caching_policy == UNW_CACHE_NONE)
|
if (c->as->caching_policy == UNW_CACHE_NONE)
|
||||||
return uncached_dwarf_find_save_locs (c);
|
return uncached_dwarf_find_save_locs (c);
|
||||||
|
|
||||||
cache = get_rs_cache(c->as);
|
cache = get_rs_cache(c->as, &saved_mask);
|
||||||
|
if (!cache)
|
||||||
|
return -UNW_ENOINFO; /* cache is busy */
|
||||||
rs = rs_lookup(cache, c);
|
rs = rs_lookup(cache, c);
|
||||||
|
|
||||||
if (rs)
|
if (rs)
|
||||||
|
@ -778,10 +827,10 @@ dwarf_find_save_locs (struct dwarf_cursor *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = fetch_proc_info (c, c->ip, 1)) < 0)
|
if ((ret = fetch_proc_info (c, c->ip, 1)) < 0)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
if ((ret = create_state_record_for (c, &sr, c->ip)) < 0)
|
if ((ret = create_state_record_for (c, &sr, c->ip)) < 0)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
rs1 = &sr.rs_current;
|
rs1 = &sr.rs_current;
|
||||||
if (rs1)
|
if (rs1)
|
||||||
|
@ -792,7 +841,7 @@ dwarf_find_save_locs (struct dwarf_cursor *c)
|
||||||
{
|
{
|
||||||
dprintf ("%s: failed to create unwind rs\n", __FUNCTION__);
|
dprintf ("%s: failed to create unwind rs\n", __FUNCTION__);
|
||||||
ret = -UNW_EUNSPEC;
|
ret = -UNW_EUNSPEC;
|
||||||
return ret;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cache->buckets[c->prev_rs].hint = rs - cache->buckets;
|
cache->buckets[c->prev_rs].hint = rs - cache->buckets;
|
||||||
|
@ -802,7 +851,12 @@ dwarf_find_save_locs (struct dwarf_cursor *c)
|
||||||
|
|
||||||
put_unwind_info (c, &c->pi);
|
put_unwind_info (c, &c->pi);
|
||||||
|
|
||||||
|
out:
|
||||||
|
put_rs_cache (c->as, cache, &saved_mask);
|
||||||
|
return ret;
|
||||||
|
|
||||||
apply:
|
apply:
|
||||||
|
put_rs_cache (c->as, cache, &saved_mask);
|
||||||
if ((ret = apply_reg_state (c, rs)) < 0)
|
if ((ret = apply_reg_state (c, rs)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue