1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-22 07:37: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:
Dave Watson 2016-12-05 15:39:37 -08:00
parent 29483327be
commit a51cf49031
19 changed files with 314 additions and 32 deletions

View file

@ -17,6 +17,7 @@ man3_MANS = libunwind.man libunwind-dynamic.man libunwind-ia64.man \
unw_destroy_addr_space.man \ unw_destroy_addr_space.man \
unw_regname.man unw_resume.man \ unw_regname.man unw_resume.man \
unw_set_caching_policy.man \ unw_set_caching_policy.man \
unw_set_cache_size.man \
unw_set_fpreg.man \ unw_set_fpreg.man \
unw_set_reg.man \ unw_set_reg.man \
unw_step.man \ unw_step.man \
@ -41,6 +42,7 @@ EXTRA_DIST = NOTES libunwind.trans \
unw_is_signal_frame.tex \ unw_is_signal_frame.tex \
unw_create_addr_space.tex unw_destroy_addr_space.tex \ unw_create_addr_space.tex unw_destroy_addr_space.tex \
unw_regname.tex unw_resume.tex unw_set_caching_policy.tex \ unw_regname.tex unw_resume.tex unw_set_caching_policy.tex \
unw_set_cache_size.tex \
unw_set_fpreg.tex \ unw_set_fpreg.tex \
unw_set_reg.tex \ unw_set_reg.tex \
unw_step.tex \ unw_step.tex \

View file

@ -1,5 +1,5 @@
'\" t '\" 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. .\" NOTE: This file is generated, DO NOT EDIT.
.de Vb .de Vb
.ft CW .ft CW
@ -10,7 +10,7 @@
.fi .fi
.. ..
.TH "LIBUNWIND" "3" "16 August 2007" "Programming Library " "Programming Library " .TH "LIBUNWIND" "3" "12 January 2017" "Programming Library " "Programming Library "
.SH NAME .SH NAME
libunwind libunwind
\-\- a (mostly) platform\-independent unwind API \-\- a (mostly) platform\-independent unwind API
@ -82,6 +82,11 @@ int
unw_set_caching_policy(unw_addr_space_t, unw_set_caching_policy(unw_addr_space_t,
unw_caching_policy_t); unw_caching_policy_t);
.br .br
int
unw_set_cache_size(unw_addr_space_t,
size_t,
int);
.br
.PP .PP
const char *unw_regname(unw_regnum_t); const char *unw_regname(unw_regnum_t);
.br .br
@ -428,7 +433,9 @@ UNW_CACHE_NONE,
it is possible to turn off caching it is possible to turn off caching
completely, therefore eliminating the risk of stale data alltogether completely, therefore eliminating the risk of stale data alltogether
(at the cost of slower execution). By default, caching is enabled for (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 .PP
.SH FILES .SH FILES
@ -482,6 +489,7 @@ unw_is_signal_frame(3),
unw_regname(3), unw_regname(3),
unw_resume(3), unw_resume(3),
unw_set_caching_policy(3), unw_set_caching_policy(3),
unw_set_cache_size(3),
unw_set_fpreg(3), unw_set_fpreg(3),
unw_set_reg(3), unw_set_reg(3),
unw_step(3), unw_step(3),

View file

@ -43,6 +43,8 @@
\Type{void} \Func{unw\_flush\_cache}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_word\_t});\\ \Type{void} \Func{unw\_flush\_cache}(\Type{unw\_addr\_space\_t}, \Type{unw\_word\_t}, \Type{unw\_word\_t});\\
\noindent \noindent
\Type{int} \Func{unw\_set\_caching\_policy}(\Type{unw\_addr\_space\_t}, \Type{unw\_caching\_policy\_t});\\ \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 \noindent
\Type{const char *}\Func{unw\_regname}(\Type{unw\_regnum\_t});\\ \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 \Const{UNW\_CACHE\_NONE}, it is possible to turn off caching
completely, therefore eliminating the risk of stale data alltogether completely, therefore eliminating the risk of stale data alltogether
(at the cost of slower execution). By default, caching is enabled for (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} \section{Files}
@ -337,6 +340,7 @@ local unwinding only.
\SeeAlso{unw\_regname(3)}, \SeeAlso{unw\_regname(3)},
\SeeAlso{unw\_resume(3)}, \SeeAlso{unw\_resume(3)},
\SeeAlso{unw\_set\_caching\_policy(3)}, \SeeAlso{unw\_set\_caching\_policy(3)},
\SeeAlso{unw\_set\_cache\_size(3)},
\SeeAlso{unw\_set\_fpreg(3)}, \SeeAlso{unw\_set\_fpreg(3)},
\SeeAlso{unw\_set\_reg(3)}, \SeeAlso{unw\_set\_reg(3)},
\SeeAlso{unw\_step(3)}, \SeeAlso{unw\_step(3)},

