mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-25 16:47:38 +01:00
dwarf: Configurable cache size
Add interface for configurable dwarf cache size * Use item size and round up to nearest power of 2. * Initial cache still exists in BSS. Without this, it means we would fail backtrace when out of memory. The test-mem test fails without this
This commit is contained in:
parent
29483327be
commit
a51cf49031
19 changed files with 314 additions and 32 deletions
|
@ -17,6 +17,7 @@ man3_MANS = libunwind.man libunwind-dynamic.man libunwind-ia64.man \
|
|||
unw_destroy_addr_space.man \
|
||||
unw_regname.man unw_resume.man \
|
||||
unw_set_caching_policy.man \
|
||||
unw_set_cache_size.man \
|
||||
unw_set_fpreg.man \
|
||||
unw_set_reg.man \
|
||||
unw_step.man \
|
||||
|
@ -41,6 +42,7 @@ EXTRA_DIST = NOTES libunwind.trans \
|
|||
unw_is_signal_frame.tex \
|
||||
unw_create_addr_space.tex unw_destroy_addr_space.tex \
|
||||
unw_regname.tex unw_resume.tex unw_set_caching_policy.tex \
|
||||
unw_set_cache_size.tex \
|
||||
unw_set_fpreg.tex \
|
||||
unw_set_reg.tex \
|
||||
unw_step.tex \
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
'\" t
|
||||
.\" Manual page created with latex2man on Thu Aug 16 09:44:43 MDT 2007
|
||||
.\" Manual page created with latex2man on Thu Jan 12 06:50:29 PST 2017
|
||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
||||
.de Vb
|
||||
.ft CW
|
||||
|
@ -10,7 +10,7 @@
|
|||
|
||||
.fi
|
||||
..
|
||||
.TH "LIBUNWIND" "3" "16 August 2007" "Programming Library " "Programming Library "
|
||||
.TH "LIBUNWIND" "3" "12 January 2017" "Programming Library " "Programming Library "
|
||||
.SH NAME
|
||||
libunwind
|
||||
\-\- a (mostly) platform\-independent unwind API
|
||||
|
@ -82,6 +82,11 @@ int
|
|||
unw_set_caching_policy(unw_addr_space_t,
|
||||
unw_caching_policy_t);
|
||||
.br
|
||||
int
|
||||
unw_set_cache_size(unw_addr_space_t,
|
||||
size_t,
|
||||
int);
|
||||
.br
|
||||
.PP
|
||||
const char *unw_regname(unw_regnum_t);
|
||||
.br
|
||||
|
@ -428,7 +433,9 @@ UNW_CACHE_NONE,
|
|||
it is possible to turn off caching
|
||||
completely, therefore eliminating the risk of stale data alltogether
|
||||
(at the cost of slower execution). By default, caching is enabled for
|
||||
local unwinding only.
|
||||
local unwinding only. The cache size can be dynamically changed with
|
||||
unw_set_cache_size(),
|
||||
which also fluches the current cache.
|
||||
.PP
|
||||
.SH FILES
|
||||
|
||||
|
@ -482,6 +489,7 @@ unw_is_signal_frame(3),
|
|||
unw_regname(3),
|
||||
unw_resume(3),
|
||||
unw_set_caching_policy(3),
|
||||
unw_set_cache_size(3),
|
||||
unw_set_fpreg(3),
|
||||
unw_set_reg(3),
|
||||
unw_step(3),
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
\Type{void} \Func{unw\_flush\_cache}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_word\_t});\\
|
||||
\noindent
|
||||
\Type{int} \Func{unw\_set\_caching\_policy}(\Type{unw\_addr\_space\_t}, \Type{unw\_caching\_policy\_t});\\
|
||||
\noindent
|
||||
\Type{int} \Func{unw\_set\_cache\_size}(\Type{unw\_addr\_space\_t}, \Type{size\_t}, \Type{int});\\
|
||||
|
||||
\noindent
|
||||
\Type{const char *}\Func{unw\_regname}(\Type{unw\_regnum\_t});\\
|
||||
|
@ -293,7 +295,8 @@ object. In particular, by selecting the policy
|
|||
\Const{UNW\_CACHE\_NONE}, it is possible to turn off caching
|
||||
completely, therefore eliminating the risk of stale data alltogether
|
||||
(at the cost of slower execution). By default, caching is enabled for
|
||||
local unwinding only.
|
||||
local unwinding only. The cache size can be dynamically changed with
|
||||
\Func{unw\_set\_cache\_size}(), which also fluches the current cache.
|
||||
|
||||
|
||||
\section{Files}
|
||||
|
@ -337,6 +340,7 @@ local unwinding only.
|
|||
\SeeAlso{unw\_regname(3)},
|
||||
\SeeAlso{unw\_resume(3)},
|
||||
\SeeAlso{unw\_set\_caching\_policy(3)},
|
||||
\SeeAlso{unw\_set\_cache\_size(3)},
|
||||
\SeeAlso{unw\_set\_fpreg(3)},
|
||||
\SeeAlso{unw\_set\_reg(3)},
|
||||
\SeeAlso{unw\_step(3)},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
'\" t
|
||||
.\" Manual page created with latex2man on Thu Aug 16 09:44:44 MDT 2007
|
||||
.\" Manual page created with latex2man on Fri Dec 2 16:09:33 PST 2016
|
||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
||||
.de Vb
|
||||
.ft CW
|
||||
|
@ -10,7 +10,7 @@
|
|||
|
||||
.fi
|
||||
..
|
||||
.TH "UNW\\_FLUSH\\_CACHE" "3" "16 August 2007" "Programming Library " "Programming Library "
|
||||
.TH "UNW\\_FLUSH\\_CACHE" "3" "02 December 2016" "Programming Library " "Programming Library "
|
||||
.SH NAME
|
||||
unw_flush_cache
|
||||
\-\- flush cached info
|
||||
|
@ -80,6 +80,7 @@ use from a signal handler.
|
|||
.PP
|
||||
libunwind(3),
|
||||
unw_set_caching_policy(3)
|
||||
unw_set_cache_size(3)
|
||||
.PP
|
||||
.SH AUTHOR
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ use from a signal handler.
|
|||
|
||||
\SeeAlso{libunwind(3)},
|
||||
\SeeAlso{unw\_set\_caching\_policy(3)}
|
||||
\SeeAlso{unw\_set\_cache\_size(3)}
|
||||
|
||||
\section{Author}
|
||||
|
||||
|
|
88
doc/unw_set_cache_size.man
Normal file
88
doc/unw_set_cache_size.man
Normal file
|
@ -0,0 +1,88 @@
|
|||
'\" t
|
||||
.\" Manual page created with latex2man on Fri Jan 13 08:33:21 PST 2017
|
||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
||||
.de Vb
|
||||
.ft CW
|
||||
.nf
|
||||
..
|
||||
.de Ve
|
||||
.ft R
|
||||
|
||||
.fi
|
||||
..
|
||||
.TH "UNW\\_SET\\_CACHE\\_SIZE" "3" "13 January 2017" "Programming Library " "Programming Library "
|
||||
.SH NAME
|
||||
unw_set_cache_size
|
||||
\-\- set unwind cache size
|
||||
.PP
|
||||
.SH SYNOPSIS
|
||||
|
||||
.PP
|
||||
#include <libunwind.h>
|
||||
.br
|
||||
.PP
|
||||
int
|
||||
unw_set_cache_size(unw_addr_space_t
|
||||
as,
|
||||
size_t
|
||||
size,
|
||||
int
|
||||
flag);
|
||||
.br
|
||||
.PP
|
||||
.SH DESCRIPTION
|
||||
|
||||
.PP
|
||||
The unw_set_cache_size()
|
||||
routine sets the cache size of
|
||||
address space as
|
||||
to hold at least as many items as given by
|
||||
argument size\&.
|
||||
It may hold more items as determined by the
|
||||
implementation. To disable caching, call
|
||||
unw_set_caching_policy)
|
||||
with a policy of
|
||||
UNW_CACHE_NONE\&.
|
||||
Flag is currently unused and must be 0.
|
||||
.PP
|
||||
.SH RETURN VALUE
|
||||
|
||||
.PP
|
||||
On successful completion, unw_set_cache_size()
|
||||
returns 0.
|
||||
Otherwise the negative value of one of the error\-codes below is
|
||||
returned.
|
||||
.PP
|
||||
.SH THREAD AND SIGNAL SAFETY
|
||||
|
||||
.PP
|
||||
unw_set_cache_size()
|
||||
is thread\-safe but \fInot\fP
|
||||
safe
|
||||
to use from a signal handler.
|
||||
.PP
|
||||
.SH ERRORS
|
||||
|
||||
.PP
|
||||
.TP
|
||||
UNW_ENOMEM
|
||||
The desired cache size could not be
|
||||
established because the application is out of memory.
|
||||
.PP
|
||||
.SH SEE ALSO
|
||||
|
||||
.PP
|
||||
libunwind(3),
|
||||
unw_create_addr_space(3),
|
||||
unw_set_caching_policy(3),
|
||||
unw_flush_cache(3)
|
||||
.PP
|
||||
.SH AUTHOR
|
||||
|
||||
.PP
|
||||
Dave Watson
|
||||
.br
|
||||
Email: \fBdade.watson@gmail.com\fP
|
||||
.br
|
||||
WWW: \fBhttp://www.nongnu.org/libunwind/\fP\&.
|
||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
59
doc/unw_set_cache_size.tex
Normal file
59
doc/unw_set_cache_size.tex
Normal file
|
@ -0,0 +1,59 @@
|
|||
\documentclass{article}
|
||||
\usepackage[fancyhdr,pdf]{latex2man}
|
||||
|
||||
\input{common.tex}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{Name}{3}{unw\_set\_cache\_size}{Dave Watson}{Programming Library}{unw\_set\_cache\_size}unw\_set\_cache\_size -- set unwind cache size
|
||||
\end{Name}
|
||||
|
||||
\section{Synopsis}
|
||||
|
||||
\File{\#include $<$libunwind.h$>$}\\
|
||||
|
||||
\Type{int} \Func{unw\_set\_cache\_size}(\Type{unw\_addr\_space\_t} \Var{as}, \Type{size\_t} \Var{size}, \Type{int} \Var{flag});\\
|
||||
|
||||
\section{Description}
|
||||
|
||||
The \Func{unw\_set\_cache\_size}() routine sets the cache size of
|
||||
address space \Var{as} to hold at least as many items as given by
|
||||
argument \Var{size}. It may hold more items as determined by the
|
||||
implementation. To disable caching, call
|
||||
\Func{unw\_set\_caching\_policy}) with a policy of
|
||||
\Const{UNW\_CACHE\_NONE}. Flag is currently unused and must be 0.
|
||||
|
||||
\section{Return Value}
|
||||
|
||||
On successful completion, \Func{unw\_set\_cache\_size}() returns 0.
|
||||
Otherwise the negative value of one of the error-codes below is
|
||||
returned.
|
||||
|
||||
\section{Thread and Signal Safety}
|
||||
|
||||
\Func{unw\_set\_cache\_size}() is thread-safe but \emph{not} safe
|
||||
to use from a signal handler.
|
||||
|
||||
\section{Errors}
|
||||
|
||||
\begin{Description}
|
||||
\item[\Const{UNW\_ENOMEM}] The desired cache size could not be
|
||||
established because the application is out of memory.
|
||||
\end{Description}
|
||||
|
||||
\section{See Also}
|
||||
|
||||
\SeeAlso{libunwind(3)},
|
||||
\SeeAlso{unw\_create\_addr\_space(3)},
|
||||
\SeeAlso{unw\_set\_caching\_policy(3)},
|
||||
\SeeAlso{unw\_flush\_cache(3)}
|
||||
|
||||
\section{Author}
|
||||
|
||||
\noindent
|
||||
Dave Watson\\
|
||||
Email: \Email{dade.watson@gmail.com}\\
|
||||
WWW: \URL{http://www.nongnu.org/libunwind/}.
|
||||
\LatexManEnd
|
||||
|
||||
\end{document}
|
|
@ -1,5 +1,5 @@
|
|||
'\" t
|
||||
.\" Manual page created with latex2man on Thu Aug 16 09:44:45 MDT 2007
|
||||
.\" Manual page created with latex2man on Fri Dec 2 16:09:33 PST 2016
|
||||
.\" NOTE: This file is generated, DO NOT EDIT.
|
||||
.de Vb
|
||||
.ft CW
|
||||
|
@ -10,7 +10,7 @@
|
|||
|
||||
.fi
|
||||
..
|
||||
.TH "UNW\\_SET\\_CACHING\\_POLICY" "3" "16 August 2007" "Programming Library " "Programming Library "
|
||||
.TH "UNW\\_SET\\_CACHING\\_POLICY" "3" "02 December 2016" "Programming Library " "Programming Library "
|
||||
.SH NAME
|
||||
unw_set_caching_policy
|
||||
\-\- set unwind caching policy
|
||||
|
@ -105,6 +105,7 @@ established because the application is out of memory.
|
|||
.PP
|
||||
libunwind(3),
|
||||
unw_create_addr_space(3),
|
||||
unw_set_cache_size(3),
|
||||
unw_flush_cache(3)
|
||||
.PP
|
||||
.SH AUTHOR
|
||||
|
|
|
@ -67,6 +67,7 @@ to use from a signal handler.
|
|||
|
||||
\SeeAlso{libunwind(3)},
|
||||
\SeeAlso{unw\_create\_addr\_space(3)},
|
||||
\SeeAlso{unw\_set\_cache\_size(3)},
|
||||
\SeeAlso{unw\_flush\_cache(3)}
|
||||
|
||||
\section{Author}
|
||||
|
|
|
@ -325,11 +325,11 @@ typedef struct dwarf_cursor
|
|||
}
|
||||
dwarf_cursor_t;
|
||||
|
||||
#define DWARF_LOG_UNW_CACHE_SIZE 7
|
||||
#define DWARF_UNW_CACHE_SIZE (1 << DWARF_LOG_UNW_CACHE_SIZE)
|
||||
#define DWARF_DEFAULT_LOG_UNW_CACHE_SIZE 7
|
||||
#define DWARF_DEFAULT_UNW_CACHE_SIZE (1 << DWARF_DEFAULT_LOG_UNW_CACHE_SIZE)
|
||||
|
||||
#define DWARF_LOG_UNW_HASH_SIZE (DWARF_LOG_UNW_CACHE_SIZE + 1)
|
||||
#define DWARF_UNW_HASH_SIZE (1 << DWARF_LOG_UNW_HASH_SIZE)
|
||||
#define DWARF_DEFAULT_LOG_UNW_HASH_SIZE (DWARF_DEFAULT_LOG_UNW_CACHE_SIZE + 1)
|
||||
#define DWARF_DEFAULT_UNW_HASH_SIZE (1 << DWARF_DEFAULT_LOG_UNW_HASH_SIZE)
|
||||
|
||||
typedef unsigned char unw_hash_index_t;
|
||||
|
||||
|
@ -339,13 +339,20 @@ struct dwarf_rs_cache
|
|||
unsigned short lru_head; /* index of lead-recently used rs */
|
||||
unsigned short lru_tail; /* index of most-recently used rs */
|
||||
|
||||
unsigned short log_size;
|
||||
unsigned short prev_log_size;
|
||||
|
||||
/* hash table that maps instruction pointer to rs index: */
|
||||
unsigned short hash[DWARF_UNW_HASH_SIZE];
|
||||
unsigned short *hash;
|
||||
|
||||
uint32_t generation; /* generation number */
|
||||
|
||||
/* rs cache: */
|
||||
dwarf_reg_state_t buckets[DWARF_UNW_CACHE_SIZE];
|
||||
dwarf_reg_state_t *buckets;
|
||||
|
||||
/* default memory, loaded in BSS segment */
|
||||
unsigned short default_hash[DWARF_DEFAULT_UNW_HASH_SIZE];
|
||||
dwarf_reg_state_t default_buckets[DWARF_DEFAULT_UNW_CACHE_SIZE];
|
||||
};
|
||||
|
||||
/* A list of descriptors for loaded .debug_frame sections. */
|
||||
|
@ -395,6 +402,7 @@ struct dwarf_callback_data
|
|||
#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info)
|
||||
#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
|
||||
#define dwarf_step UNW_OBJ (dwarf_step)
|
||||
#define dwarf_flush_rs_cache UNW_OBJ (dwarf_flush_rs_cache)
|
||||
|
||||
extern int dwarf_init (void);
|
||||
#ifndef UNW_REMOTE_ONLY
|
||||
|
@ -443,5 +451,6 @@ extern int dwarf_read_encoded_pointer (unw_addr_space_t as,
|
|||
const unw_proc_info_t *pi,
|
||||
unw_word_t *valp, void *arg);
|
||||
extern int dwarf_step (struct dwarf_cursor *c);
|
||||
extern int dwarf_flush_rs_cache (struct dwarf_rs_cache *cache);
|
||||
|
||||
#endif /* dwarf_h */
|
||||
|
|
|
@ -225,6 +225,7 @@ unw_save_loc_t;
|
|||
#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame)
|
||||
#define unw_get_proc_name UNW_OBJ(get_proc_name)
|
||||
#define unw_set_caching_policy UNW_OBJ(set_caching_policy)
|
||||
#define unw_set_cache_size UNW_OBJ(set_cache_size)
|
||||
#define unw_regname UNW_ARCH_OBJ(regname)
|
||||
#define unw_flush_cache UNW_ARCH_OBJ(flush_cache)
|
||||
#define unw_strerror UNW_ARCH_OBJ(strerror)
|
||||
|
@ -234,6 +235,7 @@ extern void unw_destroy_addr_space (unw_addr_space_t);
|
|||
extern unw_accessors_t *unw_get_accessors (unw_addr_space_t);
|
||||
extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t);
|
||||
extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t);
|
||||
extern int unw_set_cache_size (unw_addr_space_t, size_t, int);
|
||||
extern const char *unw_regname (unw_regnum_t);
|
||||
|
||||
extern int unw_init_local (unw_cursor_t *, unw_context_t *);
|
||||
|
|
|
@ -109,7 +109,8 @@ libunwind_la_SOURCES_generic = \
|
|||
mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \
|
||||
mi/Gget_reg.c mi/Gset_reg.c \
|
||||
mi/Gget_fpreg.c mi/Gset_fpreg.c \
|
||||
mi/Gset_caching_policy.c
|
||||
mi/Gset_caching_policy.c \
|
||||
mi/Gset_cache_size.c
|
||||
|
||||
if SUPPORT_CXX_EXCEPTIONS
|
||||
libunwind_la_SOURCES_local_unwind = \
|
||||
|
@ -137,7 +138,8 @@ libunwind_la_SOURCES_local_nounwind = \
|
|||
mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c \
|
||||
mi/Lget_reg.c mi/Lset_reg.c \
|
||||
mi/Lget_fpreg.c mi/Lset_fpreg.c \
|
||||
mi/Lset_caching_policy.c
|
||||
mi/Lset_caching_policy.c \
|
||||
mi/Lset_cache_size.c
|
||||
|
||||
libunwind_la_SOURCES_local = \
|
||||
$(libunwind_la_SOURCES_local_nounwind) \
|
||||
|
|
|
@ -23,13 +23,17 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include "dwarf_i.h"
|
||||
#include "libunwind_i.h"
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool))
|
||||
#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs))
|
||||
|
||||
#define DWARF_UNW_CACHE_SIZE(log_size) (1 << log_size)
|
||||
#define DWARF_UNW_HASH_SIZE(log_size) (1 << (log_size + 1))
|
||||
|
||||
static inline int
|
||||
read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
|
||||
unw_word_t *valp, void *arg)
|
||||
|
@ -508,15 +512,37 @@ parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
flush_rs_cache (struct dwarf_rs_cache *cache)
|
||||
HIDDEN int
|
||||
dwarf_flush_rs_cache (struct dwarf_rs_cache *cache)
|
||||
{
|
||||
int i;
|
||||
|
||||
cache->lru_head = DWARF_UNW_CACHE_SIZE - 1;
|
||||
if (cache->log_size == DWARF_DEFAULT_LOG_UNW_CACHE_SIZE
|
||||
|| !cache->hash) {
|
||||
cache->hash = cache->default_hash;
|
||||
cache->buckets = cache->default_buckets;
|
||||
cache->log_size = DWARF_DEFAULT_LOG_UNW_CACHE_SIZE;
|
||||
} else {
|
||||
if (cache->hash && cache->hash != cache->default_hash)
|
||||
munmap(cache->hash, DWARF_UNW_HASH_SIZE(cache->prev_log_size));
|
||||
if (cache->buckets && cache->buckets != cache->default_buckets)
|
||||
munmap(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->prev_log_size));
|
||||
GET_MEMORY(cache->hash, DWARF_UNW_HASH_SIZE(cache->log_size)
|
||||
* sizeof (cache->hash[0]));
|
||||
GET_MEMORY(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->log_size)
|
||||
* sizeof (cache->buckets[0]));
|
||||
if (!cache->hash || !cache->buckets)
|
||||
{
|
||||
Debug (1, "Unable to allocate cache memory");
|
||||
return -UNW_ENOMEM;
|
||||
}
|
||||
cache->prev_log_size = cache->log_size;
|
||||
}
|
||||
|
||||
cache->lru_head = DWARF_UNW_CACHE_SIZE(cache->log_size) - 1;
|
||||
cache->lru_tail = 0;
|
||||
|
||||
for (i = 0; i < DWARF_UNW_CACHE_SIZE; ++i)
|
||||
for (i = 0; i < DWARF_UNW_CACHE_SIZE(cache->log_size); ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
cache->buckets[i].lru_chain = (i - 1);
|
||||
|
@ -524,8 +550,10 @@ flush_rs_cache (struct dwarf_rs_cache *cache)
|
|||
cache->buckets[i].ip = 0;
|
||||
cache->buckets[i].valid = 0;
|
||||
}
|
||||
for (i = 0; i<DWARF_UNW_HASH_SIZE; ++i)
|
||||
for (i = 0; i< DWARF_UNW_HASH_SIZE(cache->log_size); ++i)
|
||||
cache->hash[i] = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct dwarf_rs_cache *
|
||||
|
@ -543,9 +571,11 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
|
|||
lock_acquire (&cache->lock, *saved_maskp);
|
||||
}
|
||||
|
||||
if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
|
||||
if ((atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
|
||||
|| !cache->hash)
|
||||
{
|
||||
flush_rs_cache (cache);
|
||||
if (dwarf_flush_rs_cache (cache) < 0)
|
||||
return NULL;
|
||||
cache->generation = as->cache_generation;
|
||||
}
|
||||
|
||||
|
@ -564,12 +594,12 @@ put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache,
|
|||
}
|
||||
|
||||
static inline unw_hash_index_t CONST_ATTR
|
||||
hash (unw_word_t ip)
|
||||
hash (unw_word_t ip, unsigned short log_size)
|
||||
{
|
||||
/* based on (sqrt(5)/2-1)*2^64 */
|
||||
# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL)
|
||||
|
||||
return ip * magic >> ((sizeof(unw_word_t) * 8) - DWARF_LOG_UNW_HASH_SIZE);
|
||||
return ip * magic >> ((sizeof(unw_word_t) * 8) - (log_size + 1));
|
||||
}
|
||||
|
||||
static inline long
|
||||
|
@ -592,8 +622,8 @@ rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
|
|||
if (cache_match (rs, ip))
|
||||
return rs;
|
||||
|
||||
index = cache->hash[hash (ip)];
|
||||
if (index >= DWARF_UNW_CACHE_SIZE)
|
||||
index = cache->hash[hash (ip, cache->log_size)];
|
||||
if (index >= DWARF_UNW_CACHE_SIZE(cache->log_size))
|
||||
return NULL;
|
||||
|
||||
rs = cache->buckets + index;
|
||||
|
@ -606,7 +636,7 @@ rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
|
|||
(rs - cache->buckets);
|
||||
return rs;
|
||||
}
|
||||
if (rs->coll_chain >= DWARF_UNW_HASH_SIZE)
|
||||
if (rs->coll_chain >= DWARF_UNW_HASH_SIZE(cache->log_size))
|
||||
return NULL;
|
||||
rs = cache->buckets + rs->coll_chain;
|
||||
}
|
||||
|
@ -630,7 +660,7 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
|
|||
/* remove the old rs from the hash table (if it's there): */
|
||||
if (rs->ip)
|
||||
{
|
||||
index = hash (rs->ip);
|
||||
index = hash (rs->ip, cache->log_size);
|
||||
tmp = cache->buckets + cache->hash[index];
|
||||
prev = NULL;
|
||||
while (1)
|
||||
|
@ -645,7 +675,7 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
|
|||
}
|
||||
else
|
||||
prev = tmp;
|
||||
if (tmp->coll_chain >= DWARF_UNW_CACHE_SIZE)
|
||||
if (tmp->coll_chain >= DWARF_UNW_CACHE_SIZE(cache->log_size))
|
||||
/* old rs wasn't in the hash-table */
|
||||
break;
|
||||
tmp = cache->buckets + tmp->coll_chain;
|
||||
|
@ -653,7 +683,7 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
|
|||
}
|
||||
|
||||
/* enter new rs in the hash table */
|
||||
index = hash (c->ip);
|
||||
index = hash (c->ip, cache->log_size);
|
||||
rs->coll_chain = cache->hash[index];
|
||||
cache->hash[index] = rs - cache->buckets;
|
||||
|
||||
|
|
64
src/mi/Gset_cache_size.c
Normal file
64
src/mi/Gset_cache_size.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2014
|
||||
Contributed by Milian Wolff <address@hidden>
|
||||
and Dave Watson <dade.watson@gmail.com>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
#include "libunwind_i.h"
|
||||
|
||||
PROTECTED int
|
||||
unw_set_cache_size (unw_addr_space_t as, size_t size, int flag)
|
||||
{
|
||||
size_t power = 1;
|
||||
unsigned short log_size = 0;
|
||||
|
||||
if (!tdep_init_done)
|
||||
tdep_init ();
|
||||
|
||||
if (flag != 0)
|
||||
return -1;
|
||||
|
||||
/* Round up to next power of two, slowly but portably */
|
||||
while(power < size)
|
||||
{
|
||||
power *= 2;
|
||||
log_size++;
|
||||
/* Largest size currently supported by rs_cache */
|
||||
if (log_size >= 15)
|
||||
break;
|
||||
}
|
||||
|
||||
if (log_size == as->global_cache.log_size)
|
||||
return 0; /* no change */
|
||||
|
||||
as->global_cache.log_size = log_size;
|
||||
|
||||
/* Ensure caches are empty (and initialized). */
|
||||
unw_flush_cache (as, 0, 0);
|
||||
#ifdef __ia64__
|
||||
return 0;
|
||||
#else
|
||||
/* Synchronously purge cache, to ensure memory is allocated */
|
||||
return dwarf_flush_rs_cache(&as->global_cache);
|
||||
#endif
|
||||
}
|
5
src/mi/Lset_cache_size.c
Normal file
5
src/mi/Lset_cache_size.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY)
|
||||
#include "Gset_cache_size.c"
|
||||
#endif
|
|
@ -103,6 +103,7 @@ check_local_unw_abi () {
|
|||
match _UL${plat}_local_addr_space
|
||||
match _UL${plat}_resume
|
||||
match _UL${plat}_set_caching_policy
|
||||
match _UL${plat}_set_cache_size
|
||||
match _UL${plat}_set_reg
|
||||
match _UL${plat}_set_fpreg
|
||||
match _UL${plat}_step
|
||||
|
@ -199,6 +200,7 @@ check_generic_unw_abi () {
|
|||
match _U${plat}_regname
|
||||
match _U${plat}_resume
|
||||
match _U${plat}_set_caching_policy
|
||||
match _U${plat}_set_cache_size
|
||||
match _U${plat}_set_fpreg
|
||||
match _U${plat}_set_reg
|
||||
match _U${plat}_step
|
||||
|
|
|
@ -46,6 +46,7 @@ f257 (void)
|
|||
for (i = 0; i < n; ++i)
|
||||
printf ("[%d] ip=%p\n", i, buffer[i]);
|
||||
|
||||
unw_set_cache_size (unw_local_addr_space, 1023, 0);
|
||||
unw_flush_cache (unw_local_addr_space, 0, 0);
|
||||
|
||||
if (verbose)
|
||||
|
|
|
@ -43,6 +43,7 @@ static void *funcs[] =
|
|||
(void *) &unw_get_accessors,
|
||||
(void *) &unw_flush_cache,
|
||||
(void *) &unw_set_caching_policy,
|
||||
(void *) &unw_set_cache_size,
|
||||
(void *) &unw_regname,
|
||||
(void *) &unw_get_proc_info,
|
||||
(void *) &unw_get_save_loc,
|
||||
|
|
|
@ -61,6 +61,7 @@ static void *funcs[] =
|
|||
(void *) &unw_get_accessors,
|
||||
(void *) &unw_flush_cache,
|
||||
(void *) &unw_set_caching_policy,
|
||||
(void *) &unw_set_cache_size,
|
||||
(void *) &unw_regname,
|
||||
(void *) &unw_get_proc_info,
|
||||
(void *) &unw_get_save_loc,
|
||||
|
|
Loading…
Reference in a new issue