[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [patch 5/7] qemu: pause and resume cpu thread(s)
From: |
mtosatti |
Subject: |
[Qemu-devel] [patch 5/7] qemu: pause and resume cpu thread(s) |
Date: |
Thu, 19 Mar 2009 11:57:10 -0300 |
User-agent: |
quilt/0.46-1 |
Since cpu emulation happens on a separate thread, it is necessary to
pause/resume it upon certain events such as reset, debug exception,
live migration, etc.
Index: qemu/vl.c
===================================================================
--- qemu.orig/vl.c
+++ qemu/vl.c
@@ -271,6 +271,11 @@ QemuMutex qemu_fair_mutex;
QemuThread io_thread;
QemuThread cpus_thread;
+QemuCond qemu_pause_cond;
+
+static void pause_all_vcpus(void);
+static void resume_all_vcpus(void);
+
/***********************************************************/
/* x86 ISA bus support */
@@ -3461,6 +3466,7 @@ void vm_start(void)
if (!vm_running) {
cpu_enable_ticks();
vm_running = 1;
+ resume_all_vcpus();
vm_state_notify(1, 0);
qemu_rearm_alarm_timer(alarm_timer);
}
@@ -3471,6 +3477,7 @@ void vm_stop(int reason)
if (vm_running) {
cpu_disable_ticks();
vm_running = 0;
+ pause_all_vcpus();
vm_state_notify(0, reason);
}
}
@@ -3620,7 +3627,9 @@ static int wait_signal(int timeout)
static int has_work(CPUState *env)
{
- if (!vm_running)
+ if (env->stop)
+ return 1;
+ if (!vm_running || env->stopped)
return 0;
if (!env->halted)
return 1;
@@ -3644,6 +3653,11 @@ static void qemu_wait_io_event(CPUState
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 void cpu_signal(int sig)
@@ -3848,6 +3862,21 @@ void main_loop_wait(int timeout)
}
+static int vm_can_run(CPUState *env)
+{
+ if (env->stop)
+ return 0;
+ if (env->stopped)
+ return 0;
+ if (shutdown_requested)
+ return 0;
+ if (powerdown_requested)
+ return 0;
+ if (reset_requested)
+ return 0;
+ return 1;
+}
+
static void *cpu_main_loop(void *arg)
{
int ret, timeout;
@@ -3887,7 +3916,9 @@ static void *cpu_main_loop(void *arg)
env->icount_decr.u16.low = decr;
env->icount_extra = count;
}
- ret = cpu_exec(env);
+ ret = EXCP_HALTED;
+ if (vm_can_run(env))
+ ret = cpu_exec(env);
#ifdef CONFIG_PROFILER
qemu_time += profile_getclock() - ti;
#endif
@@ -3965,6 +3996,7 @@ static void *cpu_main_loop(void *arg)
timeout = 0;
}
} else {
+ env = env->next_cpu ?: first_cpu;
timeout = 5000;
}
#ifdef CONFIG_PROFILER
@@ -3979,11 +4011,53 @@ static void *cpu_main_loop(void *arg)
return NULL;
}
+static int all_vcpus_paused(void)
+{
+ CPUState *penv = first_cpu;
+
+ while (penv) {
+ if (penv->stop)
+ 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(&cpus_thread, SIGUSR1);
+ penv = (CPUState *)penv->next_cpu;
+ }
+
+ while (!all_vcpus_paused()) {
+ qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
+ qemu_thread_signal(&cpus_thread, SIGUSR1);
+ }
+}
+
+static void resume_all_vcpus(void)
+{
+ CPUState *penv = first_cpu;
+
+ while (penv) {
+ penv->stop = 0;
+ penv->stopped = 0;
+ qemu_thread_signal(&cpus_thread, SIGUSR1);
+ penv = (CPUState *)penv->next_cpu;
+ }
+}
+
static void main_loop(void)
{
qemu_mutex_init(&qemu_fair_mutex);
qemu_mutex_init(&qemu_global_mutex);
qemu_mutex_lock(&qemu_global_mutex);
+ qemu_cond_init(&qemu_pause_cond);
qemu_thread_self(&io_thread);
@@ -3994,14 +4068,18 @@ static void main_loop(void)
while (1) {
main_loop_wait(1000);
if (qemu_shutdown_requested()) {
+ pause_all_vcpus();
if (no_shutdown)
no_shutdown = 0;
else
break;
} else if (qemu_powerdown_requested())
qemu_system_powerdown();
- else if (qemu_reset_requested())
+ else if (qemu_reset_requested()) {
+ pause_all_vcpus();
qemu_system_reset();
+ resume_all_vcpus();
+ }
}
}
Index: qemu/cpu-defs.h
===================================================================
--- qemu.orig/cpu-defs.h
+++ qemu/cpu-defs.h
@@ -169,6 +169,8 @@ typedef struct CPUWatchpoint {
target_ulong mem_io_vaddr; /* target virtual addr at which the \
memory was accessed */ \
uint32_t halted; /* Nonzero if the CPU is in suspend state */ \
+ uint32_t stop; /* Stop request */ \
+ uint32_t stopped; /* Artificially stopped */ \
uint32_t interrupt_request; \
/* The meaning of the MMU modes is defined in the target code. */ \
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
--
- [Qemu-devel] [patch 2/7] qemu: separate thread for io, (continued)
- [Qemu-devel] [patch 2/7] qemu: separate thread for io, mtosatti, 2009/03/19
- [Qemu-devel] Re: [patch 2/7] qemu: separate thread for io, Anthony Liguori, 2009/03/20
- [Qemu-devel] Re: [patch 2/7] qemu: separate thread for io, Marcelo Tosatti, 2009/03/20
- [Qemu-devel] Re: [patch 2/7] qemu: separate thread for io, Anthony Liguori, 2009/03/20
- [Qemu-devel] Re: [patch 2/7] qemu: separate thread for io, Marcelo Tosatti, 2009/03/20
- [Qemu-devel] Re: [patch 2/7] qemu: separate thread for io, Anthony Liguori, 2009/03/20
- [Qemu-devel] Re: [patch 2/7] qemu: separate thread for io, Avi Kivity, 2009/03/22
- [Qemu-devel] Re: [patch 2/7] qemu: separate thread for io, Anthony Liguori, 2009/03/22
[Qemu-devel] [patch 3/7] qemu: main thread does io and cpu thread is spawned, mtosatti, 2009/03/19
[Qemu-devel] [patch 4/7] qemu: handle reset/poweroff/shutdown in iothread, mtosatti, 2009/03/19
[Qemu-devel] [patch 5/7] qemu: pause and resume cpu thread(s),
mtosatti <=
[Qemu-devel] [patch 7/7] qemu: use pipe to wakeup io thread, mtosatti, 2009/03/19
[Qemu-devel] [patch 6/7] qemu: handle vmstop from cpu context, mtosatti, 2009/03/19