View file

@ -1,5 +1,5 @@
'\" t '\" 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. .\" NOTE: This file is generated, DO NOT EDIT.
.de Vb .de Vb
.ft CW .ft CW
@ -10,7 +10,7 @@
.fi .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 .SH NAME
unw_flush_cache unw_flush_cache
\-\- flush cached info \-\- flush cached info
@ -80,6 +80,7 @@ use from a signal handler.
.PP .PP
libunwind(3), libunwind(3),
unw_set_caching_policy(3) unw_set_caching_policy(3)
unw_set_cache_size(3)
.PP .PP
.SH AUTHOR .SH AUTHOR

View file

@ -45,6 +45,7 @@ use from a signal handler.
\SeeAlso{libunwind(3)}, \SeeAlso{libunwind(3)},
\SeeAlso{unw\_set\_caching\_policy(3)} \SeeAlso{unw\_set\_caching\_policy(3)}
\SeeAlso{unw\_set\_cache\_size(3)}
\section{Author} \section{Author}

View 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.

View 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}

View file

@ -1,5 +1,5 @@
'\" t '\" 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. .\" NOTE: This file is generated, DO NOT EDIT.
.de Vb .de Vb
.ft CW .ft CW
@ -10,7 +10,7 @@
.fi .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 .SH NAME
unw_set_caching_policy unw_set_caching_policy
\-\- set unwind caching policy \-\- set unwind caching policy
@ -105,6 +105,7 @@ established because the application is out of memory.
.PP .PP
libunwind(3), libunwind(3),
unw_create_addr_space(3), unw_create_addr_space(3),
unw_set_cache_size(3),
unw_flush_cache(3) unw_flush_cache(3)
.PP .PP
.SH AUTHOR .SH AUTHOR

View file

@ -67,6 +67,7 @@ to use from a signal handler.
\SeeAlso{libunwind(3)}, \SeeAlso{libunwind(3)},
\SeeAlso{unw\_create\_addr\_space(3)}, \SeeAlso{unw\_create\_addr\_space(3)},
\SeeAlso{unw\_set\_cache\_size(3)},
\SeeAlso{unw\_flush\_cache(3)} \SeeAlso{unw\_flush\_cache(3)}
\section{Author} \section{Author}

View file

