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