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 | 170 | target_ulong mem_io_vaddr; /* target virtual addr at which the \ |
171 | 171 | memory was accessed */ \ |
172 | 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 | 175 | uint32_t interrupt_request; \ |
174 | 176 | volatile sig_atomic_t exit_request; \ |
175 | 177 | /* The meaning of the MMU modes is defined in the target code. */ \ |
... | ... | @@ -210,6 +212,9 @@ typedef struct CPUWatchpoint { |
210 | 212 | /* user data */ \ |
211 | 213 | void *opaque; \ |
212 | 214 | \ |
215 | + uint32_t created; \ | |
216 | + struct QemuThread *thread; \ | |
217 | + struct QemuCond *halt_cond; \ | |
213 | 218 | const char *cpu_model_str; \ |
214 | 219 | struct KVMState *kvm_state; \ |
215 | 220 | struct kvm_run *kvm_run; \ | ... | ... |
vl.c
... | ... | @@ -1346,20 +1346,20 @@ static void host_alarm_handler(int host_signum) |
1346 | 1346 | qemu_get_clock(vm_clock))) || |
1347 | 1347 | qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], |
1348 | 1348 | qemu_get_clock(rt_clock))) { |
1349 | - CPUState *env = next_cpu; | |
1350 | - | |
1351 | 1349 | qemu_event_increment(); |
1352 | 1350 | alarm_timer->flags |= ALARM_FLAG_EXPIRED; |
1353 | 1351 | |
1354 | - if (env) { | |
1352 | +#ifndef CONFIG_IOTHREAD | |
1353 | + if (next_cpu) { | |
1355 | 1354 | /* stop the currently executing cpu because a timer occured */ |
1356 | - cpu_exit(env); | |
1355 | + cpu_exit(next_cpu); | |
1357 | 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 | 1360 | #endif |
1362 | 1361 | } |
1362 | +#endif | |
1363 | 1363 | timer_alarm_pending = 1; |
1364 | 1364 | qemu_notify_event(); |
1365 | 1365 | } |
... | ... | @@ -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 | 3543 | void vm_start(void) |
3541 | 3544 | { |
3542 | 3545 | if (!vm_running) { |
... | ... | @@ -3544,6 +3547,7 @@ void vm_start(void) |
3544 | 3547 | vm_running = 1; |
3545 | 3548 | vm_state_notify(1, 0); |
3546 | 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 | 3606 | if (vm_running) { |
3603 | 3607 | cpu_disable_ticks(); |
3604 | 3608 | vm_running = 0; |
3609 | + pause_all_vcpus(); | |
3605 | 3610 | vm_state_notify(0, reason); |
3606 | 3611 | } |
3607 | 3612 | } |
... | ... | @@ -3654,18 +3659,13 @@ void qemu_system_powerdown_request(void) |
3654 | 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 | 3670 | #ifndef _WIN32 |
3671 | 3671 | static int io_thread_fd = -1; |
... | ... | @@ -3742,6 +3742,16 @@ static void qemu_event_increment(void) |
3742 | 3742 | } |
3743 | 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 | 3755 | static int qemu_init_main_loop(void) |
3746 | 3756 | { |
3747 | 3757 | return qemu_event_init(); |
... | ... | @@ -3761,11 +3771,32 @@ int qemu_cpu_self(void *env) |
3761 | 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 | 3782 | void qemu_cpu_kick(void *env) |
3765 | 3783 | { |
3766 | 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 | 3800 | #define qemu_mutex_lock_iothread() do { } while (0) |
3770 | 3801 | #define qemu_mutex_unlock_iothread() do { } while (0) |
3771 | 3802 | |
... | ... | @@ -3774,6 +3805,321 @@ void vm_stop(int reason) |
3774 | 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 | 4123 | #ifdef _WIN32 |
3778 | 4124 | static void host_main_loop_wait(int *timeout) |
3779 | 4125 | { |
... | ... | @@ -3910,9 +4256,11 @@ void main_loop_wait(int timeout) |
3910 | 4256 | } |
3911 | 4257 | |
3912 | 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 | 4265 | /* real time timers */ |
3918 | 4266 | qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], |
... | ... | @@ -3966,7 +4314,7 @@ static int qemu_cpu_exec(CPUState *env) |
3966 | 4314 | |
3967 | 4315 | static void tcg_cpu_exec(void) |
3968 | 4316 | { |
3969 | - int ret; | |
4317 | + int ret = 0; | |
3970 | 4318 | |
3971 | 4319 | if (next_cpu == NULL) |
3972 | 4320 | next_cpu = first_cpu; |
... | ... | @@ -3979,7 +4327,8 @@ static void tcg_cpu_exec(void) |
3979 | 4327 | timer_alarm_pending = 0; |
3980 | 4328 | break; |
3981 | 4329 | } |
3982 | - ret = qemu_cpu_exec(env); | |
4330 | + if (cpu_can_run(env)) | |
4331 | + ret = qemu_cpu_exec(env); | |
3983 | 4332 | if (ret == EXCP_DEBUG) { |
3984 | 4333 | gdb_set_stop_cpu(env); |
3985 | 4334 | debug_requested = 1; |
... | ... | @@ -3990,6 +4339,10 @@ static void tcg_cpu_exec(void) |
3990 | 4339 | |
3991 | 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 | 4346 | if (!env->halted) |
3994 | 4347 | return 1; |
3995 | 4348 | if (qemu_cpu_has_work(env)) |
... | ... | @@ -4073,16 +4426,27 @@ static void main_loop(void) |
4073 | 4426 | { |
4074 | 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 | 4434 | for (;;) { |
4077 | 4435 | do { |
4078 | 4436 | #ifdef CONFIG_PROFILER |
4079 | 4437 | int64_t ti; |
4080 | 4438 | #endif |
4439 | +#ifndef CONFIG_IOTHREAD | |
4081 | 4440 | tcg_cpu_exec(); |
4441 | +#endif | |
4082 | 4442 | #ifdef CONFIG_PROFILER |
4083 | 4443 | ti = profile_getclock(); |
4084 | 4444 | #endif |
4445 | +#ifdef CONFIG_IOTHREAD | |
4446 | + main_loop_wait(1000); | |
4447 | +#else | |
4085 | 4448 | main_loop_wait(qemu_calculate_timeout()); |
4449 | +#endif | |
4086 | 4450 | #ifdef CONFIG_PROFILER |
4087 | 4451 | dev_time += profile_getclock() - ti; |
4088 | 4452 | #endif |
... | ... | @@ -4097,13 +4461,17 @@ static void main_loop(void) |
4097 | 4461 | } else |
4098 | 4462 | break; |
4099 | 4463 | } |
4100 | - if (qemu_reset_requested()) | |
4464 | + if (qemu_reset_requested()) { | |
4465 | + pause_all_vcpus(); | |
4101 | 4466 | qemu_system_reset(); |
4467 | + resume_all_vcpus(); | |
4468 | + } | |
4102 | 4469 | if (qemu_powerdown_requested()) |
4103 | 4470 | qemu_system_powerdown(); |
4104 | 4471 | if ((r = qemu_vmstop_requested())) |
4105 | 4472 | vm_stop(r); |
4106 | 4473 | } |
4474 | + pause_all_vcpus(); | |
4107 | 4475 | } |
4108 | 4476 | |
4109 | 4477 | static void version(void) | ... | ... |