Use a dedicated function to request exit from execution loop
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6762 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/cpu-all.h b/cpu-all.h
index e0c3efd..366f47e 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -760,7 +760,6 @@
extern int64_t qemu_icount;
extern int use_icount;
-#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
@@ -774,6 +773,8 @@
void cpu_interrupt(CPUState *s, int mask);
void cpu_reset_interrupt(CPUState *env, int mask);
+void cpu_exit(CPUState *s);
+
/* Breakpoint/watchpoint flags */
#define BP_MEM_READ 0x01
#define BP_MEM_WRITE 0x02
diff --git a/darwin-user/signal.c b/darwin-user/signal.c
index ba41c2e..851e85b 100644
--- a/darwin-user/signal.c
+++ b/darwin-user/signal.c
@@ -215,7 +215,7 @@
#endif
if (queue_signal(sig, &tinfo) == 1) {
/* interrupt the virtual CPU as soon as possible */
- cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
+ cpu_exit(global_env);
}
}
diff --git a/exec.c b/exec.c
index 01a5265..c6490ff 100644
--- a/exec.c
+++ b/exec.c
@@ -523,7 +523,9 @@
qemu_get_be32s(f, &env->halted);
qemu_get_be32s(f, &env->interrupt_request);
- env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
+ /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
+ version_id is increased. */
+ env->interrupt_request &= ~0x01;
tlb_flush(env, 1);
return 0;
@@ -1499,28 +1501,36 @@
cpu_set_log(loglevel);
}
-/* mask must never be zero, except for A20 change call */
-void cpu_interrupt(CPUState *env, int mask)
+static void cpu_unlink_tb(CPUState *env)
{
-#if !defined(USE_NPTL)
- TranslationBlock *tb;
- static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
-#endif
- int old_mask;
-
- if (mask & CPU_INTERRUPT_EXIT) {
- env->exit_request = 1;
- mask &= ~CPU_INTERRUPT_EXIT;
- }
-
- old_mask = env->interrupt_request;
- env->interrupt_request |= mask;
#if defined(USE_NPTL)
/* FIXME: TB unchaining isn't SMP safe. For now just ignore the
problem and hope the cpu will stop of its own accord. For userspace
emulation this often isn't actually as bad as it sounds. Often
signals are used primarily to interrupt blocking syscalls. */
#else
+ TranslationBlock *tb;
+ static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED;
+
+ tb = env->current_tb;
+ /* if the cpu is currently executing code, we must unlink it and
+ all the potentially executing TB */
+ if (tb && !testandset(&interrupt_lock)) {
+ env->current_tb = NULL;
+ tb_reset_jump_recursive(tb);
+ resetlock(&interrupt_lock);
+ }
+#endif
+}
+
+/* mask must never be zero, except for A20 change call */
+void cpu_interrupt(CPUState *env, int mask)
+{
+ int old_mask;
+
+ old_mask = env->interrupt_request;
+ env->interrupt_request |= mask;
+
if (use_icount) {
env->icount_decr.u16.high = 0xffff;
#ifndef CONFIG_USER_ONLY
@@ -1530,16 +1540,8 @@
}
#endif
} else {
- tb = env->current_tb;
- /* if the cpu is currently executing code, we must unlink it and
- all the potentially executing TB */
- if (tb && !testandset(&interrupt_lock)) {
- env->current_tb = NULL;
- tb_reset_jump_recursive(tb);
- resetlock(&interrupt_lock);
- }
+ cpu_unlink_tb(env);
}
-#endif
}
void cpu_reset_interrupt(CPUState *env, int mask)
@@ -1547,6 +1549,12 @@
env->interrupt_request &= ~mask;
}
+void cpu_exit(CPUState *env)
+{
+ env->exit_request = 1;
+ cpu_unlink_tb(env);
+}
+
const CPULogItem cpu_log_items[] = {
{ CPU_LOG_TB_OUT_ASM, "out_asm",
"show generated host assembly code for each compiled TB" },
diff --git a/gdbstub.c b/gdbstub.c
index d549766..addff2e 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2012,7 +2012,7 @@
#ifdef CONFIG_USER_ONLY
gdb_handlesig(s->c_cpu, 0);
#else
- cpu_interrupt(s->c_cpu, CPU_INTERRUPT_EXIT);
+ cpu_exit(s->c_cpu);
#endif
}
diff --git a/hw/dma.c b/hw/dma.c
index e58ab6d..971c8d4 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -449,7 +449,7 @@
{
CPUState *env = cpu_single_env;
if (env)
- cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+ cpu_exit(env);
}
static void dma_reset(void *opaque)
diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index 8e82a23..b8e4b12 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -653,7 +653,7 @@
{
CPUState *env = cpu_single_env;
if (env)
- cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+ cpu_exit(env);
}
static void
diff --git a/linux-user/main.c b/linux-user/main.c
index 2c1e4df..feb3036 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -200,7 +200,7 @@
for (other = first_cpu; other; other = other->next_cpu) {
if (other->running) {
pending_cpus++;
- cpu_interrupt(other, CPU_INTERRUPT_EXIT);
+ cpu_exit(other);
}
}
if (pending_cpus > 1) {
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 48640ec..fc37dc1 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -460,7 +460,7 @@
host_to_target_siginfo_noswap(&tinfo, info);
if (queue_signal(thread_env, sig, &tinfo) == 1) {
/* interrupt the virtual CPU as soon as possible */
- cpu_interrupt(thread_env, CPU_INTERRUPT_EXIT);
+ cpu_exit(thread_env);
}
}
diff --git a/vl.c b/vl.c
index 62a9194..39423bb 100644
--- a/vl.c
+++ b/vl.c
@@ -1181,7 +1181,7 @@
}
/* Interrupt execution to force deadline recalculation. */
if (use_icount && cpu_single_env) {
- cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+ cpu_exit(cpu_single_env);
}
}
}
@@ -1348,7 +1348,7 @@
if (env) {
/* stop the currently executing cpu because a timer occured */
- cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+ cpu_exit(env);
#ifdef USE_KQEMU
if (env->kqemu_enabled) {
kqemu_cpu_interrupt(env);
@@ -3326,7 +3326,7 @@
{
CPUState *env = cpu_single_env;
if (env) {
- cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+ cpu_exit(env);
#ifdef USE_KQEMU
if (env->kqemu_enabled) {
kqemu_cpu_interrupt(env);
@@ -3407,7 +3407,7 @@
bh->idle = 0;
/* stop the currently executing CPU to execute the BH ASAP */
if (env) {
- cpu_interrupt(env, CPU_INTERRUPT_EXIT);
+ cpu_exit(env);
}
}
@@ -3618,21 +3618,21 @@
reset_requested = 1;
}
if (cpu_single_env)
- cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+ cpu_exit(cpu_single_env);
}
void qemu_system_shutdown_request(void)
{
shutdown_requested = 1;
if (cpu_single_env)
- cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+ cpu_exit(cpu_single_env);
}
void qemu_system_powerdown_request(void)
{
powerdown_requested = 1;
if (cpu_single_env)
- cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+ cpu_exit(cpu_single_env);
}
#ifdef _WIN32