diff options
| -rw-r--r-- | arch/ia64/kernel/unwind.c | 81 |
1 files changed, 38 insertions, 43 deletions
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c index 69e095abedf6..050ae0554d5c 100644 --- a/arch/ia64/kernel/unwind.c +++ b/arch/ia64/kernel/unwind.c @@ -1269,7 +1269,6 @@ 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); @@ -1278,13 +1277,9 @@ script_new (unsigned long ip) * Can't (easily) use cmpxchg() here because of ABA problem * that is intrinsic in cmpxchg()... */ - spin_lock_irqsave(&unw.lock, flags); - { - head = unw.lru_head; - script = unw.cache + head; - unw.lru_head = script->lru_chain; - } - spin_unlock(&unw.lock); + head = unw.lru_head; + script = unw.cache + head; + unw.lru_head = script->lru_chain; /* * We'd deadlock here if we interrupted a thread that is holding a read lock on @@ -1295,43 +1290,39 @@ script_new (unsigned long ip) if (!write_trylock(&script->lock)) return NULL; - 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; - } + /* 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); - } - spin_unlock_irqrestore(&unw.lock, flags); + STAT(if (script->coll_chain < UNW_CACHE_SIZE) ++unw.stat.script.collisions); script->flags = 0; script->hint = 0; @@ -1830,6 +1821,7 @@ 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 */ @@ -1841,8 +1833,10 @@ 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); @@ -1855,9 +1849,10 @@ find_save_locs (struct unw_frame_info *info) run_script(scr, info); - if (have_write_lock) + if (have_write_lock) { write_unlock(&scr->lock); - else + spin_unlock_irqrestore(&unw.lock, flags); + } else read_unlock(&scr->lock); return 0; } |
