port qemu-kvm's on_vcpu code
run_on_cpu allows to execute work on a given CPUState context. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
parent
1fbb22e5f8
commit
e82bcec25f
@ -821,6 +821,7 @@ void cpu_watchpoint_remove_all(CPUState *env, int mask);
|
||||
|
||||
void cpu_single_step(CPUState *env, int enabled);
|
||||
void cpu_reset(CPUState *s);
|
||||
void run_on_cpu(CPUState *env, void (*func)(void *data), void *data);
|
||||
|
||||
#define CPU_LOG_TB_OUT_ASM (1 << 0)
|
||||
#define CPU_LOG_TB_IN_ASM (1 << 1)
|
||||
|
@ -132,6 +132,7 @@ typedef struct icount_decr_u16 {
|
||||
|
||||
struct kvm_run;
|
||||
struct KVMState;
|
||||
struct qemu_work_item;
|
||||
|
||||
typedef struct CPUBreakpoint {
|
||||
target_ulong pc;
|
||||
@ -204,6 +205,7 @@ typedef struct CPUWatchpoint {
|
||||
uint32_t created; \
|
||||
struct QemuThread *thread; \
|
||||
struct QemuCond *halt_cond; \
|
||||
struct qemu_work_item *queued_work_first, *queued_work_last; \
|
||||
const char *cpu_model_str; \
|
||||
struct KVMState *kvm_state; \
|
||||
struct kvm_run *kvm_run; \
|
||||
|
53
cpus.c
53
cpus.c
@ -115,6 +115,8 @@ static int cpu_has_work(CPUState *env)
|
||||
{
|
||||
if (env->stop)
|
||||
return 1;
|
||||
if (env->queued_work_first)
|
||||
return 1;
|
||||
if (env->stopped || !vm_running)
|
||||
return 0;
|
||||
if (!env->halted)
|
||||
@ -252,6 +254,11 @@ int qemu_cpu_self(void *env)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
|
||||
{
|
||||
func(data);
|
||||
}
|
||||
|
||||
void resume_all_vcpus(void)
|
||||
{
|
||||
}
|
||||
@ -304,6 +311,7 @@ static QemuCond qemu_cpu_cond;
|
||||
/* 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);
|
||||
@ -334,6 +342,50 @@ void qemu_main_loop_start(void)
|
||||
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) {
|
||||
@ -341,6 +393,7 @@ static void qemu_wait_io_event_common(CPUState *env)
|
||||
env->stopped = 1;
|
||||
qemu_cond_signal(&qemu_pause_cond);
|
||||
}
|
||||
flush_queued_work(env);
|
||||
}
|
||||
|
||||
static void qemu_wait_io_event(CPUState *env)
|
||||
|
@ -249,6 +249,14 @@ void qemu_notify_event(void);
|
||||
void qemu_cpu_kick(void *env);
|
||||
int qemu_cpu_self(void *env);
|
||||
|
||||
/* work queue */
|
||||
struct qemu_work_item {
|
||||
struct qemu_work_item *next;
|
||||
void (*func)(void *data);
|
||||
void *data;
|
||||
int done;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#define qemu_init_vcpu(env) do { } while (0)
|
||||
#else
|
||||
|
Loading…
Reference in New Issue
Block a user