diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 23:27:18 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 23:27:18 +0200 |
commit | b22793f7fdc38d73c4bb4299a313deef56dcfe66 (patch) | |
tree | 16cfdb64875d4e687daaa5a25440d80f719c2c1d /arch/ia64/kernel/unwind.c | |
parent | Merge git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6 (diff) | |
parent | Merge branches 'release', 'drop_do_IRQ', 'fix_early_irq', 'misc-2.6.37', 'nex... (diff) | |
download | linux-b22793f7fdc38d73c4bb4299a313deef56dcfe66.tar.xz linux-b22793f7fdc38d73c4bb4299a313deef56dcfe66.zip |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6:
[IA64] Cannot use register_percpu_irq() from ia64_mca_init()
[IA64] Initialize interrupts later (from init_IRQ())
[IA64] enable ARCH_DMA_ADDR_T_64BIT
[IA64] ioc3_serial: release resources in error return path
[IA64] Stop using the deprecated __do_IRQ() code path
[IA64] Remove unnecessary casts of private_data in perfmon.c
[IA64] Fix missing iounmap in error path in cyclone.c
[IA64] salinfo: sema_init instead of init_MUTEX
[IA64] xen: use ARRAY_SIZE macro in xen_pv_ops.c
[IA64] Use static const char * const in palinfo.c
[IA64] remove asm/compat.h
[IA64] Add CONFIG_STACKTRACE_SUPPORT
[IA64] Move local_softirq_pending() definition
[IA64] iommu: Add a dummy iommu_table.h file in IA64.
[IA64] unwind - optimise linked-list searches for modules
[IA64] unwind: remove preprocesser noise, and correct comment
Diffstat (limited to 'arch/ia64/kernel/unwind.c')
-rw-r--r-- | arch/ia64/kernel/unwind.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c index b6c0e63a0bf6..fed6afa2e8a9 100644 --- a/arch/ia64/kernel/unwind.c +++ b/arch/ia64/kernel/unwind.c @@ -1204,10 +1204,10 @@ desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word static inline unw_hash_index_t hash (unsigned long ip) { -# define hashmagic 0x9e3779b97f4a7c16UL /* based on (sqrt(5)/2-1)*2^64 */ + /* magic number = ((sqrt(5)-1)/2)*2^64 */ + static const unsigned long hashmagic = 0x9e3779b97f4a7c16UL; - return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE); -#undef hashmagic + return (ip >> 4) * hashmagic >> (64 - UNW_LOG_HASH_SIZE); } static inline long @@ -1531,7 +1531,7 @@ build_script (struct unw_frame_info *info) struct unw_labeled_state *ls, *next; unsigned long ip = info->ip; struct unw_state_record sr; - struct unw_table *table; + struct unw_table *table, *prev; struct unw_reg_info *r; struct unw_insn insn; u8 *dp, *desc_end; @@ -1560,11 +1560,26 @@ build_script (struct unw_frame_info *info) STAT(parse_start = ia64_get_itc()); + prev = NULL; for (table = unw.tables; table; table = table->next) { if (ip >= table->start && ip < table->end) { + /* + * Leave the kernel unwind table at the very front, + * lest moving it breaks some assumption elsewhere. + * Otherwise, move the matching table to the second + * position in the list so that traversals can benefit + * from commonality in backtrace paths. + */ + if (prev && prev != unw.tables) { + /* unw is safe - we're already spinlocked */ + prev->next = table->next; + table->next = unw.tables->next; + unw.tables->next = table; + } e = lookup(table, ip - table->segment_base); break; } + prev = table; } if (!e) { /* no info, return default unwinder (leaf proc, no mem stack, no saved regs) */ |