Commit d6dc3d424e26b49e1f37f1ef2598eacf3bc4eac7
1 parent
6e29f5da
qemu: introduce iothread (Marcelo Tosatti)
Fill in the hooks and introduce iothread. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7248 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
395 additions
and
22 deletions
cpu-defs.h
@@ -170,6 +170,8 @@ typedef struct CPUWatchpoint { | @@ -170,6 +170,8 @@ typedef struct CPUWatchpoint { | ||
170 | target_ulong mem_io_vaddr; /* target virtual addr at which the \ | 170 | target_ulong mem_io_vaddr; /* target virtual addr at which the \ |
171 | memory was accessed */ \ | 171 | memory was accessed */ \ |
172 | uint32_t halted; /* Nonzero if the CPU is in suspend state */ \ | 172 | uint32_t halted; /* Nonzero if the CPU is in suspend state */ \ |
173 | + uint32_t stop; /* Stop request */ \ | ||
174 | + uint32_t stopped; /* Artificially stopped */ \ | ||
173 | uint32_t interrupt_request; \ | 175 | uint32_t interrupt_request; \ |
174 | volatile sig_atomic_t exit_request; \ | 176 | volatile sig_atomic_t exit_request; \ |
175 | /* The meaning of the MMU modes is defined in the target code. */ \ | 177 | /* The meaning of the MMU modes is defined in the target code. */ \ |
@@ -210,6 +212,9 @@ typedef struct CPUWatchpoint { | @@ -210,6 +212,9 @@ typedef struct CPUWatchpoint { | ||
210 | /* user data */ \ | 212 | /* user data */ \ |
211 | void *opaque; \ | 213 | void *opaque; \ |
212 | \ | 214 | \ |
215 | + uint32_t created; \ | ||
216 | + struct QemuThread *thread; \ | ||
217 | + struct QemuCond *halt_cond; \ | ||
213 | const char *cpu_model_str; \ | 218 | const char *cpu_model_str; \ |
214 | struct KVMState *kvm_state; \ | 219 | struct KVMState *kvm_state; \ |
215 | struct kvm_run *kvm_run; \ | 220 | struct kvm_run *kvm_run; \ |
vl.c
@@ -1346,20 +1346,20 @@ static void host_alarm_handler(int host_signum) | @@ -1346,20 +1346,20 @@ static void host_alarm_handler(int host_signum) | ||
1346 | qemu_get_clock(vm_clock))) || | 1346 | qemu_get_clock(vm_clock))) || |
1347 | qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], | 1347 | qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], |
1348 | qemu_get_clock(rt_clock))) { | 1348 | qemu_get_clock(rt_clock))) { |
1349 | - CPUState *env = next_cpu; | ||
1350 | - | ||
1351 | qemu_event_increment(); | 1349 | qemu_event_increment(); |
1352 | alarm_timer->flags |= ALARM_FLAG_EXPIRED; | 1350 | alarm_timer->flags |= ALARM_FLAG_EXPIRED; |
1353 | 1351 | ||
1354 | - if (env) { | 1352 | +#ifndef CONFIG_IOTHREAD |
1353 | + if (next_cpu) { | ||
1355 | /* stop the currently executing cpu because a timer occured */ | 1354 | /* stop the currently executing cpu because a timer occured */ |
1356 | - cpu_exit(env); | 1355 | + cpu_exit(next_cpu); |
1357 | #ifdef CONFIG_KQEMU | 1356 | #ifdef CONFIG_KQEMU |
1358 | - if (env->kqemu_enabled) { | ||
1359 | - kqemu_cpu_interrupt(env); | 1357 | + if (next_cpu->kqemu_enabled) { |
1358 | + kqemu_cpu_interrupt(next_cpu); | ||
1360 | } | 1359 | } |
1361 | #endif | 1360 | #endif |
1362 | } | 1361 | } |
1362 | +#endif | ||
1363 | timer_alarm_pending = 1; | 1363 | timer_alarm_pending = 1; |
1364 | qemu_notify_event(); | 1364 | qemu_notify_event(); |
1365 | } | 1365 | } |
@@ -3537,6 +3537,9 @@ static void vm_state_notify(int running, int reason) | @@ -3537,6 +3537,9 @@ static void vm_state_notify(int running, int reason) | ||
3537 | } | 3537 | } |
3538 | } | 3538 | } |
3539 | 3539 | ||
3540 | +static void resume_all_vcpus(void); | ||
3541 | +static void pause_all_vcpus(void); | ||
3542 | + | ||
3540 | void vm_start(void) | 3543 | void vm_start(void) |
3541 | { | 3544 | { |
3542 | if (!vm_running) { | 3545 | if (!vm_running) { |
@@ -3544,6 +3547,7 @@ void vm_start(void) | @@ -3544,6 +3547,7 @@ void vm_start(void) | ||
3544 | vm_running = 1; | 3547 | vm_running = 1; |
3545 | vm_state_notify(1, 0); | 3548 | vm_state_notify(1, 0); |
3546 | qemu_rearm_alarm_timer(alarm_timer); | 3549 | qemu_rearm_alarm_timer(alarm_timer); |
3550 | + resume_all_vcpus(); | ||
3547 | } | 3551 | } |
3548 | } | 3552 | } |
3549 | 3553 | ||
@@ -3602,6 +3606,7 @@ static void do_vm_stop(int reason) | @@ -3602,6 +3606,7 @@ static void do_vm_stop(int reason) | ||
3602 | if (vm_running) { | 3606 | if (vm_running) { |
3603 | cpu_disable_ticks(); | 3607 | cpu_disable_ticks(); |
3604 | vm_running = 0; | 3608 | vm_running = 0; |
3609 | + pause_all_vcpus(); | ||
3605 | vm_state_notify(0, reason); | 3610 | vm_state_notify(0, reason); |
3606 | } | 3611 | } |
3607 | } | 3612 | } |
@@ -3654,18 +3659,13 @@ void qemu_system_powerdown_request(void) | @@ -3654,18 +3659,13 @@ void qemu_system_powerdown_request(void) | ||
3654 | qemu_notify_event(); | 3659 | qemu_notify_event(); |
3655 | } | 3660 | } |
3656 | 3661 | ||
3657 | -void qemu_notify_event(void) | 3662 | +#ifdef CONFIG_IOTHREAD |
3663 | +static void qemu_system_vmstop_request(int reason) | ||
3658 | { | 3664 | { |
3659 | - CPUState *env = cpu_single_env; | ||
3660 | - | ||
3661 | - if (env) { | ||
3662 | - cpu_exit(env); | ||
3663 | -#ifdef USE_KQEMU | ||
3664 | - if (env->kqemu_enabled) | ||
3665 | - kqemu_cpu_interrupt(env); | ||
3666 | -#endif | ||
3667 | - } | 3665 | + vmstop_requested = reason; |
3666 | + qemu_notify_event(); | ||
3668 | } | 3667 | } |
3668 | +#endif | ||
3669 | 3669 | ||
3670 | #ifndef _WIN32 | 3670 | #ifndef _WIN32 |
3671 | static int io_thread_fd = -1; | 3671 | static int io_thread_fd = -1; |
@@ -3742,6 +3742,16 @@ static void qemu_event_increment(void) | @@ -3742,6 +3742,16 @@ static void qemu_event_increment(void) | ||
3742 | } | 3742 | } |
3743 | #endif | 3743 | #endif |
3744 | 3744 | ||
3745 | +static int cpu_can_run(CPUState *env) | ||
3746 | +{ | ||
3747 | + if (env->stop) | ||
3748 | + return 0; | ||
3749 | + if (env->stopped) | ||
3750 | + return 0; | ||
3751 | + return 1; | ||
3752 | +} | ||
3753 | + | ||
3754 | +#ifndef CONFIG_IOTHREAD | ||
3745 | static int qemu_init_main_loop(void) | 3755 | static int qemu_init_main_loop(void) |
3746 | { | 3756 | { |
3747 | return qemu_event_init(); | 3757 | return qemu_event_init(); |
@@ -3761,11 +3771,32 @@ int qemu_cpu_self(void *env) | @@ -3761,11 +3771,32 @@ int qemu_cpu_self(void *env) | ||
3761 | return 1; | 3771 | return 1; |
3762 | } | 3772 | } |
3763 | 3773 | ||
3774 | +static void resume_all_vcpus(void) | ||
3775 | +{ | ||
3776 | +} | ||
3777 | + | ||
3778 | +static void pause_all_vcpus(void) | ||
3779 | +{ | ||
3780 | +} | ||
3781 | + | ||
3764 | void qemu_cpu_kick(void *env) | 3782 | void qemu_cpu_kick(void *env) |
3765 | { | 3783 | { |
3766 | return; | 3784 | return; |
3767 | } | 3785 | } |
3768 | 3786 | ||
3787 | +void qemu_notify_event(void) | ||
3788 | +{ | ||
3789 | + CPUState *env = cpu_single_env; | ||
3790 | + | ||
3791 | + if (env) { | ||
3792 | + cpu_exit(env); | ||
3793 | +#ifdef USE_KQEMU | ||
3794 | + if (env->kqemu_enabled) | ||
3795 | + kqemu_cpu_interrupt(env); | ||
3796 | +#endif | ||
3797 | + } | ||
3798 | +} | ||
3799 | + | ||
3769 | #define qemu_mutex_lock_iothread() do { } while (0) | 3800 | #define qemu_mutex_lock_iothread() do { } while (0) |
3770 | #define qemu_mutex_unlock_iothread() do { } while (0) | 3801 | #define qemu_mutex_unlock_iothread() do { } while (0) |
3771 | 3802 | ||
@@ -3774,6 +3805,321 @@ void vm_stop(int reason) | @@ -3774,6 +3805,321 @@ void vm_stop(int reason) | ||
3774 | do_vm_stop(reason); | 3805 | do_vm_stop(reason); |
3775 | } | 3806 | } |
3776 | 3807 | ||
3808 | +#else /* CONFIG_IOTHREAD */ | ||
3809 | + | ||
3810 | +#include "qemu-thread.h" | ||
3811 | + | ||
3812 | +QemuMutex qemu_global_mutex; | ||
3813 | +static QemuMutex qemu_fair_mutex; | ||
3814 | + | ||
3815 | +static QemuThread io_thread; | ||
3816 | + | ||
3817 | +static QemuThread *tcg_cpu_thread; | ||
3818 | +static QemuCond *tcg_halt_cond; | ||
3819 | + | ||
3820 | +static int qemu_system_ready; | ||
3821 | +/* cpu creation */ | ||
3822 | +static QemuCond qemu_cpu_cond; | ||
3823 | +/* system init */ | ||
3824 | +static QemuCond qemu_system_cond; | ||
3825 | +static QemuCond qemu_pause_cond; | ||
3826 | + | ||
3827 | +static void block_io_signals(void); | ||
3828 | +static void unblock_io_signals(void); | ||
3829 | +static int tcg_has_work(void); | ||
3830 | + | ||
3831 | +static int qemu_init_main_loop(void) | ||
3832 | +{ | ||
3833 | + int ret; | ||
3834 | + | ||
3835 | + ret = qemu_event_init(); | ||
3836 | + if (ret) | ||
3837 | + return ret; | ||
3838 | + | ||
3839 | + qemu_cond_init(&qemu_pause_cond); | ||
3840 | + qemu_mutex_init(&qemu_fair_mutex); | ||
3841 | + qemu_mutex_init(&qemu_global_mutex); | ||
3842 | + qemu_mutex_lock(&qemu_global_mutex); | ||
3843 | + | ||
3844 | + unblock_io_signals(); | ||
3845 | + qemu_thread_self(&io_thread); | ||
3846 | + | ||
3847 | + return 0; | ||
3848 | +} | ||
3849 | + | ||
3850 | +static void qemu_wait_io_event(CPUState *env) | ||
3851 | +{ | ||
3852 | + while (!tcg_has_work()) | ||
3853 | + qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000); | ||
3854 | + | ||
3855 | + qemu_mutex_unlock(&qemu_global_mutex); | ||
3856 | + | ||
3857 | + /* | ||
3858 | + * Users of qemu_global_mutex can be starved, having no chance | ||
3859 | + * to acquire it since this path will get to it first. | ||
3860 | + * So use another lock to provide fairness. | ||
3861 | + */ | ||
3862 | + qemu_mutex_lock(&qemu_fair_mutex); | ||
3863 | + qemu_mutex_unlock(&qemu_fair_mutex); | ||
3864 | + | ||
3865 | + qemu_mutex_lock(&qemu_global_mutex); | ||
3866 | + if (env->stop) { | ||
3867 | + env->stop = 0; | ||
3868 | + env->stopped = 1; | ||
3869 | + qemu_cond_signal(&qemu_pause_cond); | ||
3870 | + } | ||
3871 | +} | ||
3872 | + | ||
3873 | +static int qemu_cpu_exec(CPUState *env); | ||
3874 | + | ||
3875 | +static void *kvm_cpu_thread_fn(void *arg) | ||
3876 | +{ | ||
3877 | + CPUState *env = arg; | ||
3878 | + | ||
3879 | + block_io_signals(); | ||
3880 | + qemu_thread_self(env->thread); | ||
3881 | + | ||
3882 | + /* signal CPU creation */ | ||
3883 | + qemu_mutex_lock(&qemu_global_mutex); | ||
3884 | + env->created = 1; | ||
3885 | + qemu_cond_signal(&qemu_cpu_cond); | ||
3886 | + | ||
3887 | + /* and wait for machine initialization */ | ||
3888 | + while (!qemu_system_ready) | ||
3889 | + qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100); | ||
3890 | + | ||
3891 | + while (1) { | ||
3892 | + if (cpu_can_run(env)) | ||
3893 | + qemu_cpu_exec(env); | ||
3894 | + qemu_wait_io_event(env); | ||
3895 | + } | ||
3896 | + | ||
3897 | + return NULL; | ||
3898 | +} | ||
3899 | + | ||
3900 | +static void tcg_cpu_exec(void); | ||
3901 | + | ||
3902 | +static void *tcg_cpu_thread_fn(void *arg) | ||
3903 | +{ | ||
3904 | + CPUState *env = arg; | ||
3905 | + | ||
3906 | + block_io_signals(); | ||
3907 | + qemu_thread_self(env->thread); | ||
3908 | + | ||
3909 | + /* signal CPU creation */ | ||
3910 | + qemu_mutex_lock(&qemu_global_mutex); | ||
3911 | + for (env = first_cpu; env != NULL; env = env->next_cpu) | ||
3912 | + env->created = 1; | ||
3913 | + qemu_cond_signal(&qemu_cpu_cond); | ||
3914 | + | ||
3915 | + /* and wait for machine initialization */ | ||
3916 | + while (!qemu_system_ready) | ||
3917 | + qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100); | ||
3918 | + | ||
3919 | + while (1) { | ||
3920 | + tcg_cpu_exec(); | ||
3921 | + qemu_wait_io_event(cur_cpu); | ||
3922 | + } | ||
3923 | + | ||
3924 | + return NULL; | ||
3925 | +} | ||
3926 | + | ||
3927 | +void qemu_cpu_kick(void *_env) | ||
3928 | +{ | ||
3929 | + CPUState *env = _env; | ||
3930 | + qemu_cond_broadcast(env->halt_cond); | ||
3931 | + if (kvm_enabled()) | ||
3932 | + qemu_thread_signal(env->thread, SIGUSR1); | ||
3933 | +} | ||
3934 | + | ||
3935 | +int qemu_cpu_self(void *env) | ||
3936 | +{ | ||
3937 | + return (cpu_single_env != NULL); | ||
3938 | +} | ||
3939 | + | ||
3940 | +static void cpu_signal(int sig) | ||
3941 | +{ | ||
3942 | + if (cpu_single_env) | ||
3943 | + cpu_exit(cpu_single_env); | ||
3944 | +} | ||
3945 | + | ||
3946 | +static void block_io_signals(void) | ||
3947 | +{ | ||
3948 | + sigset_t set; | ||
3949 | + struct sigaction sigact; | ||
3950 | + | ||
3951 | + sigemptyset(&set); | ||
3952 | + sigaddset(&set, SIGUSR2); | ||
3953 | + sigaddset(&set, SIGIO); | ||
3954 | + sigaddset(&set, SIGALRM); | ||
3955 | + pthread_sigmask(SIG_BLOCK, &set, NULL); | ||
3956 | + | ||
3957 | + sigemptyset(&set); | ||
3958 | + sigaddset(&set, SIGUSR1); | ||
3959 | + pthread_sigmask(SIG_UNBLOCK, &set, NULL); | ||
3960 | + | ||
3961 | + memset(&sigact, 0, sizeof(sigact)); | ||
3962 | + sigact.sa_handler = cpu_signal; | ||
3963 | + sigaction(SIGUSR1, &sigact, NULL); | ||
3964 | +} | ||
3965 | + | ||
3966 | +static void unblock_io_signals(void) | ||
3967 | +{ | ||
3968 | + sigset_t set; | ||
3969 | + | ||
3970 | + sigemptyset(&set); | ||
3971 | + sigaddset(&set, SIGUSR2); | ||
3972 | + sigaddset(&set, SIGIO); | ||
3973 | + sigaddset(&set, SIGALRM); | ||
3974 | + pthread_sigmask(SIG_UNBLOCK, &set, NULL); | ||
3975 | + | ||
3976 | + sigemptyset(&set); | ||
3977 | + sigaddset(&set, SIGUSR1); | ||
3978 | + pthread_sigmask(SIG_BLOCK, &set, NULL); | ||
3979 | +} | ||
3980 | + | ||
3981 | +static void qemu_signal_lock(unsigned int msecs) | ||
3982 | +{ | ||
3983 | + qemu_mutex_lock(&qemu_fair_mutex); | ||
3984 | + | ||
3985 | + while (qemu_mutex_trylock(&qemu_global_mutex)) { | ||
3986 | + qemu_thread_signal(tcg_cpu_thread, SIGUSR1); | ||
3987 | + if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs)) | ||
3988 | + break; | ||
3989 | + } | ||
3990 | + qemu_mutex_unlock(&qemu_fair_mutex); | ||
3991 | +} | ||
3992 | + | ||
3993 | +static void qemu_mutex_lock_iothread(void) | ||
3994 | +{ | ||
3995 | + if (kvm_enabled()) { | ||
3996 | + qemu_mutex_lock(&qemu_fair_mutex); | ||
3997 | + qemu_mutex_lock(&qemu_global_mutex); | ||
3998 | + qemu_mutex_unlock(&qemu_fair_mutex); | ||
3999 | + } else | ||
4000 | + qemu_signal_lock(100); | ||
4001 | +} | ||
4002 | + | ||
4003 | +static void qemu_mutex_unlock_iothread(void) | ||
4004 | +{ | ||
4005 | + qemu_mutex_unlock(&qemu_global_mutex); | ||
4006 | +} | ||
4007 | + | ||
4008 | +static int all_vcpus_paused(void) | ||
4009 | +{ | ||
4010 | + CPUState *penv = first_cpu; | ||
4011 | + | ||
4012 | + while (penv) { | ||
4013 | + if (!penv->stopped) | ||
4014 | + return 0; | ||
4015 | + penv = (CPUState *)penv->next_cpu; | ||
4016 | + } | ||
4017 | + | ||
4018 | + return 1; | ||
4019 | +} | ||
4020 | + | ||
4021 | +static void pause_all_vcpus(void) | ||
4022 | +{ | ||
4023 | + CPUState *penv = first_cpu; | ||
4024 | + | ||
4025 | + while (penv) { | ||
4026 | + penv->stop = 1; | ||
4027 | + qemu_thread_signal(penv->thread, SIGUSR1); | ||
4028 | + qemu_cpu_kick(penv); | ||
4029 | + penv = (CPUState *)penv->next_cpu; | ||
4030 | + } | ||
4031 | + | ||
4032 | + while (!all_vcpus_paused()) { | ||
4033 | + qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100); | ||
4034 | + penv = first_cpu; | ||
4035 | + while (penv) { | ||
4036 | + qemu_thread_signal(penv->thread, SIGUSR1); | ||
4037 | + penv = (CPUState *)penv->next_cpu; | ||
4038 | + } | ||
4039 | + } | ||
4040 | +} | ||
4041 | + | ||
4042 | +static void resume_all_vcpus(void) | ||
4043 | +{ | ||
4044 | + CPUState *penv = first_cpu; | ||
4045 | + | ||
4046 | + while (penv) { | ||
4047 | + penv->stop = 0; | ||
4048 | + penv->stopped = 0; | ||
4049 | + qemu_thread_signal(penv->thread, SIGUSR1); | ||
4050 | + qemu_cpu_kick(penv); | ||
4051 | + penv = (CPUState *)penv->next_cpu; | ||
4052 | + } | ||
4053 | +} | ||
4054 | + | ||
4055 | +static void tcg_init_vcpu(void *_env) | ||
4056 | +{ | ||
4057 | + CPUState *env = _env; | ||
4058 | + /* share a single thread for all cpus with TCG */ | ||
4059 | + if (!tcg_cpu_thread) { | ||
4060 | + env->thread = qemu_mallocz(sizeof(QemuThread)); | ||
4061 | + env->halt_cond = qemu_mallocz(sizeof(QemuCond)); | ||
4062 | + qemu_cond_init(env->halt_cond); | ||
4063 | + qemu_thread_create(env->thread, tcg_cpu_thread_fn, env); | ||
4064 | + while (env->created == 0) | ||
4065 | + qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100); | ||
4066 | + tcg_cpu_thread = env->thread; | ||
4067 | + tcg_halt_cond = env->halt_cond; | ||
4068 | + } else { | ||
4069 | + env->thread = tcg_cpu_thread; | ||
4070 | + env->halt_cond = tcg_halt_cond; | ||
4071 | + } | ||
4072 | +} | ||
4073 | + | ||
4074 | +static void kvm_start_vcpu(CPUState *env) | ||
4075 | +{ | ||
4076 | + kvm_init_vcpu(env); | ||
4077 | + env->thread = qemu_mallocz(sizeof(QemuThread)); | ||
4078 | + env->halt_cond = qemu_mallocz(sizeof(QemuCond)); | ||
4079 | + qemu_cond_init(env->halt_cond); | ||
4080 | + qemu_thread_create(env->thread, kvm_cpu_thread_fn, env); | ||
4081 | + while (env->created == 0) | ||
4082 | + qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100); | ||
4083 | +} | ||
4084 | + | ||
4085 | +void qemu_init_vcpu(void *_env) | ||
4086 | +{ | ||
4087 | + CPUState *env = _env; | ||
4088 | + | ||
4089 | + if (kvm_enabled()) | ||
4090 | + kvm_start_vcpu(env); | ||
4091 | + else | ||
4092 | + tcg_init_vcpu(env); | ||
4093 | +} | ||
4094 | + | ||
4095 | +void qemu_notify_event(void) | ||
4096 | +{ | ||
4097 | + qemu_event_increment(); | ||
4098 | +} | ||
4099 | + | ||
4100 | +void vm_stop(int reason) | ||
4101 | +{ | ||
4102 | + QemuThread me; | ||
4103 | + qemu_thread_self(&me); | ||
4104 | + | ||
4105 | + if (!qemu_thread_equal(&me, &io_thread)) { | ||
4106 | + qemu_system_vmstop_request(reason); | ||
4107 | + /* | ||
4108 | + * FIXME: should not return to device code in case | ||
4109 | + * vm_stop() has been requested. | ||
4110 | + */ | ||
4111 | + if (cpu_single_env) { | ||
4112 | + cpu_exit(cpu_single_env); | ||
4113 | + cpu_single_env->stop = 1; | ||
4114 | + } | ||
4115 | + return; | ||
4116 | + } | ||
4117 | + do_vm_stop(reason); | ||
4118 | +} | ||
4119 | + | ||
4120 | +#endif | ||
4121 | + | ||
4122 | + | ||
3777 | #ifdef _WIN32 | 4123 | #ifdef _WIN32 |
3778 | static void host_main_loop_wait(int *timeout) | 4124 | static void host_main_loop_wait(int *timeout) |
3779 | { | 4125 | { |
@@ -3910,9 +4256,11 @@ void main_loop_wait(int timeout) | @@ -3910,9 +4256,11 @@ void main_loop_wait(int timeout) | ||
3910 | } | 4256 | } |
3911 | 4257 | ||
3912 | /* vm time timers */ | 4258 | /* vm time timers */ |
3913 | - if (vm_running && likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER))) | ||
3914 | - qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], | ||
3915 | - qemu_get_clock(vm_clock)); | 4259 | + if (vm_running) { |
4260 | + if (!cur_cpu || likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER))) | ||
4261 | + qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], | ||
4262 | + qemu_get_clock(vm_clock)); | ||
4263 | + } | ||
3916 | 4264 | ||
3917 | /* real time timers */ | 4265 | /* real time timers */ |
3918 | qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], | 4266 | qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], |
@@ -3966,7 +4314,7 @@ static int qemu_cpu_exec(CPUState *env) | @@ -3966,7 +4314,7 @@ static int qemu_cpu_exec(CPUState *env) | ||
3966 | 4314 | ||
3967 | static void tcg_cpu_exec(void) | 4315 | static void tcg_cpu_exec(void) |
3968 | { | 4316 | { |
3969 | - int ret; | 4317 | + int ret = 0; |
3970 | 4318 | ||
3971 | if (next_cpu == NULL) | 4319 | if (next_cpu == NULL) |
3972 | next_cpu = first_cpu; | 4320 | next_cpu = first_cpu; |
@@ -3979,7 +4327,8 @@ static void tcg_cpu_exec(void) | @@ -3979,7 +4327,8 @@ static void tcg_cpu_exec(void) | ||
3979 | timer_alarm_pending = 0; | 4327 | timer_alarm_pending = 0; |
3980 | break; | 4328 | break; |
3981 | } | 4329 | } |
3982 | - ret = qemu_cpu_exec(env); | 4330 | + if (cpu_can_run(env)) |
4331 | + ret = qemu_cpu_exec(env); | ||
3983 | if (ret == EXCP_DEBUG) { | 4332 | if (ret == EXCP_DEBUG) { |
3984 | gdb_set_stop_cpu(env); | 4333 | gdb_set_stop_cpu(env); |
3985 | debug_requested = 1; | 4334 | debug_requested = 1; |
@@ -3990,6 +4339,10 @@ static void tcg_cpu_exec(void) | @@ -3990,6 +4339,10 @@ static void tcg_cpu_exec(void) | ||
3990 | 4339 | ||
3991 | static int cpu_has_work(CPUState *env) | 4340 | static int cpu_has_work(CPUState *env) |
3992 | { | 4341 | { |
4342 | + if (env->stop) | ||
4343 | + return 1; | ||
4344 | + if (env->stopped) | ||
4345 | + return 0; | ||
3993 | if (!env->halted) | 4346 | if (!env->halted) |
3994 | return 1; | 4347 | return 1; |
3995 | if (qemu_cpu_has_work(env)) | 4348 | if (qemu_cpu_has_work(env)) |
@@ -4073,16 +4426,27 @@ static void main_loop(void) | @@ -4073,16 +4426,27 @@ static void main_loop(void) | ||
4073 | { | 4426 | { |
4074 | int r; | 4427 | int r; |
4075 | 4428 | ||
4429 | +#ifdef CONFIG_IOTHREAD | ||
4430 | + qemu_system_ready = 1; | ||
4431 | + qemu_cond_broadcast(&qemu_system_cond); | ||
4432 | +#endif | ||
4433 | + | ||
4076 | for (;;) { | 4434 | for (;;) { |
4077 | do { | 4435 | do { |
4078 | #ifdef CONFIG_PROFILER | 4436 | #ifdef CONFIG_PROFILER |
4079 | int64_t ti; | 4437 | int64_t ti; |
4080 | #endif | 4438 | #endif |
4439 | +#ifndef CONFIG_IOTHREAD | ||
4081 | tcg_cpu_exec(); | 4440 | tcg_cpu_exec(); |
4441 | +#endif | ||
4082 | #ifdef CONFIG_PROFILER | 4442 | #ifdef CONFIG_PROFILER |
4083 | ti = profile_getclock(); | 4443 | ti = profile_getclock(); |
4084 | #endif | 4444 | #endif |
4445 | +#ifdef CONFIG_IOTHREAD | ||
4446 | + main_loop_wait(1000); | ||
4447 | +#else | ||
4085 | main_loop_wait(qemu_calculate_timeout()); | 4448 | main_loop_wait(qemu_calculate_timeout()); |
4449 | +#endif | ||
4086 | #ifdef CONFIG_PROFILER | 4450 | #ifdef CONFIG_PROFILER |
4087 | dev_time += profile_getclock() - ti; | 4451 | dev_time += profile_getclock() - ti; |
4088 | #endif | 4452 | #endif |
@@ -4097,13 +4461,17 @@ static void main_loop(void) | @@ -4097,13 +4461,17 @@ static void main_loop(void) | ||
4097 | } else | 4461 | } else |
4098 | break; | 4462 | break; |
4099 | } | 4463 | } |
4100 | - if (qemu_reset_requested()) | 4464 | + if (qemu_reset_requested()) { |
4465 | + pause_all_vcpus(); | ||
4101 | qemu_system_reset(); | 4466 | qemu_system_reset(); |
4467 | + resume_all_vcpus(); | ||
4468 | + } | ||
4102 | if (qemu_powerdown_requested()) | 4469 | if (qemu_powerdown_requested()) |
4103 | qemu_system_powerdown(); | 4470 | qemu_system_powerdown(); |
4104 | if ((r = qemu_vmstop_requested())) | 4471 | if ((r = qemu_vmstop_requested())) |
4105 | vm_stop(r); | 4472 | vm_stop(r); |
4106 | } | 4473 | } |
4474 | + pause_all_vcpus(); | ||
4107 | } | 4475 | } |
4108 | 4476 | ||
4109 | static void version(void) | 4477 | static void version(void) |