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,7 +760,6 @@ extern CPUState *cpu_single_env; | ||
760 | extern int64_t qemu_icount; | 760 | extern int64_t qemu_icount; |
761 | extern int use_icount; | 761 | extern int use_icount; |
762 | 762 | ||
763 | -#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */ | ||
764 | #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ | 763 | #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ |
765 | #define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */ | 764 | #define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */ |
766 | #define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */ | 765 | #define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */ |
@@ -774,6 +773,8 @@ extern int use_icount; | @@ -774,6 +773,8 @@ extern int use_icount; | ||
774 | void cpu_interrupt(CPUState *s, int mask); | 773 | void cpu_interrupt(CPUState *s, int mask); |
775 | void cpu_reset_interrupt(CPUState *env, int mask); | 774 | void cpu_reset_interrupt(CPUState *env, int mask); |
776 | 775 | ||
776 | +void cpu_exit(CPUState *s); | ||
777 | + | ||
777 | /* Breakpoint/watchpoint flags */ | 778 | /* Breakpoint/watchpoint flags */ |
778 | #define BP_MEM_READ 0x01 | 779 | #define BP_MEM_READ 0x01 |
779 | #define BP_MEM_WRITE 0x02 | 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,7 +215,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, | ||
215 | #endif | 215 | #endif |
216 | if (queue_signal(sig, &tinfo) == 1) { | 216 | if (queue_signal(sig, &tinfo) == 1) { |
217 | /* interrupt the virtual CPU as soon as possible */ | 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,7 +523,9 @@ static int cpu_common_load(QEMUFile *f, void *opaque, int version_id) | ||
523 | 523 | ||
524 | qemu_get_be32s(f, &env->halted); | 524 | qemu_get_be32s(f, &env->halted); |
525 | qemu_get_be32s(f, &env->interrupt_request); | 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 | tlb_flush(env, 1); | 529 | tlb_flush(env, 1); |
528 | 530 | ||
529 | return 0; | 531 | return 0; |
@@ -1499,28 +1501,36 @@ void cpu_set_log_filename(const char *filename) | @@ -1499,28 +1501,36 @@ void cpu_set_log_filename(const char *filename) | ||
1499 | cpu_set_log(loglevel); | 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 | TranslationBlock *tb; | 1512 | TranslationBlock *tb; |
1507 | static spinlock_t interrupt_lock = SPIN_LOCK_UNLOCKED; | 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 | old_mask = env->interrupt_request; | 1531 | old_mask = env->interrupt_request; |
1517 | env->interrupt_request |= mask; | 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 | if (use_icount) { | 1534 | if (use_icount) { |
1525 | env->icount_decr.u16.high = 0xffff; | 1535 | env->icount_decr.u16.high = 0xffff; |
1526 | #ifndef CONFIG_USER_ONLY | 1536 | #ifndef CONFIG_USER_ONLY |
@@ -1530,16 +1540,8 @@ void cpu_interrupt(CPUState *env, int mask) | @@ -1530,16 +1540,8 @@ void cpu_interrupt(CPUState *env, int mask) | ||
1530 | } | 1540 | } |
1531 | #endif | 1541 | #endif |
1532 | } else { | 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 | void cpu_reset_interrupt(CPUState *env, int mask) | 1547 | void cpu_reset_interrupt(CPUState *env, int mask) |
@@ -1547,6 +1549,12 @@ void cpu_reset_interrupt(CPUState *env, int mask) | @@ -1547,6 +1549,12 @@ void cpu_reset_interrupt(CPUState *env, int mask) | ||
1547 | env->interrupt_request &= ~mask; | 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 | const CPULogItem cpu_log_items[] = { | 1558 | const CPULogItem cpu_log_items[] = { |
1551 | { CPU_LOG_TB_OUT_ASM, "out_asm", | 1559 | { CPU_LOG_TB_OUT_ASM, "out_asm", |
1552 | "show generated host assembly code for each compiled TB" }, | 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,7 +2012,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) | ||
2012 | #ifdef CONFIG_USER_ONLY | 2012 | #ifdef CONFIG_USER_ONLY |
2013 | gdb_handlesig(s->c_cpu, 0); | 2013 | gdb_handlesig(s->c_cpu, 0); |
2014 | #else | 2014 | #else |
2015 | - cpu_interrupt(s->c_cpu, CPU_INTERRUPT_EXIT); | 2015 | + cpu_exit(s->c_cpu); |
2016 | #endif | 2016 | #endif |
2017 | } | 2017 | } |
2018 | 2018 |
hw/dma.c
@@ -449,7 +449,7 @@ void DMA_schedule(int nchan) | @@ -449,7 +449,7 @@ void DMA_schedule(int nchan) | ||
449 | { | 449 | { |
450 | CPUState *env = cpu_single_env; | 450 | CPUState *env = cpu_single_env; |
451 | if (env) | 451 | if (env) |
452 | - cpu_interrupt(env, CPU_INTERRUPT_EXIT); | 452 | + cpu_exit(env); |
453 | } | 453 | } |
454 | 454 | ||
455 | static void dma_reset(void *opaque) | 455 | static void dma_reset(void *opaque) |
hw/mac_dbdma.c
@@ -653,7 +653,7 @@ void DBDMA_schedule(void) | @@ -653,7 +653,7 @@ void DBDMA_schedule(void) | ||
653 | { | 653 | { |
654 | CPUState *env = cpu_single_env; | 654 | CPUState *env = cpu_single_env; |
655 | if (env) | 655 | if (env) |
656 | - cpu_interrupt(env, CPU_INTERRUPT_EXIT); | 656 | + cpu_exit(env); |
657 | } | 657 | } |
658 | 658 | ||
659 | static void | 659 | static void |
linux-user/main.c
@@ -200,7 +200,7 @@ static inline void start_exclusive(void) | @@ -200,7 +200,7 @@ static inline void start_exclusive(void) | ||
200 | for (other = first_cpu; other; other = other->next_cpu) { | 200 | for (other = first_cpu; other; other = other->next_cpu) { |
201 | if (other->running) { | 201 | if (other->running) { |
202 | pending_cpus++; | 202 | pending_cpus++; |
203 | - cpu_interrupt(other, CPU_INTERRUPT_EXIT); | 203 | + cpu_exit(other); |
204 | } | 204 | } |
205 | } | 205 | } |
206 | if (pending_cpus > 1) { | 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,7 +460,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, | ||
460 | host_to_target_siginfo_noswap(&tinfo, info); | 460 | host_to_target_siginfo_noswap(&tinfo, info); |
461 | if (queue_signal(thread_env, sig, &tinfo) == 1) { | 461 | if (queue_signal(thread_env, sig, &tinfo) == 1) { |
462 | /* interrupt the virtual CPU as soon as possible */ | 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,7 +1181,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) | ||
1181 | } | 1181 | } |
1182 | /* Interrupt execution to force deadline recalculation. */ | 1182 | /* Interrupt execution to force deadline recalculation. */ |
1183 | if (use_icount && cpu_single_env) { | 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,7 +1348,7 @@ static void host_alarm_handler(int host_signum) | ||
1348 | 1348 | ||
1349 | if (env) { | 1349 | if (env) { |
1350 | /* stop the currently executing cpu because a timer occured */ | 1350 | /* stop the currently executing cpu because a timer occured */ |
1351 | - cpu_interrupt(env, CPU_INTERRUPT_EXIT); | 1351 | + cpu_exit(env); |
1352 | #ifdef USE_KQEMU | 1352 | #ifdef USE_KQEMU |
1353 | if (env->kqemu_enabled) { | 1353 | if (env->kqemu_enabled) { |
1354 | kqemu_cpu_interrupt(env); | 1354 | kqemu_cpu_interrupt(env); |
@@ -3326,7 +3326,7 @@ void qemu_service_io(void) | @@ -3326,7 +3326,7 @@ void qemu_service_io(void) | ||
3326 | { | 3326 | { |
3327 | CPUState *env = cpu_single_env; | 3327 | CPUState *env = cpu_single_env; |
3328 | if (env) { | 3328 | if (env) { |
3329 | - cpu_interrupt(env, CPU_INTERRUPT_EXIT); | 3329 | + cpu_exit(env); |
3330 | #ifdef USE_KQEMU | 3330 | #ifdef USE_KQEMU |
3331 | if (env->kqemu_enabled) { | 3331 | if (env->kqemu_enabled) { |
3332 | kqemu_cpu_interrupt(env); | 3332 | kqemu_cpu_interrupt(env); |
@@ -3407,7 +3407,7 @@ void qemu_bh_schedule(QEMUBH *bh) | @@ -3407,7 +3407,7 @@ void qemu_bh_schedule(QEMUBH *bh) | ||
3407 | bh->idle = 0; | 3407 | bh->idle = 0; |
3408 | /* stop the currently executing CPU to execute the BH ASAP */ | 3408 | /* stop the currently executing CPU to execute the BH ASAP */ |
3409 | if (env) { | 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,21 +3618,21 @@ void qemu_system_reset_request(void) | ||
3618 | reset_requested = 1; | 3618 | reset_requested = 1; |
3619 | } | 3619 | } |
3620 | if (cpu_single_env) | 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 | void qemu_system_shutdown_request(void) | 3624 | void qemu_system_shutdown_request(void) |
3625 | { | 3625 | { |
3626 | shutdown_requested = 1; | 3626 | shutdown_requested = 1; |
3627 | if (cpu_single_env) | 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 | void qemu_system_powerdown_request(void) | 3631 | void qemu_system_powerdown_request(void) |
3632 | { | 3632 | { |
3633 | powerdown_requested = 1; | 3633 | powerdown_requested = 1; |
3634 | if (cpu_single_env) | 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 | #ifdef _WIN32 | 3638 | #ifdef _WIN32 |