From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46268) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1boRHy-0005U3-Ps for qemu-devel@nongnu.org; Mon, 26 Sep 2016 04:29:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1boRHt-0004EC-Po for qemu-devel@nongnu.org; Mon, 26 Sep 2016 04:29:25 -0400 Received: from mail-wm0-f46.google.com ([74.125.82.46]:33732) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1boRHt-0004Dj-H9 for qemu-devel@nongnu.org; Mon, 26 Sep 2016 04:29:21 -0400 Received: by mail-wm0-f46.google.com with SMTP id d66so22228609wmf.0 for ; Mon, 26 Sep 2016 01:29:21 -0700 (PDT) References: <1474615909-17069-1-git-send-email-pbonzini@redhat.com> <1474615909-17069-15-git-send-email-pbonzini@redhat.com> From: Alex =?utf-8?Q?Benn=C3=A9e?= In-reply-to: <1474615909-17069-15-git-send-email-pbonzini@redhat.com> Date: Mon, 26 Sep 2016 09:28:19 +0100 Message-ID: <871t07gj4s.fsf@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Subject: Re: [Qemu-devel] [PATCH 14/16] cpus-common: Introduce async_safe_run_on_cpu() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Paolo Bonzini Cc: qemu-devel@nongnu.org, cota@braap.org, sergey.fedorov@linaro.org, serge.fdrv@gmail.com Paolo Bonzini writes: > Signed-off-by: Paolo Bonzini Reviewed-by: Alex Bennée > --- > cpus-common.c | 33 +++++++++++++++++++++++++++++++-- > include/qom/cpu.h | 14 ++++++++++++++ > 2 files changed, 45 insertions(+), 2 deletions(-) > > diff --git a/cpus-common.c b/cpus-common.c > index 429652c..38b1d55 100644 > --- a/cpus-common.c > +++ b/cpus-common.c > @@ -18,6 +18,7 @@ > */ > > #include "qemu/osdep.h" > +#include "qemu/main-loop.h" > #include "exec/cpu-common.h" > #include "qom/cpu.h" > #include "sysemu/cpus.h" > @@ -106,7 +107,7 @@ struct qemu_work_item { > struct qemu_work_item *next; > run_on_cpu_func func; > void *data; > - bool free, done; > + bool free, exclusive, done; > }; > > static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi) > @@ -139,6 +140,7 @@ void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data, > wi.data = data; > wi.done = false; > wi.free = false; > + wi.exclusive = false; > > queue_work_on_cpu(cpu, &wi); > while (!atomic_mb_read(&wi.done)) { > @@ -229,6 +231,19 @@ void cpu_exec_end(CPUState *cpu) > qemu_mutex_unlock(&qemu_cpu_list_lock); > } > > +void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data) > +{ > + struct qemu_work_item *wi; > + > + wi = g_malloc0(sizeof(struct qemu_work_item)); > + wi->func = func; > + wi->data = data; > + wi->free = true; > + wi->exclusive = true; > + > + queue_work_on_cpu(cpu, wi); > +} > + > void process_queued_cpu_work(CPUState *cpu) > { > struct qemu_work_item *wi; > @@ -245,7 +260,21 @@ void process_queued_cpu_work(CPUState *cpu) > cpu->queued_work_last = NULL; > } > qemu_mutex_unlock(&cpu->work_mutex); > - wi->func(cpu, wi->data); > + if (wi->exclusive) { > + /* Running work items outside the BQL avoids the following deadlock: > + * 1) start_exclusive() is called with the BQL taken while another > + * CPU is running; 2) cpu_exec in the other CPU tries to takes the > + * BQL, so it goes to sleep; start_exclusive() is sleeping too, so > + * neither CPU can proceed. > + */ > + qemu_mutex_unlock_iothread(); > + start_exclusive(); > + wi->func(cpu, wi->data); > + end_exclusive(); > + qemu_mutex_lock_iothread(); > + } else { > + wi->func(cpu, wi->data); > + } > qemu_mutex_lock(&cpu->work_mutex); > if (wi->free) { > g_free(wi); > diff --git a/include/qom/cpu.h b/include/qom/cpu.h > index 934c07a..4092dd9 100644 > --- a/include/qom/cpu.h > +++ b/include/qom/cpu.h > @@ -656,6 +656,20 @@ void run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data); > void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data); > > /** > + * async_safe_run_on_cpu: > + * @cpu: The vCPU to run on. > + * @func: The function to be executed. > + * @data: Data to pass to the function. > + * > + * Schedules the function @func for execution on the vCPU @cpu asynchronously, > + * while all other vCPUs are sleeping. > + * > + * Unlike run_on_cpu and async_run_on_cpu, the function is run outside the > + * BQL. > + */ > +void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void *data); > + > +/** > * qemu_get_cpu: > * @index: The CPUState@cpu_index value of the CPU to obtain. > * -- Alex Bennée