1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-06-26 03:11:44 +02:00

[x86-64] Add a known good address cache.

This improves the performance of Lperf-simple from 500ns to 195ns
on the avg.

Signed-off-by: Arun Sharma <arun.sharma@google.com>
This commit is contained in:
Arun Sharma (अरुण) 2006-08-02 21:10:52 -07:00 committed by David Mosberger-Tang
parent 96969f8494
commit 795529eee3
3 changed files with 44 additions and 1 deletions

View file

@ -50,6 +50,7 @@ struct unw_addr_space
unw_word_t dyn_generation; /* see dyn-common.h */
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
struct dwarf_rs_cache global_cache;
int validate;
};
struct cursor

View file

@ -107,6 +107,43 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
#define PAGE_SIZE 4096
#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1))
/* Cache of already validated addresses */
#define NLGA 4
static unw_word_t last_good_addr[NLGA];
static int lga_victim;
static int
validate_mem (unw_word_t addr)
{
int i, victim;
addr = PAGE_START(addr);
for (i = 0; i < NLGA; i++) {
if (last_good_addr[i] && (addr == last_good_addr[i]))
return 0;
}
if (msync((void *) addr, 1, MS_SYNC) == -1)
return -1;
victim = lga_victim;
for (i = 0; i < NLGA; i++) {
if (!last_good_addr[victim]) {
last_good_addr[victim++] = addr;
return 0;
}
victim = (victim + 1) % NLGA;
}
/* All slots full. Evict the victim. */
last_good_addr[victim] = addr;
victim = (victim + 1) % NLGA;
lga_victim = victim;
return 0;
}
static int
access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
void *arg)
@ -119,7 +156,7 @@ access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
else
{
/* validate address */
if (msync(PAGE_START(addr), 1, MS_SYNC) == -1)
if (as->validate && validate_mem(addr))
return -1;
*val = *(unw_word_t *) addr;
Debug (16, "mem[%016lx] -> %lx\n", addr, *val);
@ -212,6 +249,10 @@ x86_64_local_addr_space_init (void)
local_addr_space.acc.resume = x86_64_local_resume;
local_addr_space.acc.get_proc_name = get_static_proc_name;
unw_flush_cache (&local_addr_space, 0, 0);
local_addr_space.validate = 0;
bzero(last_good_addr, sizeof(unw_word_t) * NLGA);
lga_victim = 0;
}
#endif /* !UNW_REMOTE_ONLY */

View file

@ -40,6 +40,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
as = c->dwarf.as;
a = unw_get_accessors (as);
as->validate = 1; /* Don't trust the ip */
arg = c->dwarf.as_arg;
/* Check if RIP points at sigreturn sequence.