@ -325,11 +325,11 @@ typedef struct dwarf_cursor
} }
dwarf_cursor_t; dwarf_cursor_t;
#define DWARF_LOG_UNW_CACHE_SIZE 7 #define DWARF_DEFAULT_LOG_UNW_CACHE_SIZE 7
#define DWARF_UNW_CACHE_SIZE (1 << DWARF_LOG_UNW_CACHE_SIZE) #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_DEFAULT_LOG_UNW_HASH_SIZE (DWARF_DEFAULT_LOG_UNW_CACHE_SIZE + 1)
#define DWARF_UNW_HASH_SIZE (1 << DWARF_LOG_UNW_HASH_SIZE) #define DWARF_DEFAULT_UNW_HASH_SIZE (1 << DWARF_DEFAULT_LOG_UNW_HASH_SIZE)
typedef unsigned char unw_hash_index_t; 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_head; /* index of lead-recently used rs */
unsigned short lru_tail; /* index of most-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: */ /* hash table that maps instruction pointer to rs index: */
unsigned short hash[DWARF_UNW_HASH_SIZE]; unsigned short *hash;
uint32_t generation; /* generation number */ uint32_t generation; /* generation number */
/* rs cache: */ /* 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. */ /* 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_make_proc_info UNW_OBJ (dwarf_make_proc_info)
#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer) #define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer)
#define dwarf_step UNW_OBJ (dwarf_step) #define dwarf_step UNW_OBJ (dwarf_step)
#define dwarf_flush_rs_cache UNW_OBJ (dwarf_flush_rs_cache)
extern int dwarf_init (void); extern int dwarf_init (void);
#ifndef UNW_REMOTE_ONLY #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, const unw_proc_info_t *pi,
unw_word_t *valp, void *arg); unw_word_t *valp, void *arg);
extern int dwarf_step (struct dwarf_cursor *c); extern int dwarf_step (struct dwarf_cursor *c);
extern int dwarf_flush_rs_cache (struct dwarf_rs_cache *cache);
#endif /* dwarf_h */ #endif /* dwarf_h */

View file

@ -225,6 +225,7 @@ unw_save_loc_t;
#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame) #define unw_handle_signal_frame UNW_OBJ(handle_signal_frame)
#define unw_get_proc_name UNW_OBJ(get_proc_name) #define unw_get_proc_name UNW_OBJ(get_proc_name)
#define unw_set_caching_policy UNW_OBJ(set_caching_policy) #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_regname UNW_ARCH_OBJ(regname)
#define unw_flush_cache UNW_ARCH_OBJ(flush_cache) #define unw_flush_cache UNW_ARCH_OBJ(flush_cache)
#define unw_strerror UNW_ARCH_OBJ(strerror) #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 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 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_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 const char *unw_regname (unw_regnum_t);
extern int unw_init_local (unw_cursor_t *, unw_context_t *); extern int unw_init_local (unw_cursor_t *, unw_context_t *);

View file

@ -109,7 +109,8 @@ libunwind_la_SOURCES_generic = \
mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \ mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \
mi/Gget_reg.c mi/Gset_reg.c \ mi/Gget_reg.c mi/Gset_reg.c \
mi/Gget_fpreg.c mi/Gset_fpreg.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 if SUPPORT_CXX_EXCEPTIONS
libunwind_la_SOURCES_local_unwind = \ 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/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c \
mi/Lget_reg.c mi/Lset_reg.c \ mi/Lget_reg.c mi/Lset_reg.c \
mi/Lget_fpreg.c mi/Lset_fpreg.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 = \
$(libunwind_la_SOURCES_local_nounwind) \ $(libunwind_la_SOURCES_local_nounwind) \

View file

