From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44034) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1boWA5-0006BX-6H for qemu-devel@nongnu.org; Mon, 26 Sep 2016 09:41:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1boWA0-0004sG-Ss for qemu-devel@nongnu.org; Mon, 26 Sep 2016 09:41:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:16585) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1boWA0-0004rv-I4 for qemu-devel@nongnu.org; Mon, 26 Sep 2016 09:41:32 -0400 From: Paolo Bonzini Date: Mon, 26 Sep 2016 15:40:46 +0200 Message-Id: <1474897258-1205-17-git-send-email-pbonzini@redhat.com> In-Reply-To: <1474897258-1205-1-git-send-email-pbonzini@redhat.com> References: <1474897258-1205-1-git-send-email-pbonzini@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PULL 16/28] cpus-common: move CPU work item management to common code List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Sergey Fedorov , Sergey Fedorov , =?UTF-8?q?Alex=20Benn=C3=A9e?= From: Sergey Fedorov Make CPU work core functions common between system and user-mode emulation. User-mode does not use run_on_cpu, so do not implement it. Signed-off-by: Sergey Fedorov Signed-off-by: Sergey Fedorov Reviewed-by: Alex Benn=C3=A9e Signed-off-by: Alex Benn=C3=A9e Message-Id: <1470158864-17651-10-git-send-email-alex.bennee@linaro.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- bsd-user/main.c | 11 +++++-- cpus-common.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++= ++++++ cpus.c | 82 +----------------------------------------------- include/qom/cpu.h | 27 +++++++++++----- linux-user/main.c | 25 +++++++++++++++ 5 files changed, 148 insertions(+), 91 deletions(-) diff --git a/bsd-user/main.c b/bsd-user/main.c index 591c424..6dfa912 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -68,11 +68,11 @@ int cpu_get_pic_interrupt(CPUX86State *env) #endif =20 /* These are no-ops because we are not threadsafe. */ -static inline void cpu_exec_start(CPUArchState *env) +static inline void cpu_exec_start(CPUState *cpu) { } =20 -static inline void cpu_exec_end(CPUArchState *env) +static inline void cpu_exec_end(CPUState *cpu) { } =20 @@ -164,7 +164,11 @@ void cpu_loop(CPUX86State *env) //target_siginfo_t info; =20 for(;;) { + cpu_exec_start(cs); trapnr =3D cpu_exec(cs); + cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch(trapnr) { case 0x80: /* syscall from int $0x80 */ @@ -505,7 +509,10 @@ void cpu_loop(CPUSPARCState *env) //target_siginfo_t info; =20 while (1) { + cpu_exec_start(cs); trapnr =3D cpu_exec(cs); + cpu_exec_end(cs); + process_queued_cpu_work(cs); =20 switch (trapnr) { #ifndef TARGET_SPARC64 diff --git a/cpus-common.c b/cpus-common.c index fda3848..2005bfe 100644 --- a/cpus-common.c +++ b/cpus-common.c @@ -23,10 +23,12 @@ #include "sysemu/cpus.h" =20 static QemuMutex qemu_cpu_list_lock; +static QemuCond qemu_work_cond; =20 void qemu_init_cpu_list(void) { qemu_mutex_init(&qemu_cpu_list_lock); + qemu_cond_init(&qemu_work_cond); } =20 void cpu_list_lock(void) @@ -81,3 +83,95 @@ void cpu_list_remove(CPUState *cpu) cpu->cpu_index =3D UNASSIGNED_CPU_INDEX; qemu_mutex_unlock(&qemu_cpu_list_lock); } + +struct qemu_work_item { + struct qemu_work_item *next; + run_on_cpu_func func; + void *data; + int done; + bool free; +}; + +static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi) +{ + qemu_mutex_lock(&cpu->work_mutex); + if (cpu->queued_work_first =3D=3D NULL) { + cpu->queued_work_first =3D wi; + } else { + cpu->queued_work_last->next =3D wi; + } + cpu->queued_work_last =3D wi; + wi->next =3D NULL; + wi->done =3D false; + qemu_mutex_unlock(&cpu->work_mutex); + + qemu_cpu_kick(cpu); +} + +void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data, + QemuMutex *mutex) +{ + struct qemu_work_item wi; + + if (qemu_cpu_is_self(cpu)) { + func(cpu, data); + return; + } + + wi.func =3D func; + wi.data =3D data; + wi.free =3D false; + + queue_work_on_cpu(cpu, &wi); + while (!atomic_mb_read(&wi.done)) { + CPUState *self_cpu =3D current_cpu; + + qemu_cond_wait(&qemu_work_cond, mutex); + current_cpu =3D self_cpu; + } +} + +void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data) +{ + struct qemu_work_item *wi; + + if (qemu_cpu_is_self(cpu)) { + func(cpu, data); + return; + } + + wi =3D g_malloc0(sizeof(struct qemu_work_item)); + wi->func =3D func; + wi->data =3D data; + wi->free =3D true; + + queue_work_on_cpu(cpu, wi); +} + +void process_queued_cpu_work(CPUState *cpu) +{ + struct qemu_work_item *wi; + + if (cpu->queued_work_first =3D=3D NULL) { + return; + } + + qemu_mutex_lock(&cpu->work_mutex); + while (cpu->queued_work_first !=3D NULL) { + wi =3D cpu->queued_work_first; + cpu->queued_work_first =3D wi->next; + if (!cpu->queued_work_first) { + cpu->queued_work_last =3D NULL; + } + qemu_mutex_unlock(&cpu->work_mutex); + wi->func(cpu, wi->data); + qemu_mutex_lock(&cpu->work_mutex); + if (wi->free) { + g_free(wi); + } else { + atomic_mb_set(&wi->done, true); + } + } + qemu_mutex_unlock(&cpu->work_mutex); + qemu_cond_broadcast(&qemu_work_cond); +} diff --git a/cpus.c b/cpus.c index 28d6206..c3afd18 100644 --- a/cpus.c +++ b/cpus.c @@ -902,73 +902,21 @@ static QemuThread io_thread; static QemuCond qemu_cpu_cond; /* system init */ static QemuCond qemu_pause_cond; -static QemuCond qemu_work_cond; =20 void qemu_init_cpu_loop(void) { qemu_init_sigbus(); qemu_cond_init(&qemu_cpu_cond); qemu_cond_init(&qemu_pause_cond); - qemu_cond_init(&qemu_work_cond); qemu_cond_init(&qemu_io_proceeded_cond); qemu_mutex_init(&qemu_global_mutex); =20 qemu_thread_get_self(&io_thread); } =20 -static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi) -{ - qemu_mutex_lock(&cpu->work_mutex); - if (cpu->queued_work_first =3D=3D NULL) { - cpu->queued_work_first =3D wi; - } else { - cpu->queued_work_last->next =3D wi; - } - cpu->queued_work_last =3D wi; - wi->next =3D NULL; - wi->done =3D false; - qemu_mutex_unlock(&cpu->work_mutex); - - qemu_cpu_kick(cpu); -} - void run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data) { - struct qemu_work_item wi; - - if (qemu_cpu_is_self(cpu)) { - func(cpu, data); - return; - } - - wi.func =3D func; - wi.data =3D data; - wi.free =3D false; - - queue_work_on_cpu(cpu, &wi); - while (!atomic_mb_read(&wi.done)) { - CPUState *self_cpu =3D current_cpu; - - qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex); - current_cpu =3D self_cpu; - } -} - -void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data) -{ - struct qemu_work_item *wi; - - if (qemu_cpu_is_self(cpu)) { - func(cpu, data); - return; - } - - wi =3D g_malloc0(sizeof(struct qemu_work_item)); - wi->func =3D func; - wi->data =3D data; - wi->free =3D true; - - queue_work_on_cpu(cpu, wi); + do_run_on_cpu(cpu, func, data, &qemu_global_mutex); } =20 static void qemu_kvm_destroy_vcpu(CPUState *cpu) @@ -983,34 +931,6 @@ static void qemu_tcg_destroy_vcpu(CPUState *cpu) { } =20 -static void process_queued_cpu_work(CPUState *cpu) -{ - struct qemu_work_item *wi; - - if (cpu->queued_work_first =3D=3D NULL) { - return; - } - - qemu_mutex_lock(&cpu->work_mutex); - while (cpu->queued_work_first !=3D NULL) { - wi =3D cpu->queued_work_first; - cpu->queued_work_first =3D wi->next; - if (!cpu->queued_work_first) { - cpu->queued_work_last =3D NULL; - } - qemu_mutex_unlock(&cpu->work_mutex); - wi->func(cpu, wi->data); - qemu_mutex_lock(&cpu->work_mutex); - if (wi->free) { - g_free(wi); - } else { - atomic_mb_set(&wi->done, true); - } - } - qemu_mutex_unlock(&cpu->work_mutex); - qemu_cond_broadcast(&qemu_work_cond); -} - static void qemu_wait_io_event_common(CPUState *cpu) { if (cpu->stop) { diff --git a/include/qom/cpu.h b/include/qom/cpu.h index ea3233f..c04e510 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -233,14 +233,7 @@ struct kvm_run; =20 /* work queue */ typedef void (*run_on_cpu_func)(CPUState *cpu, void *data); - -struct qemu_work_item { - struct qemu_work_item *next; - run_on_cpu_func func; - void *data; - int done; - bool free; -}; +struct qemu_work_item; =20 /** * CPUState: @@ -630,6 +623,18 @@ void qemu_cpu_kick(CPUState *cpu); bool cpu_is_stopped(CPUState *cpu); =20 /** + * do_run_on_cpu: + * @cpu: The vCPU to run on. + * @func: The function to be executed. + * @data: Data to pass to the function. + * @mutex: Mutex to release while waiting for @func to run. + * + * Used internally in the implementation of run_on_cpu. + */ +void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data, + QemuMutex *mutex); + +/** * run_on_cpu: * @cpu: The vCPU to run on. * @func: The function to be executed. @@ -808,6 +813,12 @@ void cpu_remove(CPUState *cpu); void cpu_remove_sync(CPUState *cpu); =20 /** + * process_queued_cpu_work() - process all items on CPU work queue + * @cpu: The CPU which work queue to process. + */ +void process_queued_cpu_work(CPUState *cpu); + +/** * qemu_init_vcpu: * @cpu: The vCPU to initialize. * diff --git a/linux-user/main.c b/linux-user/main.c index 719f046..e3eca40 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -294,6 +294,8 @@ void cpu_loop(CPUX86State *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch(trapnr) { case 0x80: /* linux syscall from int $0x80 */ @@ -735,6 +737,8 @@ void cpu_loop(CPUARMState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch(trapnr) { case EXCP_UDEF: { @@ -1071,6 +1075,7 @@ void cpu_loop(CPUARMState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); =20 switch (trapnr) { case EXCP_SWI: @@ -1159,6 +1164,8 @@ void cpu_loop(CPUUniCore32State *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch (trapnr) { case UC32_EXCP_PRIV: { @@ -1364,6 +1371,7 @@ void cpu_loop (CPUSPARCState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); =20 /* Compute PSR before exposing state. */ if (env->cc_op !=3D CC_OP_FLAGS) { @@ -1636,6 +1644,8 @@ void cpu_loop(CPUPPCState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch(trapnr) { case POWERPC_EXCP_NONE: /* Just go on */ @@ -2482,6 +2492,8 @@ void cpu_loop(CPUMIPSState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch(trapnr) { case EXCP_SYSCALL: env->active_tc.PC +=3D 4; @@ -2722,6 +2734,7 @@ void cpu_loop(CPUOpenRISCState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); gdbsig =3D 0; =20 switch (trapnr) { @@ -2816,6 +2829,7 @@ void cpu_loop(CPUSH4State *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); =20 switch (trapnr) { case 0x160: @@ -2882,6 +2896,8 @@ void cpu_loop(CPUCRISState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch (trapnr) { case 0xaa: { @@ -2947,6 +2963,8 @@ void cpu_loop(CPUMBState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch (trapnr) { case 0xaa: { @@ -3064,6 +3082,8 @@ void cpu_loop(CPUM68KState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch(trapnr) { case EXCP_ILLEGAL: { @@ -3207,6 +3227,7 @@ void cpu_loop(CPUAlphaState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); =20 /* All of the traps imply a transition through PALcode, which implies an REI instruction has been executed. Which means @@ -3399,6 +3420,8 @@ void cpu_loop(CPUS390XState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch (trapnr) { case EXCP_INTERRUPT: /* Just indicate that signals should be handled asap. */ @@ -3708,6 +3731,8 @@ void cpu_loop(CPUTLGState *env) cpu_exec_start(cs); trapnr =3D cpu_exec(cs); cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch (trapnr) { case TILEGX_EXCP_SYSCALL: { --=20 2.7.4