static void *kvm_cpu_thread_fn(void *arg) { CPUState *env = arg; qemu_mutex_lock(&qemu_global_mutex); qemu_thread_self(env->thread); if (kvm_enabled()) kvm_init_vcpu(env); kvm_init_ipi(env); /* signal CPU creation */ env->created = 1; qemu_cond_signal(&qemu_cpu_cond); /* and wait for machine initialization */ while (!qemu_system_ready) qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100); while (1) { if (cpu_can_run(env)) qemu_cpu_exec(env); qemu_kvm_wait_io_event(env); } return NULL; }
static void qemu_kvm_wait_io_event(CPUState *env) { while (!cpu_has_work(env)) qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000); qemu_kvm_eat_signal(env, 0); qemu_wait_io_event_common(env); }
static void kvm_start_vcpu(CPUState *env) { env->thread = qemu_mallocz(sizeof(QemuThread)); env->halt_cond = qemu_mallocz(sizeof(QemuCond)); qemu_cond_init(env->halt_cond); qemu_thread_create(env->thread, kvm_cpu_thread_fn, env); while (env->created == 0) qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100); }
static void tcg_init_vcpu(void *_env) { CPUState *env = _env; /* share a single thread for all cpus with TCG */ if (!tcg_cpu_thread) { env->thread = qemu_mallocz(sizeof(QemuThread)); env->halt_cond = qemu_mallocz(sizeof(QemuCond)); qemu_cond_init(env->halt_cond); qemu_thread_create(env->thread, tcg_cpu_thread_fn, env); while (env->created == 0) qemu_cond_timedwait(&qemu_cpu_cond, &qemu_global_mutex, 100); tcg_cpu_thread = env->thread; tcg_halt_cond = env->halt_cond; } else { env->thread = tcg_cpu_thread; env->halt_cond = tcg_halt_cond; } }
static void qemu_wait_io_event(CPUState *env) { while (!tcg_has_work()) qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000); qemu_mutex_unlock(&qemu_global_mutex); /* * Users of qemu_global_mutex can be starved, having no chance * to acquire it since this path will get to it first. * So use another lock to provide fairness. */ qemu_mutex_lock(&qemu_fair_mutex); qemu_mutex_unlock(&qemu_fair_mutex); qemu_mutex_lock(&qemu_global_mutex); qemu_wait_io_event_common(env); }
void pause_all_vcpus(void) { CPUState *penv = first_cpu; while (penv) { penv->stop = 1; qemu_cpu_kick(penv); penv = (CPUState *)penv->next_cpu; } while (!all_vcpus_paused()) { qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100); penv = first_cpu; while (penv) { qemu_cpu_kick(penv); penv = (CPUState *)penv->next_cpu; } } }
static void qemu_tcg_wait_io_event(void) { CPUState *env; while (!any_cpu_has_work()) qemu_cond_timedwait(tcg_halt_cond, &qemu_global_mutex, 1000); qemu_mutex_unlock(&qemu_global_mutex); /* * Users of qemu_global_mutex can be starved, having no chance * to acquire it since this path will get to it first. * So use another lock to provide fairness. */ qemu_mutex_lock(&qemu_fair_mutex); qemu_mutex_unlock(&qemu_fair_mutex); qemu_mutex_lock(&qemu_global_mutex); for (env = first_cpu; env != NULL; env = env->next_cpu) { qemu_wait_io_event_common(env); } }
static void *tcg_cpu_thread_fn(void *arg) { CPUState *env = arg; block_io_signals(); qemu_thread_self(env->thread); /* signal CPU creation */ qemu_mutex_lock(&qemu_global_mutex); for (env = first_cpu; env != NULL; env = env->next_cpu) env->created = 1; qemu_cond_signal(&qemu_cpu_cond); /* and wait for machine initialization */ while (!qemu_system_ready) qemu_cond_timedwait(&qemu_system_cond, &qemu_global_mutex, 100); while (1) { tcg_cpu_exec(); qemu_wait_io_event(cur_cpu); } return NULL; }