Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
[pandora-kernel.git] / arch / ia64 / kernel / unwind.c
index b6c0e63..fed6afa 100644 (file)
@@ -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)  */