Comment 6 for bug 668799

Revision history for this message
Peter Maydell (pmaydell) wrote :

The following patch stops the segfault (which happens because cpu_unlink_tb() is fiddling with the links between tbs without taking the tb_lock, so another thread can come in via eg tb_add_jump() and cause corruption of the linked lists). However, there are a number of comments in the TB handling code about things being non-thread-safe or not SMP safe, so I need to have a more careful think about the whole thing.

diff --git a/exec.c b/exec.c
index db9ff55..5f4a50b 100644
--- a/exec.c
+++ b/exec.c
@@ -1606,9 +1606,8 @@ static void cpu_unlink_tb(CPUState *env)
        emulation this often isn't actually as bad as it sounds. Often
        signals are used primarily to interrupt blocking syscalls. */
     TranslationBlock *tb;
- static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;

- spin_lock(&interrupt_lock);
+ spin_lock(&tb_lock);
     tb = env->current_tb;
     /* if the cpu is currently executing code, we must unlink it and
        all the potentially executing TB */
@@ -1616,7 +1615,7 @@ static void cpu_unlink_tb(CPUState *env)
         env->current_tb = NULL;
         tb_reset_jump_recursive(tb);
     }
- spin_unlock(&interrupt_lock);
+ spin_unlock(&tb_lock);
 }

 /* mask must never be zero, except for A20 change call */