Commit 3098dba01c7daab60762b6f6624ea88c0d6cb65a
1 parent
9e995645
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
Showing
9 changed files
with
47 additions
and
38 deletions
cpu-all.h
| ... | ... | @@ -760,7 +760,6 @@ extern CPUState *cpu_single_env; |
| 760 | 760 | extern int64_t qemu_icount; |
| 761 | 761 | extern int use_icount; |
| 762 | 762 | |
| 763 | -#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */ | |
| 764 | 763 | #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ |
| 765 | 764 | #define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */ |
| 766 | 765 | #define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */ |
| ... | ... | @@ -774,6 +773,8 @@ extern int use_icount; |
| 774 | 773 | void cpu_interrupt(CPUState *s, int mask); |
| 775 | 774 | void cpu_reset_interrupt(CPUState *env, int mask); |
| 776 | 775 | |
| 776 | +void cpu_exit(CPUState *s); | |
| 777 | + | |
| 777 | 778 | /* Breakpoint/watchpoint flags */ |
| 778 | 779 | #define BP_MEM_READ 0x01 |
| 779 | 780 | #define BP_MEM_WRITE 0x02 | ... | ... |
darwin-user/signal.c
| ... | ... | @@ -215,7 +215,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, |
| 215 | 215 | #endif |
| 216 | 216 | if (queue_signal(sig, &tinfo) == 1) { |
| 217 | 217 | /* interrupt the virtual CPU as soon as possible */ |
| 218 | - cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); | |
| 218 | + cpu_exit(global_env); | |
| 219 | 219 | } |
| 220 | 220 | } |
| 221 | 221 | ... | ... |
exec.c
| ... | ... | @@ -523,7 +523,9 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id) |
| 523 | 523 | |
| 524 | 524 | qemu_get_be32s(f, &env->halted); |
| 525 | 525 | qemu_get_be32s(f, &env->interrupt_request); |
| 526 | - env->interrupt_request &= ~CPU_INTERRUPT_EXIT; | |
| 526 | + /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the | |
| 527 | + version_id is increased. */ | |
| 528 | + env->interrupt_request &= ~0x01; | |
| 527 | 529 | tlb_flush(env, 1); |
| 528 | 530 | |
| 529 | 531 | return 0; |
| ... | ... | @@ -1499,28 +1501,36 @@ void cpu_set_log_filename(const char *filename) |
| 1499 | 1501 | cpu_set_log(loglevel); |
| 1500 | 1502 | } |
| 1501 | 1503 | |
| 1502 | -/* mask must never be zero, except for A20 change call */ | |
| 1503 | -void cpu_interrupt(CPUState *env, int mask) | |
| 1504 | +static void cpu_unlink_tb(CPUState *env) | |
| 1504 | 1505 | { |
| 1505 | -#if !defined(USE_NPTL) | |
| 1506 | +#if defined(USE_NPTL) | |
| 1507 | + /* FIXME: TB unchaining isn't SMP safe. For now just ignore the | |
| 1508 | + problem and hope the cpu will stop of its own accord. For userspace | |
| 1509 | + emulation this often isn't actually as bad as it sounds. Often | |
| 1510 | + signals are used primarily to interrupt blocking syscalls. */ | |
| 1511 | +#else | |
| 1506 | 1512 | TranslationBlock *tb; |
| 1507 | 1513 | static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED; |
| 1508 | -#endif | |
| 1509 | - int old_mask; | |
| 1510 | 1514 | |
| 1511 | - if (mask & CPU_INTERRUPT_EXIT) { | |
| 1512 | - env->exit_request = 1; | |
| 1513 | - mask &= ~CPU_INTERRUPT_EXIT; | |
| 1515 | + tb = env->current_tb; | |
| 1516 | + /* if the cpu is currently executing code, we must unlink it and | |
| 1517 | + all the potentially executing TB */ | |
| 1518 | + if (tb && !testandset(&interrupt_lock)) { | |
| 1519 | + env->current_tb = NULL; | |
| 1520 | + tb_reset_jump_recursive(tb); | |
| 1521 | + resetlock(&interrupt_lock); | |
| 1514 | 1522 | } |
| 1523 | +#endif | |
| 1524 | +} | |
| 1525 | + | |
| 1526 | +/* mask must never be zero, except for A20 change call */ | |
| 1527 | +void cpu_interrupt(CPUState *env, int mask) | |
| 1528 | +{ | |
| 1529 | + int old_mask; | |
| 1515 | 1530 | |
| 1516 | 1531 | old_mask = env->interrupt_request; |
| 1517 | 1532 | env->interrupt_request |= mask; |
| 1518 | -#if defined(USE_NPTL) | |
| 1519 | - /* FIXME: TB unchaining isn't SMP safe. For now just ignore the | |
| 1520 | - problem and hope the cpu will stop of its own accord. For userspace | |
| 1521 | - emulation this often isn't actually as bad as it sounds. Often | |
| 1522 | - signals are used primarily to interrupt blocking syscalls. */ | |
| 1523 | -#else | |
| 1533 | + | |
| 1524 | 1534 | if (use_icount) { |
| 1525 | 1535 | env->icount_decr.u16.high = 0xffff; |
| 1526 | 1536 | #ifndef CONFIG_USER_ONLY |
| ... | ... | @@ -1530,16 +1540,8 @@ void cpu_interrupt(CPUState *env, int mask) |
| 1530 | 1540 | } |
| 1531 | 1541 | #endif |
| 1532 | 1542 | } else { |
| 1533 | - tb = env->current_tb; | |
| 1534 | - /* if the cpu is currently executing code, we must unlink it and | |
| 1535 | - all the potentially executing TB */ | |
| 1536 | - if (tb && !testandset(&interrupt_lock)) { | |
| 1537 | - env->current_tb = NULL; | |
| 1538 | - tb_reset_jump_recursive(tb); | |
| 1539 | - resetlock(&interrupt_lock); | |
| 1540 | - } | |
| 1543 | + cpu_unlink_tb(env); | |
| 1541 | 1544 | } |
| 1542 | -#endif | |
| 1543 | 1545 | } |
| 1544 | 1546 | |
| 1545 | 1547 | void cpu_reset_interrupt(CPUState *env, int mask) |
| ... | ... | @@ -1547,6 +1549,12 @@ void cpu_reset_interrupt(CPUState *env, int mask) |
| 1547 | 1549 | env->interrupt_request &= ~mask; |
| 1548 | 1550 | } |
| 1549 | 1551 | |
| 1552 | +void cpu_exit(CPUState *env) | |
| 1553 | +{ | |
| 1554 | + env->exit_request = 1; | |
| 1555 | + cpu_unlink_tb(env); | |
| 1556 | +} | |
| 1557 | + | |
| 1550 | 1558 | const CPULogItem cpu_log_items[] = { |
| 1551 | 1559 | { CPU_LOG_TB_OUT_ASM, "out_asm", |
| 1552 | 1560 | "show generated host assembly code for each compiled TB" }, | ... | ... |
gdbstub.c
| ... | ... | @@ -2012,7 +2012,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) |
| 2012 | 2012 | #ifdef CONFIG_USER_ONLY |
| 2013 | 2013 | gdb_handlesig(s->c_cpu, 0); |
| 2014 | 2014 | #else |
| 2015 | - cpu_interrupt(s->c_cpu, CPU_INTERRUPT_EXIT); | |
| 2015 | + cpu_exit(s->c_cpu); | |
| 2016 | 2016 | #endif |
| 2017 | 2017 | } |
| 2018 | 2018 | ... | ... |
hw/dma.c
hw/mac_dbdma.c
linux-user/main.c
| ... | ... | @@ -200,7 +200,7 @@ static inline void start_exclusive(void) |
| 200 | 200 | for (other = first_cpu; other; other = other->next_cpu) { |
| 201 | 201 | if (other->running) { |
| 202 | 202 | pending_cpus++; |
| 203 | - cpu_interrupt(other, CPU_INTERRUPT_EXIT); | |
| 203 | + cpu_exit(other); | |
| 204 | 204 | } |
| 205 | 205 | } |
| 206 | 206 | if (pending_cpus > 1) { | ... | ... |
linux-user/signal.c
| ... | ... | @@ -460,7 +460,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, |
| 460 | 460 | host_to_target_siginfo_noswap(&tinfo, info); |
| 461 | 461 | if (queue_signal(thread_env, sig, &tinfo) == 1) { |
| 462 | 462 | /* interrupt the virtual CPU as soon as possible */ |
| 463 | - cpu_interrupt(thread_env, CPU_INTERRUPT_EXIT); | |
| 463 | + cpu_exit(thread_env); | |
| 464 | 464 | } |
| 465 | 465 | } |
| 466 | 466 | ... | ... |
vl.c
| ... | ... | @@ -1181,7 +1181,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) |
| 1181 | 1181 | } |
| 1182 | 1182 | /* Interrupt execution to force deadline recalculation. */ |
| 1183 | 1183 | if (use_icount && cpu_single_env) { |
| 1184 | - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); | |
| 1184 | + cpu_exit(cpu_single_env); | |
| 1185 | 1185 | } |
| 1186 | 1186 | } |
| 1187 | 1187 | } |
| ... | ... | @@ -1348,7 +1348,7 @@ static void host_alarm_handler(int host_signum) |
| 1348 | 1348 | |
| 1349 | 1349 | if (env) { |
| 1350 | 1350 | /* stop the currently executing cpu because a timer occured */ |
| 1351 | - cpu_interrupt(env, CPU_INTERRUPT_EXIT); | |
| 1351 | + cpu_exit(env); | |
| 1352 | 1352 | #ifdef USE_KQEMU |
| 1353 | 1353 | if (env->kqemu_enabled) { |
| 1354 | 1354 | kqemu_cpu_interrupt(env); |
| ... | ... | @@ -3326,7 +3326,7 @@ void qemu_service_io(void) |
| 3326 | 3326 | { |
| 3327 | 3327 | CPUState *env = cpu_single_env; |
| 3328 | 3328 | if (env) { |
| 3329 | - cpu_interrupt(env, CPU_INTERRUPT_EXIT); | |
| 3329 | + cpu_exit(env); | |
| 3330 | 3330 | #ifdef USE_KQEMU |
| 3331 | 3331 | if (env->kqemu_enabled) { |
| 3332 | 3332 | kqemu_cpu_interrupt(env); |
| ... | ... | @@ -3407,7 +3407,7 @@ void qemu_bh_schedule(QEMUBH *bh) |
| 3407 | 3407 | bh->idle = 0; |
| 3408 | 3408 | /* stop the currently executing CPU to execute the BH ASAP */ |
| 3409 | 3409 | if (env) { |
| 3410 | - cpu_interrupt(env, CPU_INTERRUPT_EXIT); | |
| 3410 | + cpu_exit(env); | |
| 3411 | 3411 | } |
| 3412 | 3412 | } |
| 3413 | 3413 | |
| ... | ... | @@ -3618,21 +3618,21 @@ void qemu_system_reset_request(void) |
| 3618 | 3618 | reset_requested = 1; |
| 3619 | 3619 | } |
| 3620 | 3620 | if (cpu_single_env) |
| 3621 | - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); | |
| 3621 | + cpu_exit(cpu_single_env); | |
| 3622 | 3622 | } |
| 3623 | 3623 | |
| 3624 | 3624 | void qemu_system_shutdown_request(void) |
| 3625 | 3625 | { |
| 3626 | 3626 | shutdown_requested = 1; |
| 3627 | 3627 | if (cpu_single_env) |
| 3628 | - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); | |
| 3628 | + cpu_exit(cpu_single_env); | |
| 3629 | 3629 | } |
| 3630 | 3630 | |
| 3631 | 3631 | void qemu_system_powerdown_request(void) |
| 3632 | 3632 | { |
| 3633 | 3633 | powerdown_requested = 1; |
| 3634 | 3634 | if (cpu_single_env) |
| 3635 | - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); | |
| 3635 | + cpu_exit(cpu_single_env); | |
| 3636 | 3636 | } |
| 3637 | 3637 | |
| 3638 | 3638 | #ifdef _WIN32 | ... | ... |