From db08b687cdd5319286665aabd34f82665630416f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 11 Jan 2018 13:53:12 +0100 Subject: [PATCH] cpus: unify qemu_*_wait_io_event Except for round-robin TCG, every other accelerator is using more or less the same code around qemu_wait_io_event_common. The exception is HAX, which also has to eat the dummy APC that is queued by qemu_cpu_kick_thread. We can add the SleepEx call to qemu_wait_io_event under "if (!tcg_enabled())", since that is the condition that is used in qemu_cpu_kick_thread, and unify the function for KVM, HAX, HVF and multi-threaded TCG. Single-threaded TCG code can also be simplified since it is only used in the round-robin, sleep-if-all-CPUs-idle case. Signed-off-by: Paolo Bonzini --- cpus.c | 49 +++++++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/cpus.c b/cpus.c index f99253746a..2cb0af9b22 100644 --- a/cpus.c +++ b/cpus.c @@ -909,7 +909,8 @@ static void kick_tcg_thread(void *opaque) static void start_tcg_kick_timer(void) { - if (!mttcg_enabled && !tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) { + assert(!mttcg_enabled); + if (!tcg_kick_vcpu_timer && CPU_NEXT(first_cpu)) { tcg_kick_vcpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, kick_tcg_thread, NULL); timer_mod(tcg_kick_vcpu_timer, qemu_tcg_next_kick()); @@ -918,6 +919,7 @@ static void start_tcg_kick_timer(void) static void stop_tcg_kick_timer(void) { + assert(!mttcg_enabled); if (tcg_kick_vcpu_timer) { timer_del(tcg_kick_vcpu_timer); tcg_kick_vcpu_timer = NULL; @@ -1137,18 +1139,9 @@ static void qemu_wait_io_event_common(CPUState *cpu) process_queued_cpu_work(cpu); } -static bool qemu_tcg_should_sleep(CPUState *cpu) +static void qemu_tcg_rr_wait_io_event(CPUState *cpu) { - if (mttcg_enabled) { - return cpu_thread_is_idle(cpu); - } else { - return all_cpu_threads_idle(); - } -} - -static void qemu_tcg_wait_io_event(CPUState *cpu) -{ - while (qemu_tcg_should_sleep(cpu)) { + while (all_cpu_threads_idle()) { stop_tcg_kick_timer(); qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); } @@ -1158,20 +1151,18 @@ static void qemu_tcg_wait_io_event(CPUState *cpu) qemu_wait_io_event_common(cpu); } -static void qemu_kvm_wait_io_event(CPUState *cpu) +static void qemu_wait_io_event(CPUState *cpu) { while (cpu_thread_is_idle(cpu)) { qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); } - qemu_wait_io_event_common(cpu); -} - -static void qemu_hvf_wait_io_event(CPUState *cpu) -{ - while (cpu_thread_is_idle(cpu)) { - qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); +#ifdef _WIN32 + /* Eat dummy APC queued by qemu_cpu_kick_thread. */ + if (!tcg_enabled()) { + SleepEx(0, TRUE); } +#endif qemu_wait_io_event_common(cpu); } @@ -1207,7 +1198,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) cpu_handle_guest_debug(cpu); } } - qemu_kvm_wait_io_event(cpu); + qemu_wait_io_event(cpu); } while (!cpu->unplug || cpu_can_run(cpu)); qemu_kvm_destroy_vcpu(cpu); @@ -1253,7 +1244,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg) exit(1); } qemu_mutex_lock_iothread(); - qemu_wait_io_event_common(cpu); + qemu_wait_io_event(cpu); } return NULL; @@ -1470,7 +1461,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg) atomic_mb_set(&cpu->exit_request, 0); } - qemu_tcg_wait_io_event(cpu ? cpu : QTAILQ_FIRST(&cpus)); + qemu_tcg_rr_wait_io_event(cpu ? cpu : QTAILQ_FIRST(&cpus)); deal_with_unplugged_cpus(); } @@ -1501,13 +1492,7 @@ static void *qemu_hax_cpu_thread_fn(void *arg) } } - while (cpu_thread_is_idle(cpu)) { - qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex); - } -#ifdef _WIN32 - SleepEx(0, TRUE); -#endif - qemu_wait_io_event_common(cpu); + qemu_wait_io_event(cpu); } return NULL; } @@ -1544,7 +1529,7 @@ static void *qemu_hvf_cpu_thread_fn(void *arg) cpu_handle_guest_debug(cpu); } } - qemu_hvf_wait_io_event(cpu); + qemu_wait_io_event(cpu); } while (!cpu->unplug || cpu_can_run(cpu)); hvf_vcpu_destroy(cpu); @@ -1623,7 +1608,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) } atomic_mb_set(&cpu->exit_request, 0); - qemu_tcg_wait_io_event(cpu); + qemu_wait_io_event(cpu); } return NULL;