From 3098dba01c7daab60762b6f6624ea88c0d6cb65a Mon Sep 17 00:00:00 2001 From: aurel32 Date: Sat, 7 Mar 2009 21:28:24 +0000 Subject: [PATCH] Use a dedicated function to request exit from execution loop Signed-off-by: Aurelien Jarno git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6762 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-all.h | 3 ++- darwin-user/signal.c | 2 +- exec.c | 58 +++++++++++++++++++++++++------------------- gdbstub.c | 2 +- hw/dma.c | 2 +- hw/mac_dbdma.c | 2 +- linux-user/main.c | 2 +- linux-user/signal.c | 2 +- vl.c | 14 +++++------ 9 files changed, 48 insertions(+), 39 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) - 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 @@ 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