summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2009-03-07 21:28:24 +0000
committeraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2009-03-07 21:28:24 +0000
commit3098dba01c7daab60762b6f6624ea88c0d6cb65a (patch)
treea77ed1b45c1228d3fa7486de9f3d64885682c0d7
parent9e995645b54de7aa77c0b56c9507a2153e81f92f (diff)
downloadqemu-3098dba01c7daab60762b6f6624ea88c0d6cb65a.tar.gz
qemu-3098dba01c7daab60762b6f6624ea88c0d6cb65a.tar.bz2
qemu-3098dba01c7daab60762b6f6624ea88c0d6cb65a.zip
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
-rw-r--r--cpu-all.h3
-rw-r--r--darwin-user/signal.c2
-rw-r--r--exec.c56
-rw-r--r--gdbstub.c2
-rw-r--r--hw/dma.c2
-rw-r--r--hw/mac_dbdma.c2
-rw-r--r--linux-user/main.c2
-rw-r--r--linux-user/signal.c2
-rw-r--r--vl.c14
9 files changed, 47 insertions, 38 deletions
diff --git a/cpu-all.h b/cpu-all.h
index e0c3efd557..366f47e5bb 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -760,7 +760,6 @@ extern CPUState *cpu_single_env;
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 @@ extern int use_icount;
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 ba41c2e61a..851e85b60f 100644
--- a/darwin-user/signal.c
+++ b/darwin-user/signal.c
@@ -215,7 +215,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
#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 01a5265df8..c6490ff074 100644
--- a/exec.c
+++ b/exec.c
@@ -523,7 +523,9 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id)
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 @@ void cpu_set_log_filename(const char *filename)
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)
+#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;
-#endif
- int old_mask;
- if (mask & CPU_INTERRUPT_EXIT) {
- env->exit_request = 1;
- mask &= ~CPU_INTERRUPT_EXIT;
+ 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 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
+
if (use_icount) {
env->icount_decr.u16.high = 0xffff;
#ifndef CONFIG_USER_ONLY
@@ -1530,16 +1540,8 @@ void cpu_interrupt(CPUState *env, int mask)
}
#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 @@ void cpu_reset_interrupt(CPUState *env, int mask)
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 d54976612f..addff2ee7a 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2012,7 +2012,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
#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 e58ab6dd23..971c8d466f 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -449,7 +449,7 @@ void DMA_schedule(int nchan)
{
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 8e82a2356c..b8e4b128d4 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -653,7 +653,7 @@ void DBDMA_schedule(void)
{
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 2c1e4df6e5..feb3036170 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -200,7 +200,7 @@ static inline void start_exclusive(void)
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 48640ec835..fc37dc11ff 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -460,7 +460,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
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 62a9194614..39423bb4d6 100644
--- a/vl.c
+++ b/vl.c
@@ -1181,7 +1181,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
}
/* 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 @@ static void host_alarm_handler(int host_signum)
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 @@ void qemu_service_io(void)
{
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 @@ void qemu_bh_schedule(QEMUBH *bh)
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 @@ void qemu_system_reset_request(void)
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