All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Emilio G. Cota" <cota@braap.org>
To: qemu-devel@nongnu.org
Cc: "Richard Henderson" <richard.henderson@linaro.org>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Alex Bennée" <alex.bennee@linaro.org>
Subject: [Qemu-devel] [PATCH v5 03/73] cpu: introduce cpu_mutex_lock/unlock
Date: Thu, 13 Dec 2018 00:03:43 -0500	[thread overview]
Message-ID: <20181213050453.9677-4-cota@braap.org> (raw)
In-Reply-To: <20181213050453.9677-1-cota@braap.org>

The few direct users of &cpu->lock will be converted soon.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Emilio G. Cota <cota@braap.org>
---
 include/qom/cpu.h   | 33 +++++++++++++++++++++++++++++++
 cpus.c              | 48 +++++++++++++++++++++++++++++++++++++++++++--
 stubs/cpu-lock.c    | 28 ++++++++++++++++++++++++++
 stubs/Makefile.objs |  1 +
 4 files changed, 108 insertions(+), 2 deletions(-)
 create mode 100644 stubs/cpu-lock.c

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 86ce773388..bb5a36a324 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -446,6 +446,39 @@ extern struct CPUTailQ cpus;
 
 extern __thread CPUState *current_cpu;
 
+/**
+ * cpu_mutex_lock - lock a CPU's mutex
+ * @cpu: the CPU whose mutex is to be locked
+ *
+ * To avoid deadlock, a CPU's mutex must be acquired after the BQL.
+ */
+#define cpu_mutex_lock(cpu)                             \
+    cpu_mutex_lock_impl(cpu, __FILE__, __LINE__)
+void cpu_mutex_lock_impl(CPUState *cpu, const char *file, int line);
+
+/**
+ * cpu_mutex_unlock - unlock a CPU's mutex
+ * @cpu: the CPU whose mutex is to be unlocked
+ */
+#define cpu_mutex_unlock(cpu)                           \
+    cpu_mutex_unlock_impl(cpu, __FILE__, __LINE__)
+void cpu_mutex_unlock_impl(CPUState *cpu, const char *file, int line);
+
+/**
+ * cpu_mutex_locked - check whether a CPU's mutex is locked
+ * @cpu: the CPU of interest
+ *
+ * Returns true if the calling thread is currently holding the CPU's mutex.
+ */
+bool cpu_mutex_locked(const CPUState *cpu);
+
+/**
+ * no_cpu_mutex_locked - check whether any CPU mutex is held
+ *
+ * Returns true if the calling thread is not holding any CPU mutex.
+ */
+bool no_cpu_mutex_locked(void);
+
 static inline void cpu_tb_jmp_cache_clear(CPUState *cpu)
 {
     unsigned int i;
diff --git a/cpus.c b/cpus.c
index 895013b56a..980d62cd58 100644
--- a/cpus.c
+++ b/cpus.c
@@ -83,6 +83,47 @@ static unsigned int throttle_percentage;
 #define CPU_THROTTLE_PCT_MAX 99
 #define CPU_THROTTLE_TIMESLICE_NS 10000000
 
+/* XXX: is this really the max number of CPUs? */
+#define CPU_LOCK_BITMAP_SIZE 2048
+
+/*
+ * Note: we index the bitmap with cpu->cpu_index + 1 so that the logic
+ * also works during early CPU initialization, when cpu->cpu_index is set to
+ * UNASSIGNED_CPU_INDEX == -1.
+ */
+static __thread DECLARE_BITMAP(cpu_lock_bitmap, CPU_LOCK_BITMAP_SIZE);
+
+bool no_cpu_mutex_locked(void)
+{
+    return bitmap_empty(cpu_lock_bitmap, CPU_LOCK_BITMAP_SIZE);
+}
+
+void cpu_mutex_lock_impl(CPUState *cpu, const char *file, int line)
+{
+/* coverity gets confused by the indirect function call */
+#ifdef __COVERITY__
+    qemu_mutex_lock_impl(&cpu->lock, file, line);
+#else
+    QemuMutexLockFunc f = atomic_read(&qemu_mutex_lock_func);
+
+    g_assert(!cpu_mutex_locked(cpu));
+    set_bit(cpu->cpu_index + 1, cpu_lock_bitmap);
+    f(&cpu->lock, file, line);
+#endif
+}
+
+void cpu_mutex_unlock_impl(CPUState *cpu, const char *file, int line)
+{
+    g_assert(cpu_mutex_locked(cpu));
+    qemu_mutex_unlock_impl(&cpu->lock, file, line);
+    clear_bit(cpu->cpu_index + 1, cpu_lock_bitmap);
+}
+
+bool cpu_mutex_locked(const CPUState *cpu)
+{
+    return test_bit(cpu->cpu_index + 1, cpu_lock_bitmap);
+}
+
 bool cpu_is_stopped(CPUState *cpu)
 {
     return cpu->stopped || !runstate_is_running();
@@ -92,9 +133,9 @@ static inline bool cpu_work_list_empty(CPUState *cpu)
 {
     bool ret;
 
-    qemu_mutex_lock(&cpu->lock);
+    cpu_mutex_lock(cpu);
     ret = QSIMPLEQ_EMPTY(&cpu->work_list);
-    qemu_mutex_unlock(&cpu->lock);
+    cpu_mutex_unlock(cpu);
     return ret;
 }
 
@@ -1855,6 +1896,9 @@ void qemu_mutex_lock_iothread_impl(const char *file, int line)
 {
     QemuMutexLockFunc bql_lock = atomic_read(&qemu_bql_mutex_lock_func);
 
+    /* prevent deadlock with CPU mutex */
+    g_assert(no_cpu_mutex_locked());
+
     g_assert(!qemu_mutex_iothread_locked());
     bql_lock(&qemu_global_mutex, file, line);
     iothread_locked = true;
diff --git a/stubs/cpu-lock.c b/stubs/cpu-lock.c
new file mode 100644
index 0000000000..3f07d3a28b
--- /dev/null
+++ b/stubs/cpu-lock.c
@@ -0,0 +1,28 @@
+#include "qemu/osdep.h"
+#include "qom/cpu.h"
+
+void cpu_mutex_lock_impl(CPUState *cpu, const char *file, int line)
+{
+/* coverity gets confused by the indirect function call */
+#ifdef __COVERITY__
+    qemu_mutex_lock_impl(&cpu->lock, file, line);
+#else
+    QemuMutexLockFunc f = atomic_read(&qemu_mutex_lock_func);
+    f(&cpu->lock, file, line);
+#endif
+}
+
+void cpu_mutex_unlock_impl(CPUState *cpu, const char *file, int line)
+{
+    qemu_mutex_unlock_impl(&cpu->lock, file, line);
+}
+
+bool cpu_mutex_locked(const CPUState *cpu)
+{
+    return true;
+}
+
+bool no_cpu_mutex_locked(void)
+{
+    return true;
+}
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 5dd0aeeec6..49f83cf7ff 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -8,6 +8,7 @@ stub-obj-y += blockdev-close-all-bdrv-states.o
 stub-obj-y += clock-warp.o
 stub-obj-y += cpu-get-clock.o
 stub-obj-y += cpu-get-icount.o
+stub-obj-y += cpu-lock.o
 stub-obj-y += dump.o
 stub-obj-y += error-printf.o
 stub-obj-y += fdset.o
-- 
2.17.1

  parent reply	other threads:[~2018-12-13  5:05 UTC|newest]

Thread overview: 82+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-13  5:03 [Qemu-devel] [PATCH v5 00/73] per-CPU locks Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 01/73] cpu: convert queued work to a QSIMPLEQ Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 02/73] cpu: rename cpu->work_mutex to cpu->lock Emilio G. Cota
2018-12-13  5:03 ` Emilio G. Cota [this message]
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 04/73] cpu: make qemu_work_cond per-cpu Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 05/73] cpu: move run_on_cpu to cpus-common Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 06/73] cpu: introduce process_queued_cpu_work_locked Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 07/73] cpu: make per-CPU locks an alias of the BQL in TCG rr mode Emilio G. Cota
2018-12-15  1:51   ` Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 08/73] tcg-runtime: define helper_cpu_halted_set Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 09/73] ppc: convert to helper_cpu_halted_set Emilio G. Cota
2018-12-15  9:00   ` David Gibson
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 10/73] cris: " Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 11/73] hppa: " Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 12/73] m68k: " Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 13/73] alpha: " Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 14/73] microblaze: " Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 15/73] cpu: define cpu_halted helpers Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 16/73] tcg-runtime: convert to cpu_halted_set Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 17/73] arm: convert to cpu_halted Emilio G. Cota
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 18/73] ppc: " Emilio G. Cota
2018-12-15  9:02   ` David Gibson
2018-12-13  5:03 ` [Qemu-devel] [PATCH v5 19/73] sh4: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 20/73] i386: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 21/73] lm32: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 22/73] m68k: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 23/73] mips: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 24/73] riscv: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 25/73] s390x: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 26/73] sparc: " Emilio G. Cota
2018-12-17 12:53   ` Mark Cave-Ayland
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 27/73] xtensa: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 28/73] gdbstub: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 29/73] openrisc: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 30/73] cpu-exec: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 31/73] cpu: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 32/73] cpu: define cpu_interrupt_request helpers Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 33/73] ppc: use cpu_reset_interrupt Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 34/73] exec: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 35/73] i386: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 36/73] s390x: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 37/73] openrisc: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 38/73] arm: convert to cpu_interrupt_request Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 39/73] i386: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 40/73] i386/kvm: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 41/73] i386/hax-all: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 42/73] i386/whpx-all: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 43/73] i386/hvf: convert to cpu_request_interrupt Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 44/73] ppc: convert to cpu_interrupt_request Emilio G. Cota
2018-12-15  9:06   ` David Gibson
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 45/73] sh4: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 46/73] cris: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 47/73] hppa: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 48/73] lm32: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 49/73] m68k: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 50/73] mips: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 51/73] nios: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 52/73] s390x: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 53/73] alpha: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 54/73] moxie: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 55/73] sparc: " Emilio G. Cota
2018-12-17 12:57   ` Mark Cave-Ayland
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 56/73] openrisc: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 57/73] unicore32: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 58/73] microblaze: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 59/73] accel/tcg: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 60/73] cpu: convert to interrupt_request Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 61/73] cpu: call .cpu_has_work with the CPU lock held Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 62/73] cpu: introduce cpu_has_work_with_iothread_lock Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 63/73] ppc: convert to cpu_has_work_with_iothread_lock Emilio G. Cota
2018-12-15  9:07   ` David Gibson
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 64/73] mips: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 65/73] s390x: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 66/73] riscv: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 67/73] sparc: " Emilio G. Cota
2018-12-17 12:58   ` Mark Cave-Ayland
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 68/73] xtensa: " Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 69/73] cpu: rename all_cpu_threads_idle to qemu_tcg_rr_all_cpu_threads_idle Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 70/73] cpu: protect CPU state with cpu->lock instead of the BQL Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 71/73] cpus-common: release BQL earlier in run_on_cpu Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 72/73] cpu: add async_run_on_cpu_no_bql Emilio G. Cota
2018-12-13  5:04 ` [Qemu-devel] [PATCH v5 73/73] cputlb: queue async flush jobs without the BQL Emilio G. Cota

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181213050453.9677-4-cota@braap.org \
    --to=cota@braap.org \
    --cc=alex.bennee@linaro.org \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.