aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2011-06-01 16:14:53 +0200
committerDavid 'Digit' Turner <digit@android.com>2011-06-01 17:08:19 +0200
commit23ca2ae2bf303236eb6b1e0beb126ec05c6c23bf (patch)
treec77aca9a122561872a55b2065bb54ca321a5dd10
parentc1ac40a3f493bebe160a441faf36cc9b28b9f205 (diff)
downloadexternal_qemu-23ca2ae2bf303236eb6b1e0beb126ec05c6c23bf.zip
external_qemu-23ca2ae2bf303236eb6b1e0beb126ec05c6c23bf.tar.gz
external_qemu-23ca2ae2bf303236eb6b1e0beb126ec05c6c23bf.tar.bz2
vl-android.c: move cpu functions to cpus.c
Change-Id: Ib422f24224c2e75dd126689c67dbbb187d7c1670
-rw-r--r--Makefile.target2
-rw-r--r--cpus.c629
-rw-r--r--cpus.h36
-rw-r--r--vl-android.c733
-rw-r--r--vl.c661
5 files changed, 675 insertions, 1386 deletions
diff --git a/Makefile.target b/Makefile.target
index aa3824b..190219f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -248,6 +248,7 @@ LOCAL_LDLIBS += \
LOCAL_SRC_FILES := \
audio/audio.c \
+ cpus.c \
disas.c \
dma-helpers.c \
gdbstub.c \
@@ -325,6 +326,7 @@ LOCAL_CFLAGS += \
LOCAL_SRC_FILES := \
audio/audio.c \
+ cpus.c \
disas.c \
dma-helpers.c \
gdbstub.c \
diff --git a/cpus.c b/cpus.c
new file mode 100644
index 0000000..470eb32
--- /dev/null
+++ b/cpus.c
@@ -0,0 +1,629 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "config-host.h"
+
+#include "monitor.h"
+#include "sysemu.h"
+#include "gdbstub.h"
+#include "dma.h"
+#include "kvm.h"
+
+#include "cpus.h"
+
+static CPUState *cur_cpu;
+static CPUState *next_cpu;
+
+/***********************************************************/
+void hw_error(const char *fmt, ...)
+{
+ va_list ap;
+ CPUState *env;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "qemu: hardware error: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ for(env = first_cpu; env != NULL; env = env->next_cpu) {
+ fprintf(stderr, "CPU #%d:\n", env->cpu_index);
+#ifdef TARGET_I386
+ cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
+#else
+ cpu_dump_state(env, stderr, fprintf, 0);
+#endif
+ }
+ va_end(ap);
+ abort();
+}
+
+static void do_vm_stop(int reason)
+{
+ if (vm_running) {
+ cpu_disable_ticks();
+ vm_running = 0;
+ pause_all_vcpus();
+ vm_state_notify(0, reason);
+ }
+}
+
+static int cpu_can_run(CPUState *env)
+{
+ if (env->stop)
+ return 0;
+ if (env->stopped)
+ return 0;
+ return 1;
+}
+
+static int cpu_has_work(CPUState *env)
+{
+ if (env->stop)
+ return 1;
+ if (env->stopped)
+ return 0;
+ if (!env->halted)
+ return 1;
+ if (qemu_cpu_has_work(env))
+ return 1;
+ return 0;
+}
+
+int tcg_has_work(void)
+{
+ CPUState *env;
+
+ for (env = first_cpu; env != NULL; env = env->next_cpu)
+ if (cpu_has_work(env))
+ return 1;
+ return 0;
+}
+
+#ifndef _WIN32
+static int io_thread_fd = -1;
+
+#if 0
+static void qemu_event_increment(void)
+{
+ static const char byte = 0;
+
+ if (io_thread_fd == -1)
+ return;
+
+ write(io_thread_fd, &byte, sizeof(byte));
+}
+#endif
+
+static void qemu_event_read(void *opaque)
+{
+ int fd = (unsigned long)opaque;
+ ssize_t len;
+
+ /* Drain the notify pipe */
+ do {
+ char buffer[512];
+ len = read(fd, buffer, sizeof(buffer));
+ } while ((len == -1 && errno == EINTR) || len > 0);
+}
+
+static int qemu_event_init(void)
+{
+ int err;
+ int fds[2];
+
+ err = pipe(fds);
+ if (err == -1)
+ return -errno;
+
+ err = fcntl_setfl(fds[0], O_NONBLOCK);
+ if (err < 0)
+ goto fail;
+
+ err = fcntl_setfl(fds[1], O_NONBLOCK);
+ if (err < 0)
+ goto fail;
+
+ qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
+ (void *)(unsigned long)fds[0]);
+
+ io_thread_fd = fds[1];
+ return 0;
+
+fail:
+ close(fds[0]);
+ close(fds[1]);
+ return err;
+}
+#else
+HANDLE qemu_event_handle;
+
+static void dummy_event_handler(void *opaque)
+{
+}
+
+static int qemu_event_init(void)
+{
+ qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!qemu_event_handle) {
+ perror("Failed CreateEvent");
+ return -1;
+ }
+ qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
+ return 0;
+}
+
+#if 0
+static void qemu_event_increment(void)
+{
+ SetEvent(qemu_event_handle);
+}
+#endif
+#endif
+
+#ifndef CONFIG_IOTHREAD
+int qemu_init_main_loop(void)
+{
+ return qemu_event_init();
+}
+
+void qemu_init_vcpu(void *_env)
+{
+ CPUState *env = _env;
+
+ if (kvm_enabled())
+ kvm_init_vcpu(env);
+ return;
+}
+
+int qemu_cpu_self(void *env)
+{
+ return 1;
+}
+
+void resume_all_vcpus(void)
+{
+}
+
+void pause_all_vcpus(void)
+{
+}
+
+void qemu_cpu_kick(void *env)
+{
+ return;
+}
+
+void qemu_notify_event(void)
+{
+ CPUState *env = cpu_single_env;
+
+ if (env) {
+ cpu_exit(env);
+#ifdef USE_KQEMU
+ if (env->kqemu_enabled)
+ kqemu_cpu_interrupt(env);
+#endif
+ }
+}
+
+void qemu_mutex_lock_iothread(void)
+{
+}
+
+void qemu_mutex_unlock_iothread(void)
+{
+}
+
+void vm_stop(int reason)
+{
+ do_vm_stop(reason);
+}
+
+#else /* CONFIG_IOTHREAD */
+
+#include "qemu-thread.h"
+
+QemuMutex qemu_global_mutex;
+static QemuMutex qemu_fair_mutex;
+
+static QemuThread io_thread;
+
+static QemuThread *tcg_cpu_thread;
+static QemuCond *tcg_halt_cond;
+
+static int qemu_system_ready;
+/* cpu creation */
+static QemuCond qemu_cpu_cond;
+/* system init */
+static QemuCond qemu_system_cond;
+static QemuCond qemu_pause_cond;
+
+static void block_io_signals(void);
+static void unblock_io_signals(void);
+static int tcg_has_work(void);
+
+int qemu_init_main_loop(void)
+{
+ int ret;
+
+ ret = qemu_event_init();
+ if (ret)
+ return ret;
+
+ qemu_cond_init(&qemu_pause_cond);
+ qemu_mutex_init(&qemu_fair_mutex);
+ qemu_mutex_init(&qemu_global_mutex);
+ qemu_mutex_lock(&qemu_global_mutex);
+
+ unblock_io_signals();
+ qemu_thread_self(&io_thread);
+
+ return 0;
+}
+
+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);
+ if (env->stop) {
+ env->stop = 0;
+ env->stopped = 1;
+ qemu_cond_signal(&qemu_pause_cond);
+ }
+}
+
+static int qemu_cpu_exec(CPUState *env);
+
+static void *kvm_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);
+ 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_wait_io_event(env);
+ }
+
+ return NULL;
+}
+
+static void tcg_cpu_exec(void);
+
+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;
+}
+
+void qemu_cpu_kick(void *_env)
+{
+ CPUState *env = _env;
+ qemu_cond_broadcast(env->halt_cond);
+ if (kvm_enabled())
+ qemu_thread_signal(env->thread, SIGUSR1);
+}
+
+int qemu_cpu_self(void *env)
+{
+ return (cpu_single_env != NULL);
+}
+
+static void cpu_signal(int sig)
+{
+ if (cpu_single_env)
+ cpu_exit(cpu_single_env);
+}
+
+static void block_io_signals(void)
+{
+ sigset_t set;
+ struct sigaction sigact;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR2);
+ sigaddset(&set, SIGIO);
+ sigaddset(&set, SIGALRM);
+ pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR1);
+ pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = cpu_signal;
+ sigaction(SIGUSR1, &sigact, NULL);
+}
+
+static void unblock_io_signals(void)
+{
+ sigset_t set;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR2);
+ sigaddset(&set, SIGIO);
+ sigaddset(&set, SIGALRM);
+ pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR1);
+ 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, SIGUSR1);
+ 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);
+}
+
+void qemu_mutex_unlock_iothread(void)
+{
+ qemu_mutex_unlock(&qemu_global_mutex);
+}
+
+static int all_vcpus_paused(void)
+{
+ CPUState *penv = first_cpu;
+
+ while (penv) {
+ if (!penv->stopped)
+ return 0;
+ penv = (CPUState *)penv->next_cpu;
+ }
+
+ return 1;
+}
+
+void pause_all_vcpus(void)
+{
+ CPUState *penv = first_cpu;
+
+ while (penv) {
+ penv->stop = 1;
+ qemu_thread_signal(penv->thread, SIGUSR1);
+ 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_thread_signal(penv->thread, SIGUSR1);
+ penv = (CPUState *)penv->next_cpu;
+ }
+ }
+}
+
+void resume_all_vcpus(void)
+{
+ CPUState *penv = first_cpu;
+
+ while (penv) {
+ penv->stop = 0;
+ penv->stopped = 0;
+ qemu_thread_signal(penv->thread, SIGUSR1);
+ qemu_cpu_kick(penv);
+ penv = (CPUState *)penv->next_cpu;
+ }
+}
+
+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 kvm_start_vcpu(CPUState *env)
+{
+#if 0
+ kvm_init_vcpu(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);
+#endif
+}
+
+void qemu_init_vcpu(void *_env)
+{
+ CPUState *env = _env;
+
+ if (kvm_enabled())
+ kvm_start_vcpu(env);
+ else
+ tcg_init_vcpu(env);
+}
+
+void qemu_notify_event(void)
+{
+ qemu_event_increment();
+}
+
+void vm_stop(int reason)
+{
+ QemuThread me;
+ qemu_thread_self(&me);
+
+ if (!qemu_thread_equal(&me, &io_thread)) {
+ qemu_system_vmstop_request(reason);
+ /*
+ * FIXME: should not return to device code in case
+ * vm_stop() has been requested.
+ */
+ if (cpu_single_env) {
+ cpu_exit(cpu_single_env);
+ cpu_single_env->stop = 1;
+ }
+ return;
+ }
+ do_vm_stop(reason);
+}
+
+#endif
+
+static int qemu_cpu_exec(CPUState *env)
+{
+ int ret;
+#ifdef CONFIG_PROFILER
+ int64_t ti;
+#endif
+
+#ifdef CONFIG_PROFILER
+ ti = profile_getclock();
+#endif
+ if (use_icount) {
+ int64_t count;
+ int decr;
+ qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
+ env->icount_decr.u16.low = 0;
+ env->icount_extra = 0;
+ count = qemu_next_icount_deadline();
+ count = (count + (1 << icount_time_shift) - 1)
+ >> icount_time_shift;
+ qemu_icount += count;
+ decr = (count > 0xffff) ? 0xffff : count;
+ count -= decr;
+ env->icount_decr.u16.low = decr;
+ env->icount_extra = count;
+ }
+#ifdef CONFIG_TRACE
+ if (tbflush_requested) {
+ tbflush_requested = 0;
+ tb_flush(env);
+ return EXCP_INTERRUPT;
+ }
+#endif
+
+
+ ret = cpu_exec(env);
+#ifdef CONFIG_PROFILER
+ qemu_time += profile_getclock() - ti;
+#endif
+ if (use_icount) {
+ /* Fold pending instructions back into the
+ instruction counter, and clear the interrupt flag. */
+ qemu_icount -= (env->icount_decr.u16.low
+ + env->icount_extra);
+ env->icount_decr.u32 = 0;
+ env->icount_extra = 0;
+ }
+ return ret;
+}
+
+void tcg_cpu_exec(void)
+{
+ int ret = 0;
+
+ if (next_cpu == NULL)
+ next_cpu = first_cpu;
+ for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
+ CPUState *env = cur_cpu = next_cpu;
+
+ if (!vm_running)
+ break;
+ if (qemu_timer_alarm_pending()) {
+ break;
+ }
+ if (cpu_can_run(env))
+ ret = qemu_cpu_exec(env);
+ if (ret == EXCP_DEBUG) {
+ gdb_set_stop_cpu(env);
+ debug_requested = 1;
+ break;
+ }
+ }
+}
+
diff --git a/cpus.h b/cpus.h
new file mode 100644
index 0000000..c25f35e
--- /dev/null
+++ b/cpus.h
@@ -0,0 +1,36 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef QEMU_CPUS_H
+#define QEMU_CPUS_H
+
+void tcg_cpu_exec(void);
+void vm_state_notify(int running, int reason);
+extern int tbflush_requested;
+extern int debug_requested;
+
+void resume_all_vcpus(void);
+void pause_all_vcpus(void);
+int qemu_init_main_loop(void);
+
+#endif /* QEMU_CPUS_H */
diff --git a/vl-android.c b/vl-android.c
index 18fdb40..c85aff5 100644
--- a/vl-android.c
+++ b/vl-android.c
@@ -162,6 +162,7 @@
#define memalign(align, size) malloc(size)
#endif
+#include "cpus.h"
#ifdef CONFIG_COCOA
#undef main
@@ -329,8 +330,6 @@ int nb_numa_nodes;
uint64_t node_mem[MAX_NODES];
uint64_t node_cpumask[MAX_NODES];
-static CPUState *cur_cpu;
-static CPUState *next_cpu;
static QEMUTimer *nographic_timer;
uint8_t qemu_uuid[16];
@@ -562,28 +561,6 @@ FILE* rotate_qemu_log(FILE* old_log_fd, const char* filename) {
return new_log_fd;
}
-/***********************************************************/
-void hw_error(const char *fmt, ...)
-{
- va_list ap;
- CPUState *env;
-
- va_start(ap, fmt);
- fprintf(stderr, "qemu: hardware error: ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- for(env = first_cpu; env != NULL; env = env->next_cpu) {
- fprintf(stderr, "CPU #%d:\n", env->cpu_index);
-#ifdef TARGET_I386
- cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
-#else
- cpu_dump_state(env, stderr, fprintf, 0);
-#endif
- }
- va_end(ap);
- abort();
-}
-
/***************/
/* ballooning */
@@ -648,7 +625,7 @@ int qemu_timedate_diff(struct tm *tm)
#ifdef CONFIG_TRACE
-static int tbflush_requested;
+int tbflush_requested;
static int exit_requested;
void start_tracing()
@@ -1717,86 +1694,6 @@ void pcmcia_info(Monitor *mon)
"Empty");
}
-#ifdef _WIN32
-/***********************************************************/
-/* Polling handling */
-
-typedef struct PollingEntry {
- PollingFunc *func;
- void *opaque;
- struct PollingEntry *next;
-} PollingEntry;
-
-static PollingEntry *first_polling_entry;
-
-int qemu_add_polling_cb(PollingFunc *func, void *opaque)
-{
- PollingEntry **ppe, *pe;
- pe = qemu_mallocz(sizeof(PollingEntry));
- pe->func = func;
- pe->opaque = opaque;
- for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
- *ppe = pe;
- return 0;
-}
-
-void qemu_del_polling_cb(PollingFunc *func, void *opaque)
-{
- PollingEntry **ppe, *pe;
- for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
- pe = *ppe;
- if (pe->func == func && pe->opaque == opaque) {
- *ppe = pe->next;
- qemu_free(pe);
- break;
- }
- }
-}
-
-/***********************************************************/
-/* Wait objects support */
-typedef struct WaitObjects {
- int num;
- HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
- WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
- void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
-} WaitObjects;
-
-static WaitObjects wait_objects = {0};
-
-int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
- WaitObjects *w = &wait_objects;
-
- if (w->num >= MAXIMUM_WAIT_OBJECTS)
- return -1;
- w->events[w->num] = handle;
- w->func[w->num] = func;
- w->opaque[w->num] = opaque;
- w->num++;
- return 0;
-}
-
-void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
- int i, found;
- WaitObjects *w = &wait_objects;
-
- found = 0;
- for (i = 0; i < w->num; i++) {
- if (w->events[i] == handle)
- found = 1;
- if (found) {
- w->events[i] = w->events[i + 1];
- w->func[i] = w->func[i + 1];
- w->opaque[i] = w->opaque[i + 1];
- }
- }
- if (found)
- w->num--;
-}
-#endif
-
/***********************************************************/
/* ram save/restore */
@@ -2207,7 +2104,7 @@ void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
qemu_free (e);
}
-static void vm_state_notify(int running, int reason)
+void vm_state_notify(int running, int reason)
{
VMChangeStateEntry *e;
@@ -2216,9 +2113,6 @@ static void vm_state_notify(int running, int reason)
}
}
-static void resume_all_vcpus(void);
-static void pause_all_vcpus(void);
-
void vm_start(void)
{
if (!vm_running) {
@@ -2244,7 +2138,7 @@ static int reset_requested;
static int shutdown_requested, shutdown_signal = -1;
static pid_t shutdown_pid;
static int powerdown_requested;
-static int debug_requested;
+int debug_requested;
static int vmstop_requested;
int qemu_shutdown_requested(void)
@@ -2282,16 +2176,6 @@ static int qemu_vmstop_requested(void)
return r;
}
-static void do_vm_stop(int reason)
-{
- if (vm_running) {
- cpu_disable_ticks();
- vm_running = 0;
- pause_all_vcpus();
- vm_state_notify(0, reason);
- }
-}
-
void qemu_register_reset(QEMUResetHandler *func, int order, void *opaque)
{
QEMUResetEntry **pre, *re;
@@ -2355,517 +2239,6 @@ static void qemu_system_vmstop_request(int reason)
}
#endif
-#ifndef _WIN32
-static int io_thread_fd = -1;
-
-#if 0
-static void qemu_event_increment(void)
-{
- static const char byte = 0;
-
- if (io_thread_fd == -1)
- return;
-
- write(io_thread_fd, &byte, sizeof(byte));
-}
-#endif
-
-static void qemu_event_read(void *opaque)
-{
- int fd = (unsigned long)opaque;
- ssize_t len;
-
- /* Drain the notify pipe */
- do {
- char buffer[512];
- len = read(fd, buffer, sizeof(buffer));
- } while ((len == -1 && errno == EINTR) || len > 0);
-}
-
-static int qemu_event_init(void)
-{
- int err;
- int fds[2];
-
- err = pipe(fds);
- if (err == -1)
- return -errno;
-
- err = fcntl_setfl(fds[0], O_NONBLOCK);
- if (err < 0)
- goto fail;
-
- err = fcntl_setfl(fds[1], O_NONBLOCK);
- if (err < 0)
- goto fail;
-
- qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
- (void *)(unsigned long)fds[0]);
-
- io_thread_fd = fds[1];
- return 0;
-
-fail:
- close(fds[0]);
- close(fds[1]);
- return err;
-}
-#else
-HANDLE qemu_event_handle;
-
-static void dummy_event_handler(void *opaque)
-{
-}
-
-static int qemu_event_init(void)
-{
- qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (!qemu_event_handle) {
- perror("Failed CreateEvent");
- return -1;
- }
- qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
- return 0;
-}
-
-#if 0
-static void qemu_event_increment(void)
-{
- SetEvent(qemu_event_handle);
-}
-#endif
-#endif
-
-static int cpu_can_run(CPUState *env)
-{
- if (env->stop)
- return 0;
- if (env->stopped)
- return 0;
- return 1;
-}
-
-#ifndef CONFIG_IOTHREAD
-static int qemu_init_main_loop(void)
-{
- return qemu_event_init();
-}
-
-void qemu_init_vcpu(void *_env)
-{
- CPUState *env = _env;
-
- if (kvm_enabled())
- kvm_init_vcpu(env);
- return;
-}
-
-int qemu_cpu_self(void *env)
-{
- return 1;
-}
-
-static void resume_all_vcpus(void)
-{
-}
-
-static void pause_all_vcpus(void)
-{
-}
-
-void qemu_cpu_kick(void *env)
-{
- return;
-}
-
-void qemu_notify_event(void)
-{
- CPUState *env = cpu_single_env;
-
- if (env) {
- cpu_exit(env);
-#ifdef USE_KQEMU
- if (env->kqemu_enabled)
- kqemu_cpu_interrupt(env);
-#endif
- }
-}
-
-#define qemu_mutex_lock_iothread() do { } while (0)
-#define qemu_mutex_unlock_iothread() do { } while (0)
-
-void vm_stop(int reason)
-{
- do_vm_stop(reason);
-}
-
-#else /* CONFIG_IOTHREAD */
-
-#include "qemu-thread.h"
-
-QemuMutex qemu_global_mutex;
-static QemuMutex qemu_fair_mutex;
-
-static QemuThread io_thread;
-
-static QemuThread *tcg_cpu_thread;
-static QemuCond *tcg_halt_cond;
-
-static int qemu_system_ready;
-/* cpu creation */
-static QemuCond qemu_cpu_cond;
-/* system init */
-static QemuCond qemu_system_cond;
-static QemuCond qemu_pause_cond;
-
-static void block_io_signals(void);
-static void unblock_io_signals(void);
-static int tcg_has_work(void);
-
-static int qemu_init_main_loop(void)
-{
- int ret;
-
- ret = qemu_event_init();
- if (ret)
- return ret;
-
- qemu_cond_init(&qemu_pause_cond);
- qemu_mutex_init(&qemu_fair_mutex);
- qemu_mutex_init(&qemu_global_mutex);
- qemu_mutex_lock(&qemu_global_mutex);
-
- unblock_io_signals();
- qemu_thread_self(&io_thread);
-
- return 0;
-}
-
-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);
- if (env->stop) {
- env->stop = 0;
- env->stopped = 1;
- qemu_cond_signal(&qemu_pause_cond);
- }
-}
-
-static int qemu_cpu_exec(CPUState *env);
-
-static void *kvm_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);
- 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_wait_io_event(env);
- }
-
- return NULL;
-}
-
-static void tcg_cpu_exec(void);
-
-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;
-}
-
-void qemu_cpu_kick(void *_env)
-{
- CPUState *env = _env;
- qemu_cond_broadcast(env->halt_cond);
- if (kvm_enabled())
- qemu_thread_signal(env->thread, SIGUSR1);
-}
-
-int qemu_cpu_self(void *env)
-{
- return (cpu_single_env != NULL);
-}
-
-static void cpu_signal(int sig)
-{
- if (cpu_single_env)
- cpu_exit(cpu_single_env);
-}
-
-static void block_io_signals(void)
-{
- sigset_t set;
- struct sigaction sigact;
-
- sigemptyset(&set);
- sigaddset(&set, SIGUSR2);
- sigaddset(&set, SIGIO);
- sigaddset(&set, SIGALRM);
- pthread_sigmask(SIG_BLOCK, &set, NULL);
-
- sigemptyset(&set);
- sigaddset(&set, SIGUSR1);
- pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-
- memset(&sigact, 0, sizeof(sigact));
- sigact.sa_handler = cpu_signal;
- sigaction(SIGUSR1, &sigact, NULL);
-}
-
-static void unblock_io_signals(void)
-{
- sigset_t set;
-
- sigemptyset(&set);
- sigaddset(&set, SIGUSR2);
- sigaddset(&set, SIGIO);
- sigaddset(&set, SIGALRM);
- pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-
- sigemptyset(&set);
- sigaddset(&set, SIGUSR1);
- 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, SIGUSR1);
- 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);
-}
-
-void qemu_mutex_unlock_iothread(void)
-{
- qemu_mutex_unlock(&qemu_global_mutex);
-}
-
-static int all_vcpus_paused(void)
-{
- CPUState *penv = first_cpu;
-
- while (penv) {
- if (!penv->stopped)
- return 0;
- penv = (CPUState *)penv->next_cpu;
- }
-
- return 1;
-}
-
-static void pause_all_vcpus(void)
-{
- CPUState *penv = first_cpu;
-
- while (penv) {
- penv->stop = 1;
- qemu_thread_signal(penv->thread, SIGUSR1);
- 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_thread_signal(penv->thread, SIGUSR1);
- penv = (CPUState *)penv->next_cpu;
- }
- }
-}
-
-static void resume_all_vcpus(void)
-{
- CPUState *penv = first_cpu;
-
- while (penv) {
- penv->stop = 0;
- penv->stopped = 0;
- qemu_thread_signal(penv->thread, SIGUSR1);
- qemu_cpu_kick(penv);
- penv = (CPUState *)penv->next_cpu;
- }
-}
-
-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 kvm_start_vcpu(CPUState *env)
-{
-#if 0
- kvm_init_vcpu(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);
-#endif
-}
-
-void qemu_init_vcpu(void *_env)
-{
- CPUState *env = _env;
-
- if (kvm_enabled())
- kvm_start_vcpu(env);
- else
- tcg_init_vcpu(env);
-}
-
-void qemu_notify_event(void)
-{
- qemu_event_increment();
-}
-
-void vm_stop(int reason)
-{
- QemuThread me;
- qemu_thread_self(&me);
-
- if (!qemu_thread_equal(&me, &io_thread)) {
- qemu_system_vmstop_request(reason);
- /*
- * FIXME: should not return to device code in case
- * vm_stop() has been requested.
- */
- if (cpu_single_env) {
- cpu_exit(cpu_single_env);
- cpu_single_env->stop = 1;
- }
- return;
- }
- do_vm_stop(reason);
-}
-
-#endif
-
-
-#ifdef _WIN32
-static void host_main_loop_wait(int *timeout)
-{
- int ret, ret2, i;
- PollingEntry *pe;
-
-
- /* XXX: need to suppress polling by better using win32 events */
- ret = 0;
- for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
- ret |= pe->func(pe->opaque);
- }
- if (ret == 0) {
- int err;
- WaitObjects *w = &wait_objects;
-
- ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
- if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
- if (w->func[ret - WAIT_OBJECT_0])
- w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
-
- /* Check for additional signaled events */
- for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-
- /* Check if event is signaled */
- ret2 = WaitForSingleObject(w->events[i], 0);
- if(ret2 == WAIT_OBJECT_0) {
- if (w->func[i])
- w->func[i](w->opaque[i]);
- } else if (ret2 == WAIT_TIMEOUT) {
- } else {
- err = GetLastError();
- fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
- }
- }
- } else if (ret == WAIT_TIMEOUT) {
- } else {
- err = GetLastError();
- fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
- }
- }
-
- *timeout = 0;
-}
-#else
-static void host_main_loop_wait(int *timeout)
-{
-}
-#endif
-
void main_loop_wait(int timeout)
{
fd_set rfds, wfds, xfds;
@@ -2874,7 +2247,7 @@ void main_loop_wait(int timeout)
qemu_bh_update_timeout(&timeout);
- host_main_loop_wait(&timeout);
+ os_host_main_loop_wait(&timeout);
tv.tv_sec = timeout / 1000;
@@ -2914,102 +2287,6 @@ void main_loop_wait(int timeout)
}
-static int qemu_cpu_exec(CPUState *env)
-{
- int ret;
-#ifdef CONFIG_PROFILER
- int64_t ti;
-#endif
-
-#ifdef CONFIG_PROFILER
- ti = profile_getclock();
-#endif
- if (use_icount) {
- int64_t count;
- int decr;
- qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
- env->icount_decr.u16.low = 0;
- env->icount_extra = 0;
- count = qemu_next_icount_deadline();
- count = (count + (1 << icount_time_shift) - 1)
- >> icount_time_shift;
- qemu_icount += count;
- decr = (count > 0xffff) ? 0xffff : count;
- count -= decr;
- env->icount_decr.u16.low = decr;
- env->icount_extra = count;
- }
-#ifdef CONFIG_TRACE
- if (tbflush_requested) {
- tbflush_requested = 0;
- tb_flush(env);
- return EXCP_INTERRUPT;
- }
-#endif
-
-
- ret = cpu_exec(env);
-#ifdef CONFIG_PROFILER
- qemu_time += profile_getclock() - ti;
-#endif
- if (use_icount) {
- /* Fold pending instructions back into the
- instruction counter, and clear the interrupt flag. */
- qemu_icount -= (env->icount_decr.u16.low
- + env->icount_extra);
- env->icount_decr.u32 = 0;
- env->icount_extra = 0;
- }
- return ret;
-}
-
-static void tcg_cpu_exec(void)
-{
- int ret = 0;
-
- if (next_cpu == NULL)
- next_cpu = first_cpu;
- for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
- CPUState *env = cur_cpu = next_cpu;
-
- if (!vm_running)
- break;
- if (qemu_timer_alarm_pending()) {
- break;
- }
- if (cpu_can_run(env))
- ret = qemu_cpu_exec(env);
- if (ret == EXCP_DEBUG) {
- gdb_set_stop_cpu(env);
- debug_requested = 1;
- break;
- }
- }
-}
-
-static int cpu_has_work(CPUState *env)
-{
- if (env->stop)
- return 1;
- if (env->stopped)
- return 0;
- if (!env->halted)
- return 1;
- if (qemu_cpu_has_work(env))
- return 1;
- return 0;
-}
-
-int tcg_has_work(void)
-{
- CPUState *env;
-
- for (env = first_cpu; env != NULL; env = env->next_cpu)
- if (cpu_has_work(env))
- return 1;
- return 0;
-}
-
static int vm_can_run(void)
{
if (powerdown_requested)
diff --git a/vl.c b/vl.c
index feb8831..f1246f4 100644
--- a/vl.c
+++ b/vl.c
@@ -261,9 +261,6 @@ int nb_numa_nodes;
uint64_t node_mem[MAX_NODES];
uint64_t node_cpumask[MAX_NODES];
-static CPUState *cur_cpu;
-static CPUState *next_cpu;
-static int timer_alarm_pending = 1;
static QEMUTimer *nographic_timer;
uint8_t qemu_uuid[16];
@@ -351,28 +348,6 @@ static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
}
-/***********************************************************/
-void hw_error(const char *fmt, ...)
-{
- va_list ap;
- CPUState *env;
-
- va_start(ap, fmt);
- fprintf(stderr, "qemu: hardware error: ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- for(env = first_cpu; env != NULL; env = env->next_cpu) {
- fprintf(stderr, "CPU #%d:\n", env->cpu_index);
-#ifdef TARGET_I386
- cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU);
-#else
- cpu_dump_state(env, stderr, fprintf, 0);
-#endif
- }
- va_end(ap);
- abort();
-}
-
/***************/
/* ballooning */
@@ -1932,7 +1907,7 @@ void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
qemu_free (e);
}
-static void vm_state_notify(int running, int reason)
+void vm_state_notify(int running, int reason)
{
VMChangeStateEntry *e;
@@ -1941,9 +1916,6 @@ static void vm_state_notify(int running, int reason)
}
}
-static void resume_all_vcpus(void);
-static void pause_all_vcpus(void);
-
void vm_start(void)
{
if (!vm_running) {
@@ -1969,7 +1941,7 @@ static int reset_requested;
static int shutdown_requested, shutdown_signal = -1;
static pid_t shutdown_pid;
static int powerdown_requested;
-static int debug_requested;
+int debug_requested;
static int vmstop_requested;
int qemu_shutdown_requested(void)
@@ -2007,38 +1979,6 @@ static int qemu_vmstop_requested(void)
return r;
}
-void qemu_register_reset(QEMUResetHandler *func, void *opaque)
-{
- QEMUResetEntry *re = qemu_mallocz(sizeof(QEMUResetEntry));
-
- re->func = func;
- re->opaque = opaque;
- QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
-}
-
-void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
-{
- QEMUResetEntry *re;
-
- QTAILQ_FOREACH(re, &reset_handlers, entry) {
- if (re->func == func && re->opaque == opaque) {
- QTAILQ_REMOVE(&reset_handlers, re, entry);
- qemu_free(re);
- return;
- }
- }
-}
-
-static void do_vm_stop(int reason)
-{
- if (vm_running) {
- cpu_disable_ticks();
- vm_running = 0;
- pause_all_vcpus();
- vm_state_notify(0, reason);
- }
-}
-
void qemu_register_reset(QEMUResetHandler *func, int order, void *opaque)
{
QEMUResetEntry **pre, *re;
@@ -2102,519 +2042,15 @@ static void qemu_system_vmstop_request(int reason)
}
#endif
-#ifndef _WIN32
-static int io_thread_fd = -1;
-
-static void qemu_event_increment(void)
-{
- static const char byte = 0;
-
- if (io_thread_fd == -1)
- return;
-
- write(io_thread_fd, &byte, sizeof(byte));
-}
-
-static void qemu_event_read(void *opaque)
-{
- int fd = (unsigned long)opaque;
- ssize_t len;
-
- /* Drain the notify pipe */
- do {
- char buffer[512];
- len = read(fd, buffer, sizeof(buffer));
- } while ((len == -1 && errno == EINTR) || len > 0);
-}
-
-static int qemu_event_init(void)
-{
- int err;
- int fds[2];
-
- err = pipe(fds);
- if (err == -1)
- return -errno;
-
- err = fcntl_setfl(fds[0], O_NONBLOCK);
- if (err < 0)
- goto fail;
-
- err = fcntl_setfl(fds[1], O_NONBLOCK);
- if (err < 0)
- goto fail;
-
- qemu_set_fd_handler2(fds[0], NULL, qemu_event_read, NULL,
- (void *)(unsigned long)fds[0]);
-
- io_thread_fd = fds[1];
- return 0;
-
-fail:
- close(fds[0]);
- close(fds[1]);
- return err;
-}
-#else
-HANDLE qemu_event_handle;
-
-static void dummy_event_handler(void *opaque)
-{
-}
-
-static int qemu_event_init(void)
-{
- qemu_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (!qemu_event_handle) {
- perror("Failed CreateEvent");
- return -1;
- }
- qemu_add_wait_object(qemu_event_handle, dummy_event_handler, NULL);
- return 0;
-}
-
-static void qemu_event_increment(void)
-{
- SetEvent(qemu_event_handle);
-}
-#endif
-
-static int cpu_can_run(CPUState *env)
-{
- if (env->stop)
- return 0;
- if (env->stopped)
- return 0;
- if (!vm_running)
- return 0;
- return 1;
-}
-
-#ifndef CONFIG_IOTHREAD
-static int qemu_init_main_loop(void)
-{
- return qemu_event_init();
-}
-
-void qemu_init_vcpu(void *_env)
-{
- CPUState *env = _env;
-
- if (kvm_enabled())
- kvm_init_vcpu(env);
- return;
-}
-
-int qemu_cpu_self(void *env)
-{
- return 1;
-}
-
-static void resume_all_vcpus(void)
-{
-}
-
-static void pause_all_vcpus(void)
-{
-}
-
-void qemu_cpu_kick(void *env)
-{
- return;
-}
-
-void qemu_notify_event(void)
-{
- CPUState *env = cpu_single_env;
-
- if (env) {
- cpu_exit(env);
- }
-}
-
-#define qemu_mutex_lock_iothread() do { } while (0)
-#define qemu_mutex_unlock_iothread() do { } while (0)
-
-void vm_stop(int reason)
-{
- do_vm_stop(reason);
-}
-
-#else /* CONFIG_IOTHREAD */
-
-#include "qemu-thread.h"
-
-QemuMutex qemu_global_mutex;
-static QemuMutex qemu_fair_mutex;
-
-static QemuThread io_thread;
-
-static QemuThread *tcg_cpu_thread;
-static QemuCond *tcg_halt_cond;
-
-static int qemu_system_ready;
-/* cpu creation */
-static QemuCond qemu_cpu_cond;
-/* system init */
-static QemuCond qemu_system_cond;
-static QemuCond qemu_pause_cond;
-
-static void block_io_signals(void);
-static void unblock_io_signals(void);
-static int tcg_has_work(void);
-
-static int qemu_init_main_loop(void)
-{
- int ret;
-
- ret = qemu_event_init();
- if (ret)
- return ret;
-
- qemu_cond_init(&qemu_pause_cond);
- qemu_mutex_init(&qemu_fair_mutex);
- qemu_mutex_init(&qemu_global_mutex);
- qemu_mutex_lock(&qemu_global_mutex);
-
- unblock_io_signals();
- qemu_thread_self(&io_thread);
-
- return 0;
-}
-
-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);
- if (env->stop) {
- env->stop = 0;
- env->stopped = 1;
- qemu_cond_signal(&qemu_pause_cond);
- }
-}
-
-static int qemu_cpu_exec(CPUState *env);
-
-static void *kvm_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);
- 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_wait_io_event(env);
- }
-
- return NULL;
-}
-
-static void tcg_cpu_exec(void);
-
-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;
-}
-
-void qemu_cpu_kick(void *_env)
-{
- CPUState *env = _env;
- qemu_cond_broadcast(env->halt_cond);
- if (kvm_enabled())
- qemu_thread_signal(env->thread, SIGUSR1);
-}
-
-int qemu_cpu_self(void *env)
-{
- return (cpu_single_env != NULL);
-}
-
-static void cpu_signal(int sig)
-{
- if (cpu_single_env)
- cpu_exit(cpu_single_env);
-}
-
-static void block_io_signals(void)
-{
- sigset_t set;
- struct sigaction sigact;
-
- sigemptyset(&set);
- sigaddset(&set, SIGUSR2);
- sigaddset(&set, SIGIO);
- sigaddset(&set, SIGALRM);
- pthread_sigmask(SIG_BLOCK, &set, NULL);
-
- sigemptyset(&set);
- sigaddset(&set, SIGUSR1);
- pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-
- memset(&sigact, 0, sizeof(sigact));
- sigact.sa_handler = cpu_signal;
- sigaction(SIGUSR1, &sigact, NULL);
-}
-
-static void unblock_io_signals(void)
-{
- sigset_t set;
-
- sigemptyset(&set);
- sigaddset(&set, SIGUSR2);
- sigaddset(&set, SIGIO);
- sigaddset(&set, SIGALRM);
- pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-
- sigemptyset(&set);
- sigaddset(&set, SIGUSR1);
- 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, SIGUSR1);
- 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);
-}
-
-void qemu_mutex_unlock_iothread(void)
-{
- qemu_mutex_unlock(&qemu_global_mutex);
-}
-
-static int all_vcpus_paused(void)
-{
- CPUState *penv = first_cpu;
-
- while (penv) {
- if (!penv->stopped)
- return 0;
- penv = (CPUState *)penv->next_cpu;
- }
-
- return 1;
-}
-
-static void pause_all_vcpus(void)
-{
- CPUState *penv = first_cpu;
-
- while (penv) {
- penv->stop = 1;
- qemu_thread_signal(penv->thread, SIGUSR1);
- 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_thread_signal(penv->thread, SIGUSR1);
- penv = (CPUState *)penv->next_cpu;
- }
- }
-}
-
-static void resume_all_vcpus(void)
-{
- CPUState *penv = first_cpu;
-
- while (penv) {
- penv->stop = 0;
- penv->stopped = 0;
- qemu_thread_signal(penv->thread, SIGUSR1);
- qemu_cpu_kick(penv);
- penv = (CPUState *)penv->next_cpu;
- }
-}
-
-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 kvm_start_vcpu(CPUState *env)
-{
- kvm_init_vcpu(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);
-}
-
-void qemu_init_vcpu(void *_env)
-{
- CPUState *env = _env;
-
- if (kvm_enabled())
- kvm_start_vcpu(env);
- else
- tcg_init_vcpu(env);
-}
-
-void qemu_notify_event(void)
-{
- qemu_event_increment();
-}
-
-void vm_stop(int reason)
-{
- QemuThread me;
- qemu_thread_self(&me);
-
- if (!qemu_thread_equal(&me, &io_thread)) {
- qemu_system_vmstop_request(reason);
- /*
- * FIXME: should not return to device code in case
- * vm_stop() has been requested.
- */
- if (cpu_single_env) {
- cpu_exit(cpu_single_env);
- cpu_single_env->stop = 1;
- }
- return;
- }
- do_vm_stop(reason);
-}
-
-#endif
-
-
-#ifdef _WIN32
-static void host_main_loop_wait(int *timeout)
-{
- int ret, ret2, i;
- PollingEntry *pe;
-
-
- /* XXX: need to suppress polling by better using win32 events */
- ret = 0;
- for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
- ret |= pe->func(pe->opaque);
- }
- if (ret == 0) {
- int err;
- WaitObjects *w = &wait_objects;
-
- ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
- if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
- if (w->func[ret - WAIT_OBJECT_0])
- w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
-
- /* Check for additional signaled events */
- for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-
- /* Check if event is signaled */
- ret2 = WaitForSingleObject(w->events[i], 0);
- if(ret2 == WAIT_OBJECT_0) {
- if (w->func[i])
- w->func[i](w->opaque[i]);
- } else if (ret2 == WAIT_TIMEOUT) {
- } else {
- err = GetLastError();
- fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
- }
- }
- } else if (ret == WAIT_TIMEOUT) {
- } else {
- err = GetLastError();
- fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
- }
- }
-
- *timeout = 0;
-}
-#else
-static void host_main_loop_wait(int *timeout)
-{
-}
-#endif
-
void main_loop_wait(int timeout)
{
- IOHandlerRecord *ioh;
fd_set rfds, wfds, xfds;
int ret, nfds;
struct timeval tv;
qemu_bh_update_timeout(&timeout);
- host_main_loop_wait(&timeout);
+ os_host_main_loop_wait(&timeout);
tv.tv_sec = timeout / 1000;
@@ -2653,97 +2089,6 @@ void main_loop_wait(int timeout)
}
-static int qemu_cpu_exec(CPUState *env)
-{
- int ret;
-#ifdef CONFIG_PROFILER
- int64_t ti;
-#endif
-
-#ifdef CONFIG_PROFILER
- ti = profile_getclock();
-#endif
- if (use_icount) {
- int64_t count;
- int decr;
- qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
- env->icount_decr.u16.low = 0;
- env->icount_extra = 0;
- count = qemu_next_deadline();
- count = (count + (1 << icount_time_shift) - 1)
- >> icount_time_shift;
- qemu_icount += count;
- decr = (count > 0xffff) ? 0xffff : count;
- count -= decr;
- env->icount_decr.u16.low = decr;
- env->icount_extra = count;
- }
- ret = cpu_exec(env);
-#ifdef CONFIG_PROFILER
- qemu_time += profile_getclock() - ti;
-#endif
- if (use_icount) {
- /* Fold pending instructions back into the
- instruction counter, and clear the interrupt flag. */
- qemu_icount -= (env->icount_decr.u16.low
- + env->icount_extra);
- env->icount_decr.u32 = 0;
- env->icount_extra = 0;
- }
- return ret;
-}
-
-static void tcg_cpu_exec(void)
-{
- int ret = 0;
-
- if (next_cpu == NULL)
- next_cpu = first_cpu;
- for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
- CPUState *env = cur_cpu = next_cpu;
-
- if (timer_alarm_pending) {
- timer_alarm_pending = 0;
- break;
- }
- if (cpu_can_run(env))
- ret = qemu_cpu_exec(env);
- else if (env->stop)
- break;
-
- if (ret == EXCP_DEBUG) {
- gdb_set_stop_cpu(env);
- debug_requested = 1;
- break;
- }
- }
-}
-
-#if 0
-static int cpu_has_work(CPUState *env)
-{
- if (env->stop)
- return 1;
- if (env->stopped)
- return 0;
- if (!env->halted)
- return 1;
- if (qemu_cpu_has_work(env))
- return 1;
- return 0;
-}
-
-static int tcg_has_work(void)
-{
- CPUState *env;
-
- for (env = first_cpu; env != NULL; env = env->next_cpu)
- if (cpu_has_work(env))
- return 1;
- return 0;
-}
-#endif
-
static int vm_can_run(void)
{
if (powerdown_requested)