@@ -77,7 +77,7 @@ void accel_init_ops_interfaces(AccelClass *ac)
/*
* all accelerators need to define ops, providing at least a mandatory
- * non-NULL create_vcpu_thread operation.
+ * non-NULL vcpu_thread_fn operation.
*/
g_assert(ops != NULL);
if (ops->ops_init) {
@@ -18,7 +18,7 @@
#include "qemu/main-loop.h"
#include "hw/core/cpu.h"
-static void *dummy_cpu_thread_fn(void *arg)
+void *dummy_vcpu_thread_fn(void *arg)
{
CPUState *cpu = arg;
sigset_t waitset;
@@ -57,16 +57,3 @@ static void *dummy_cpu_thread_fn(void *arg)
rcu_unregister_thread();
return NULL;
}
-
-void dummy_start_vcpu_thread(CPUState *cpu)
-{
- char thread_name[VCPU_THREAD_NAME_SIZE];
-
- cpu->thread = g_malloc0(sizeof(QemuThread));
- cpu->halt_cond = g_malloc0(sizeof(QemuCond));
- qemu_cond_init(cpu->halt_cond);
- snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/DUMMY",
- cpu->cpu_index);
- qemu_thread_create(cpu->thread, thread_name, dummy_cpu_thread_fn, cpu,
- QEMU_THREAD_JOINABLE);
-}
@@ -442,25 +442,13 @@ static void *hvf_cpu_thread_fn(void *arg)
return NULL;
}
-static void hvf_start_vcpu_thread(CPUState *cpu)
-{
- char thread_name[VCPU_THREAD_NAME_SIZE];
-
- cpu->thread = g_malloc0(sizeof(QemuThread));
- cpu->halt_cond = g_malloc0(sizeof(QemuCond));
- qemu_cond_init(cpu->halt_cond);
-
- snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF",
- cpu->cpu_index);
- qemu_thread_create(cpu->thread, thread_name, hvf_cpu_thread_fn,
- cpu, QEMU_THREAD_JOINABLE);
-}
-
static void hvf_accel_ops_class_init(ObjectClass *oc, void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
- ops->create_vcpu_thread = hvf_start_vcpu_thread;
+ ops->thread_name = "HVF";
+ ops->vcpu_thread_fn = hvf_cpu_thread_fn;
+
ops->kick_vcpu_thread = hvf_kick_vcpu_thread;
ops->synchronize_post_reset = hvf_cpu_synchronize_post_reset;
@@ -61,19 +61,6 @@ static void *kvm_vcpu_thread_fn(void *arg)
return NULL;
}
-static void kvm_start_vcpu_thread(CPUState *cpu)
-{
- char thread_name[VCPU_THREAD_NAME_SIZE];
-
- cpu->thread = g_malloc0(sizeof(QemuThread));
- cpu->halt_cond = g_malloc0(sizeof(QemuCond));
- qemu_cond_init(cpu->halt_cond);
- snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
- cpu->cpu_index);
- qemu_thread_create(cpu->thread, thread_name, kvm_vcpu_thread_fn,
- cpu, QEMU_THREAD_JOINABLE);
-}
-
static bool kvm_vcpu_thread_is_idle(CPUState *cpu)
{
return !kvm_halt_in_kernel();
@@ -88,7 +75,9 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
- ops->create_vcpu_thread = kvm_start_vcpu_thread;
+ ops->thread_name = "KVM";
+ ops->vcpu_thread_fn = kvm_vcpu_thread_fn;
+
ops->cpu_thread_is_idle = kvm_vcpu_thread_is_idle;
ops->cpus_are_resettable = kvm_cpus_are_resettable;
ops->synchronize_post_reset = kvm_cpu_synchronize_post_reset;
@@ -50,7 +50,8 @@ static void qtest_accel_ops_class_init(ObjectClass *oc, void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
- ops->create_vcpu_thread = dummy_start_vcpu_thread;
+ ops->vcpu_thread_fn = dummy_vcpu_thread_fn;
+
ops->get_virtual_clock = qtest_get_virtual_clock;
};
@@ -63,7 +63,7 @@ static void mttcg_force_rcu(Notifier *notify, void *data)
* current CPUState for a given thread.
*/
-static void *mttcg_cpu_thread_fn(void *arg)
+void *mttcg_vcpu_thread_fn(void *arg)
{
MttcgForceRcuNotifier force_rcu;
CPUState *cpu = arg;
@@ -137,23 +137,3 @@ void mttcg_kick_vcpu_thread(CPUState *cpu)
{
cpu_exit(cpu);
}
-
-void mttcg_start_vcpu_thread(CPUState *cpu)
-{
- char thread_name[VCPU_THREAD_NAME_SIZE];
-
- cpu->thread = g_new0(QemuThread, 1);
- cpu->halt_cond = g_malloc0(sizeof(QemuCond));
- qemu_cond_init(cpu->halt_cond);
-
- /* create a thread per vCPU with TCG (MTTCG) */
- snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
- cpu->cpu_index);
-
- qemu_thread_create(cpu->thread, thread_name, mttcg_cpu_thread_fn,
- cpu, QEMU_THREAD_JOINABLE);
-
-#ifdef _WIN32
- cpu->hThread = qemu_thread_get_handle(cpu->thread);
-#endif
-}
@@ -13,7 +13,6 @@
/* kick MTTCG vCPU thread */
void mttcg_kick_vcpu_thread(CPUState *cpu);
-/* start an mttcg vCPU thread */
-void mttcg_start_vcpu_thread(CPUState *cpu);
+void *mttcg_vcpu_thread_fn(void *arg);
#endif /* TCG_CPUS_MTTCG_H */
@@ -148,7 +148,7 @@ static void rr_force_rcu(Notifier *notify, void *data)
* elsewhere.
*/
-static void *rr_cpu_thread_fn(void *arg)
+void *rr_vcpu_thread_fn(void *arg)
{
Notifier force_rcu;
CPUState *cpu = arg;
@@ -279,28 +279,13 @@ bool rr_create_vcpu_thread_precheck(CPUState *cpu)
return !single_tcg_cpu_thread;
}
-void rr_start_vcpu_thread(CPUState *cpu)
+void rr_create_vcpu_thread_postcheck(CPUState *cpu)
{
- char thread_name[VCPU_THREAD_NAME_SIZE];
static QemuCond *single_tcg_halt_cond;
- static QemuThread *single_tcg_cpu_thread;
-
- if (!single_tcg_cpu_thread) {
- cpu->thread = g_new0(QemuThread, 1);
- cpu->halt_cond = g_new0(QemuCond, 1);
- qemu_cond_init(cpu->halt_cond);
-
- /* share a single thread for all cpus with TCG */
- snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG");
- qemu_thread_create(cpu->thread, thread_name,
- rr_cpu_thread_fn,
- cpu, QEMU_THREAD_JOINABLE);
+ if (! single_tcg_cpu_thread) {
single_tcg_halt_cond = cpu->halt_cond;
single_tcg_cpu_thread = cpu->thread;
-#ifdef _WIN32
- cpu->hThread = qemu_thread_get_handle(cpu->thread);
-#endif
} else {
/* we share the thread */
cpu->thread = single_tcg_cpu_thread;
@@ -16,7 +16,9 @@
void rr_kick_vcpu_thread(CPUState *unused);
bool rr_create_vcpu_thread_precheck(CPUState *cpu);
-/* start the round robin vcpu thread */
-void rr_start_vcpu_thread(CPUState *cpu);
+void rr_create_vcpu_thread_postcheck(CPUState *cpu);
+bool rr_destroy_vcpu_thread_precheck(CPUState *cpu);
+
+void *rr_vcpu_thread_fn(void *arg);
#endif /* TCG_CPUS_RR_H */
@@ -95,11 +95,13 @@ void tcg_handle_interrupt(CPUState *cpu, int mask)
static void tcg_accel_ops_init(AccelOpsClass *ops)
{
if (qemu_tcg_mttcg_enabled()) {
- ops->create_vcpu_thread = mttcg_start_vcpu_thread;
+ ops->vcpu_thread_fn = mttcg_vcpu_thread_fn;
ops->kick_vcpu_thread = mttcg_kick_vcpu_thread;
ops->handle_interrupt = tcg_handle_interrupt;
} else {
- ops->create_vcpu_thread = rr_start_vcpu_thread;
+ ops->vcpu_thread_fn = rr_vcpu_thread_fn;
+ ops->create_vcpu_thread_precheck = rr_create_vcpu_thread_precheck;
+ ops->create_vcpu_thread_postcheck = rr_create_vcpu_thread_postcheck;
ops->kick_vcpu_thread = rr_kick_vcpu_thread;
if (icount_enabled()) {
@@ -219,7 +219,7 @@ static void xen_accel_ops_class_init(ObjectClass *oc, void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
- ops->create_vcpu_thread = dummy_start_vcpu_thread;
+ ops->vcpu_thread_fn = dummy_vcpu_thread_fn;
}
static const TypeInfo xen_accel_ops_type = {
@@ -30,7 +30,8 @@ struct AccelOpsClass {
bool (*cpus_are_resettable)(void);
- void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY NON-NULL */
+ const char *thread_name;
+ void *(*vcpu_thread_fn)(void *arg); /* MANDATORY NON-NULL */
/* If non-NULL, return whether common vCPU thread must be created */
bool (*create_vcpu_thread_precheck)(CPUState *cpu);
void (*create_vcpu_thread_postcheck)(CPUState *cpu);
@@ -9,8 +9,8 @@ void cpus_register_accel(const AccelOpsClass *i);
/* accel/dummy-cpus.c */
-/* Create a dummy vcpu for AccelOpsClass->create_vcpu_thread */
-void dummy_start_vcpu_thread(CPUState *);
+/* Create a dummy vcpu for AccelOpsClass->vcpu_thread_fn */
+void *dummy_vcpu_thread_fn(void *arg);
/* interface available for cpus accelerator threads */
@@ -601,6 +601,22 @@ void resume_all_vcpus(void)
}
}
+static void common_vcpu_thread_create(CPUState *cpu)
+{
+ char thread_name[VCPU_THREAD_NAME_SIZE];
+
+ cpu->thread = g_new0(QemuThread, 1);
+ cpu->halt_cond = g_new0(QemuCond, 1);
+ qemu_cond_init(cpu->halt_cond);
+ snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/%s",
+ cpu->cpu_index, cpus_accel->thread_name ?: "DUMMY");
+ qemu_thread_create(cpu->thread, thread_name, cpus_accel->vcpu_thread_fn,
+ cpu, QEMU_THREAD_JOINABLE);
+#ifdef _WIN32
+ cpu->hThread = qemu_thread_get_handle(cpu->thread);
+#endif
+}
+
void cpu_remove_sync(CPUState *cpu)
{
cpu->stop = true;
@@ -614,7 +630,7 @@ void cpu_remove_sync(CPUState *cpu)
void cpus_register_accel(const AccelOpsClass *ops)
{
assert(ops != NULL);
- assert(ops->create_vcpu_thread != NULL); /* mandatory */
+ assert(ops->vcpu_thread_fn != NULL); /* mandatory */
cpus_accel = ops;
}
@@ -636,10 +652,11 @@ void qemu_init_vcpu(CPUState *cpu)
}
/* accelerators all implement the AccelOpsClass */
- g_assert(cpus_accel != NULL && cpus_accel->create_vcpu_thread != NULL);
+ g_assert(cpus_accel != NULL && cpus_accel->vcpu_thread_fn != NULL);
+
if (cpus_accel->create_vcpu_thread_precheck == NULL
|| cpus_accel->create_vcpu_thread_precheck(cpu)) {
- cpus_accel->create_vcpu_thread(cpu);
+ common_vcpu_thread_create(cpu);
}
if (cpus_accel->create_vcpu_thread_postcheck) {
cpus_accel->create_vcpu_thread_postcheck(cpu);
@@ -57,28 +57,12 @@ static void *hax_cpu_thread_fn(void *arg)
return NULL;
}
-static void hax_start_vcpu_thread(CPUState *cpu)
-{
- char thread_name[VCPU_THREAD_NAME_SIZE];
-
- cpu->thread = g_new0(QemuThread, 1);
- cpu->halt_cond = g_new0(QemuCond, 1);
- qemu_cond_init(cpu->halt_cond);
-
- snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HAX",
- cpu->cpu_index);
- qemu_thread_create(cpu->thread, thread_name, hax_cpu_thread_fn,
- cpu, QEMU_THREAD_JOINABLE);
-#ifdef _WIN32
- cpu->hThread = qemu_thread_get_handle(cpu->thread);
-#endif
-}
-
static void hax_accel_ops_class_init(ObjectClass *oc, void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
- ops->create_vcpu_thread = hax_start_vcpu_thread;
+ ops->thread_name = "HAX";
+ ops->vcpu_thread_fn = hax_cpu_thread_fn;
ops->kick_vcpu_thread = hax_kick_vcpu_thread;
ops->synchronize_post_reset = hax_cpu_synchronize_post_reset;
@@ -60,19 +60,6 @@ static void *qemu_nvmm_cpu_thread_fn(void *arg)
return NULL;
}
-static void nvmm_start_vcpu_thread(CPUState *cpu)
-{
- char thread_name[VCPU_THREAD_NAME_SIZE];
-
- cpu->thread = g_new0(QemuThread, 1);
- cpu->halt_cond = g_new0(QemuCond, 1);
- qemu_cond_init(cpu->halt_cond);
- snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/NVMM",
- cpu->cpu_index);
- qemu_thread_create(cpu->thread, thread_name, qemu_nvmm_cpu_thread_fn,
- cpu, QEMU_THREAD_JOINABLE);
-}
-
/*
* Abort the call to run the virtual processor by another thread, and to
* return the control to that thread.
@@ -87,7 +74,9 @@ static void nvmm_accel_ops_class_init(ObjectClass *oc, void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
- ops->create_vcpu_thread = nvmm_start_vcpu_thread;
+ ops->thread_name = "NVMM";
+ ops->vcpu_thread_fn = qemu_nvmm_cpu_thread_fn;
+
ops->kick_vcpu_thread = nvmm_kick_vcpu_thread;
ops->synchronize_post_reset = nvmm_cpu_synchronize_post_reset;
@@ -60,22 +60,6 @@ static void *whpx_cpu_thread_fn(void *arg)
return NULL;
}
-static void whpx_start_vcpu_thread(CPUState *cpu)
-{
- char thread_name[VCPU_THREAD_NAME_SIZE];
-
- cpu->thread = g_new0(QemuThread, 1);
- cpu->halt_cond = g_new0(QemuCond, 1);
- qemu_cond_init(cpu->halt_cond);
- snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/WHPX",
- cpu->cpu_index);
- qemu_thread_create(cpu->thread, thread_name, whpx_cpu_thread_fn,
- cpu, QEMU_THREAD_JOINABLE);
-#ifdef _WIN32
- cpu->hThread = qemu_thread_get_handle(cpu->thread);
-#endif
-}
-
static void whpx_kick_vcpu_thread(CPUState *cpu)
{
if (!qemu_cpu_is_self(cpu)) {
@@ -92,7 +76,9 @@ static void whpx_accel_ops_class_init(ObjectClass *oc, void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
- ops->create_vcpu_thread = whpx_start_vcpu_thread;
+ ops->thread_name = "WHPX";
+ ops->vcpu_thread_fn = whpx_cpu_thread_fn;
+
ops->kick_vcpu_thread = whpx_kick_vcpu_thread;
ops->cpu_thread_is_idle = whpx_vcpu_thread_is_idle;