@ -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 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <stddef.h>
#include "dwarf_i.h" #include "dwarf_i.h"
#include "libunwind_i.h" #include "libunwind_i.h"
#include <stddef.h>
#include <limits.h>
#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool)) #define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool))
#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs)) #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 static inline int
read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
unw_word_t *valp, void *arg) 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; return 0;
} }
static inline void HIDDEN int
flush_rs_cache (struct dwarf_rs_cache *cache) dwarf_flush_rs_cache (struct dwarf_rs_cache *cache)
{ {
int i; 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; 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) if (i > 0)
cache->buckets[i].lru_chain = (i - 1); 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].ip = 0;
cache->buckets[i].valid = 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; cache->hash[i] = -1;
return 0;
} }
static inline struct dwarf_rs_cache * 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); 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; 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 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 */ /* based on (sqrt(5)/2-1)*2^64 */
# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL) # 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 static inline long
@ -592,8 +622,8 @@ rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
if (cache_match (rs, ip)) if (cache_match (rs, ip))
return rs; return rs;
index = cache->hash[hash (ip)]; index = cache->hash[hash (ip, cache->log_size)];
if (index >= DWARF_UNW_CACHE_SIZE) if (index >= DWARF_UNW_CACHE_SIZE(cache->log_size))
return NULL; return NULL;
rs = cache->buckets + index; rs = cache->buckets + index;
@ -606,7 +636,7 @@ rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
(rs - cache->buckets); (rs - cache->buckets);
return rs; return rs;
} }
if (rs->coll_chain >= DWARF_UNW_HASH_SIZE) if (rs->coll_chain >= DWARF_UNW_HASH_SIZE(cache->log_size))
return NULL; return NULL;
rs = cache->buckets + rs->coll_chain; 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): */ /* remove the old rs from the hash table (if it's there): */
if (rs->ip) if (rs->ip)
{ {
index = hash (rs->ip); index = hash (rs->ip, cache->log_size);
tmp = cache->buckets + cache->hash[index]; tmp = cache->buckets + cache->hash[index];
prev = NULL; prev = NULL;
while (1) while (1)
@ -645,7 +675,7 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
} }
else else
prev = tmp; 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 */ /* old rs wasn't in the hash-table */
break; break;
tmp = cache->buckets + tmp->coll_chain; 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 */ /* enter new rs in the hash table */
index = hash (c->ip); index = hash (c->ip, cache->log_size);
rs->coll_chain = cache->hash[index]; rs->coll_chain = cache->hash[index];
cache->hash[index] = rs - cache->buckets; cache->hash[index] = rs - cache->buckets;

64
src/mi/Gset_cache_size.c Normal file
View 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
View 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

View file

@ -103,6 +103,7 @@ check_local_unw_abi () {
match _UL${plat}_local_addr_space match _UL${plat}_local_addr_space
match _UL${plat}_resume match _UL${plat}_resume
match _UL${plat}_set_caching_policy match _UL${plat}_set_caching_policy
match _UL${plat}_set_cache_size
match _UL${plat}_set_reg match _UL${plat}_set_reg
match _UL${plat}_set_fpreg match _UL${plat}_set_fpreg
match _UL${plat}_step match _UL${plat}_step
@ -199,6 +200,7 @@ check_generic_unw_abi () {
match _U${plat}_regname match _U${plat}_regname
match _U${plat}_resume match _U${plat}_resume
match _U${plat}_set_caching_policy match _U${plat}_set_caching_policy
match _U${plat}_set_cache_size
match _U${plat}_set_fpreg match _U${plat}_set_fpreg
match _U${plat}_set_reg match _U${plat}_set_reg
match _U${plat}_step match _U${plat}_step

View file

@ -46,6 +46,7 @@ f257 (void)
for (i = 0; i < n; ++i) for (i = 0; i < n; ++i)
printf ("[%d] ip=%p\n", i, buffer[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); unw_flush_cache (unw_local_addr_space, 0, 0);
if (verbose) if (verbose)

View file

@ -43,6 +43,7 @@ static void *funcs[] =
(void *) &unw_get_accessors, (void *) &unw_get_accessors,
(void *) &unw_flush_cache, (void *) &unw_flush_cache,
(void *) &unw_set_caching_policy, (void *) &unw_set_caching_policy,
(void *) &unw_set_cache_size,
(void *) &unw_regname, (void *) &unw_regname,
(void *) &unw_get_proc_info, (void *) &unw_get_proc_info,
(void *) &unw_get_save_loc, (void *) &unw_get_save_loc,

View file

@ -61,6 +61,7 @@ static void *funcs[] =
(void *) &unw_get_accessors, (void *) &unw_get_accessors,
(void *) &unw_flush_cache, (void *) &unw_flush_cache,
(void *) &unw_set_caching_policy, (void *) &unw_set_caching_policy,
(void *) &unw_set_cache_size,
(void *) &unw_regname, (void *) &unw_regname,
(void *) &unw_get_proc_info, (void *) &unw_get_proc_info,
(void *) &unw_get_save_loc, (void *) &unw_get_save_loc,