Providing a optional mechanism to wait for all VCPU threads be created out of qemu_init_vcpu(), then we can initialize the cpu concurrently on the x86 architecture.
This reduces the time of creating virtual machines. For example, when the haxm is used as the accelerator, cpus_accel->create_vcpu_thread() will cause at least 200ms for each cpu, extremely prolong the boot time. Signed-off-by: Eduardo Habkost <ehabk...@redhat.com> Signed-off-by: eillon <yezhen...@huawei.com> --- hw/i386/x86.c | 3 +++ include/hw/core/cpu.h | 13 +++++++++++++ softmmu/cpus.c | 21 +++++++++++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 6329f90ef9..09afff724a 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -108,6 +108,8 @@ void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, Error **errp) if (!object_property_set_uint(cpu, "apic-id", apic_id, errp)) { goto out; } + + CPU(cpu)->async_init = true; qdev_realize(DEVICE(cpu), NULL, errp); out: @@ -137,6 +139,7 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) for (i = 0; i < ms->smp.cpus; i++) { x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, &error_fatal); } + qemu_wait_all_vcpu_threads_init(); } void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count) diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 8e7552910d..55c2c17d93 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -467,6 +467,12 @@ struct CPUState { /* track IOMMUs whose translations we've cached in the TCG TLB */ GArray *iommu_notifiers; + + /* + * If true, qemu_init_vcpu() will not wait for the VCPU thread to be created + * before returning. + */ + bool async_init; }; typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ; @@ -977,6 +983,13 @@ void start_exclusive(void); */ void end_exclusive(void); +/** + * qemu_wait_all_vcpu_threads_init: + * + * Wait for all VCPU threads to be created. + */ +void qemu_wait_all_vcpu_threads_init(void); + /** * qemu_init_vcpu: * @cpu: The vCPU to initialize. diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 1dc20b9dc3..d76853d356 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -601,6 +601,23 @@ void cpus_register_accel(const CpusAccel *ca) cpus_accel = ca; } +static void qemu_wait_vcpu_thread_init(CPUState *cpu) +{ + while (!cpu->created) { + qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex); + } +} + +void qemu_wait_all_vcpu_threads_init(void) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + printf("***** cpuid: %d\n", cpu->cpu_index); + qemu_wait_vcpu_thread_init(cpu); + } +} + void qemu_init_vcpu(CPUState *cpu) { MachineState *ms = MACHINE(qdev_get_machine()); @@ -622,8 +639,8 @@ void qemu_init_vcpu(CPUState *cpu) g_assert(cpus_accel != NULL && cpus_accel->create_vcpu_thread != NULL); cpus_accel->create_vcpu_thread(cpu); - while (!cpu->created) { - qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex); + if (!cpu->async_init) { + qemu_wait_vcpu_thread_init(cpu); } } -- 2.22.0.windows.1