This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / arch / ia64 / kernel / unwind.c
index 050ae05..69e095a 100644 (file)
@@ -1269,6 +1269,7 @@ script_new (unsigned long ip)
 {
        struct unw_script *script, *prev, *tmp;
        unw_hash_index_t index;
+       unsigned long flags;
        unsigned short head;
 
        STAT(++unw.stat.script.news);
@@ -1277,9 +1278,13 @@ script_new (unsigned long ip)
         * Can't (easily) use cmpxchg() here because of ABA problem
         * that is intrinsic in cmpxchg()...
         */
-       head = unw.lru_head;
-       script = unw.cache + head;
-       unw.lru_head = script->lru_chain;
+       spin_lock_irqsave(&unw.lock, flags);
+       {
+               head = unw.lru_head;
+               script = unw.cache + head;
+               unw.lru_head = script->lru_chain;
+       }
+       spin_unlock(&unw.lock);
 
        /*
         * We'd deadlock here if we interrupted a thread that is holding a read lock on
@@ -1290,39 +1295,43 @@ script_new (unsigned long ip)
        if (!write_trylock(&script->lock))
                return NULL;
 
-       /* re-insert script at the tail of the LRU chain: */
-       unw.cache[unw.lru_tail].lru_chain = head;
-       unw.lru_tail = head;
-
-       /* remove the old script from the hash table (if it's there): */
-       if (script->ip) {
-               index = hash(script->ip);
-               tmp = unw.cache + unw.hash[index];
-               prev = NULL;
-               while (1) {
-                       if (tmp == script) {
-                               if (prev)
-                                       prev->coll_chain = tmp->coll_chain;
-                               else
-                                       unw.hash[index] = tmp->coll_chain;
-                               break;
-                       } else
-                               prev = tmp;
-                       if (tmp->coll_chain >= UNW_CACHE_SIZE)
-                       /* old script wasn't in the hash-table */
-                               break;
-                       tmp = unw.cache + tmp->coll_chain;
+       spin_lock(&unw.lock);
+       {
+               /* re-insert script at the tail of the LRU chain: */
+               unw.cache[unw.lru_tail].lru_chain = head;
+               unw.lru_tail = head;
+
+               /* remove the old script from the hash table (if it's there): */
+               if (script->ip) {
+                       index = hash(script->ip);
+                       tmp = unw.cache + unw.hash[index];
+                       prev = NULL;
+                       while (1) {
+                               if (tmp == script) {
+                                       if (prev)
+                                               prev->coll_chain = tmp->coll_chain;
+                                       else
+                                               unw.hash[index] = tmp->coll_chain;
+                                       break;
+                               } else
+                                       prev = tmp;
+                               if (tmp->coll_chain >= UNW_CACHE_SIZE)
+                               /* old script wasn't in the hash-table */
+                                       break;
+                               tmp = unw.cache + tmp->coll_chain;
+                       }
                }
-       }
 
-       /* enter new script in the hash table */
-       index = hash(ip);
-       script->coll_chain = unw.hash[index];
-       unw.hash[index] = script - unw.cache;
+               /* enter new script in the hash table */
+               index = hash(ip);
+               script->coll_chain = unw.hash[index];
+               unw.hash[index] = script - unw.cache;
 
-       script->ip = ip;        /* set new IP while we're holding the locks */
+               script->ip = ip;        /* set new IP while we're holding the locks */
 
-       STAT(if (script->coll_chain < UNW_CACHE_SIZE) ++unw.stat.script.collisions);
+               STAT(if (script->coll_chain < UNW_CACHE_SIZE) ++unw.stat.script.collisions);
+       }
+       spin_unlock_irqrestore(&unw.lock, flags);
 
        script->flags = 0;
        script->hint = 0;
@@ -1821,7 +1830,6 @@ find_save_locs (struct unw_frame_info *info)
 {
        int have_write_lock = 0;
        struct unw_script *scr;
-       unsigned long flags = 0;
 
        if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) {
                /* don't let obviously bad addresses pollute the cache */
@@ -1833,10 +1841,8 @@ find_save_locs (struct unw_frame_info *info)
 
        scr = script_lookup(info);
        if (!scr) {
-               spin_lock_irqsave(&unw.lock, flags);
                scr = build_script(info);
                if (!scr) {
-                       spin_unlock_irqrestore(&unw.lock, flags);
                        UNW_DPRINT(0,
                                   "unwind.%s: failed to locate/build unwind script for ip %lx\n",
                                   __FUNCTION__, info->ip);
@@ -1849,10 +1855,9 @@ find_save_locs (struct unw_frame_info *info)
 
        run_script(scr, info);
 
-       if (have_write_lock) {
+       if (have_write_lock)
                write_unlock(&scr->lock);
-               spin_unlock_irqrestore(&unw.lock, flags);
-       } else
+       else
                read_unlock(&scr->lock);
        return 0;
 }