}
}
+int cpu_is_stopped(CPUState *env)
+{
+ return !vm_running || env->stopped;
+}
+
static void do_vm_stop(int reason)
{
if (vm_running) {
{
if (env->stop)
return 1;
+ if (env->queued_work_first)
+ return 1;
if (env->stopped || !vm_running)
return 0;
if (!env->halted)
static void qemu_event_increment(void)
{
/* Write 8 bytes to be compatible with eventfd. */
- static uint64_t val = 1;
+ static const uint64_t val = 1;
ssize_t ret;
if (io_thread_fd == -1)
return 1;
}
+void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
+{
+ func(data);
+}
+
void resume_all_vcpus(void)
{
}
/* system init */
static QemuCond qemu_system_cond;
static QemuCond qemu_pause_cond;
+static QemuCond qemu_work_cond;
static void tcg_block_io_signals(void);
static void kvm_block_io_signals(CPUState *env);
qemu_cond_broadcast(&qemu_system_cond);
}
+void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
+{
+ struct qemu_work_item wi;
+
+ if (qemu_cpu_self(env)) {
+ func(data);
+ return;
+ }
+
+ wi.func = func;
+ wi.data = data;
+ if (!env->queued_work_first)
+ env->queued_work_first = &wi;
+ else
+ env->queued_work_last->next = &wi;
+ env->queued_work_last = &wi;
+ wi.next = NULL;
+ wi.done = false;
+
+ qemu_cpu_kick(env);
+ while (!wi.done) {
+ CPUState *self_env = cpu_single_env;
+
+ qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex);
+ cpu_single_env = self_env;
+ }
+}
+
+static void flush_queued_work(CPUState *env)
+{
+ struct qemu_work_item *wi;
+
+ if (!env->queued_work_first)
+ return;
+
+ while ((wi = env->queued_work_first)) {
+ env->queued_work_first = wi->next;
+ wi->func(wi->data);
+ wi->done = true;
+ }
+ env->queued_work_last = NULL;
+ qemu_cond_broadcast(&qemu_work_cond);
+}
+
static void qemu_wait_io_event_common(CPUState *env)
{
if (env->stop) {
env->stopped = 1;
qemu_cond_signal(&qemu_pause_cond);
}
+ flush_queued_work(env);
}
static void qemu_wait_io_event(CPUState *env)
{
CPUState *env = _env;
qemu_cond_broadcast(env->halt_cond);
- if (kvm_enabled())
- qemu_thread_signal(env->thread, SIG_IPI);
+ qemu_thread_signal(env->thread, SIG_IPI);
}
int qemu_cpu_self(void *_env)
{
if (cpu_single_env)
cpu_exit(cpu_single_env);
+ exit_request = 1;
}
static void tcg_block_io_signals(void)
pthread_sigmask(SIG_BLOCK, &set, NULL);
}
-static void qemu_signal_lock(unsigned int msecs)
-{
- qemu_mutex_lock(&qemu_fair_mutex);
-
- while (qemu_mutex_trylock(&qemu_global_mutex)) {
- qemu_thread_signal(tcg_cpu_thread, SIG_IPI);
- if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
- break;
- }
- qemu_mutex_unlock(&qemu_fair_mutex);
-}
-
void qemu_mutex_lock_iothread(void)
{
if (kvm_enabled()) {
qemu_mutex_lock(&qemu_fair_mutex);
qemu_mutex_lock(&qemu_global_mutex);
qemu_mutex_unlock(&qemu_fair_mutex);
- } else
- qemu_signal_lock(100);
+ } else {
+ qemu_mutex_lock(&qemu_fair_mutex);
+ if (qemu_mutex_trylock(&qemu_global_mutex)) {
+ qemu_thread_signal(tcg_cpu_thread, SIG_IPI);
+ qemu_mutex_lock(&qemu_global_mutex);
+ }
+ qemu_mutex_unlock(&qemu_fair_mutex);
+ }
}
void qemu_mutex_unlock_iothread(void)
while (penv) {
penv->stop = 1;
- qemu_thread_signal(penv->thread, SIG_IPI);
qemu_cpu_kick(penv);
penv = (CPUState *)penv->next_cpu;
}
qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
penv = first_cpu;
while (penv) {
- qemu_thread_signal(penv->thread, SIG_IPI);
+ qemu_cpu_kick(penv);
penv = (CPUState *)penv->next_cpu;
}
}
while (penv) {
penv->stop = 0;
penv->stopped = 0;
- qemu_thread_signal(penv->thread, SIG_IPI);
qemu_cpu_kick(penv);
penv = (CPUState *)penv->next_cpu;
}
}
return qemu_icount_bias + (icount << icount_time_shift);
}
+
+void list_cpus(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+ const char *optarg)
+{
+ /* XXX: implement xxx_cpu_list for targets that still miss it */
+#if defined(cpu_list_id)
+ cpu_list_id(f, cpu_fprintf, optarg);
+#elif defined(cpu_list)
+ cpu_list(f, cpu_fprintf); /* deprecated */
+#endif
+}