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
This commit is contained in:
aurel32 2009-03-07 21:28:24 +00:00
parent 9e995645b5
commit 3098dba01c
9 changed files with 48 additions and 39 deletions

View File

@ -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

View File

@ -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);
}
}

58
exec.c
View File

@ -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" },

View File

@ -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
}

View File

@ -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)

View File

@ -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

View File

@ -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) {

View File

@ -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);
}
}

14
vl.c
View File

@ -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