[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH v3 16/30] cpus: only take BQL for sleeping threa
From: |
Pavel Dovgalyuk |
Subject: |
[Qemu-devel] [RFC PATCH v3 16/30] cpus: only take BQL for sleeping threads |
Date: |
Thu, 11 Jan 2018 11:26:26 +0300 |
User-agent: |
StGit/0.17.1-dirty |
From: Alex Bennée <address@hidden>
Now the only real need to hold the BQL is for when we sleep on the
cpu->halt conditional. The lock is actually dropped while the thread
sleeps so the actual window for contention is pretty small. This also
means we can remove the special case hack for exclusive work and
simply declare that work no longer has an implicit BQL held. This
isn't a major problem async work is generally only changing things in
the context of its own vCPU. If it needs to work across vCPUs it
should be using the exclusive mechanism or possibly taking the lock
itself.
Signed-off-by: Alex Bennée <address@hidden>
Tested-by: Pavel Dovgalyuk <address@hidden>
---
cpus-common.c | 13 +++++--------
cpus.c | 10 ++++------
2 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/cpus-common.c b/cpus-common.c
index 59f751e..64661c3 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -310,6 +310,11 @@ void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func
func,
queue_work_on_cpu(cpu, wi);
}
+/* Work items run outside of the BQL. This is essential for avoiding a
+ * deadlock for exclusive work but also applies to non-exclusive work.
+ * If the work requires cross-vCPU changes then it should use the
+ * exclusive mechanism.
+ */
void process_queued_cpu_work(CPUState *cpu)
{
struct qemu_work_item *wi;
@@ -327,17 +332,9 @@ void process_queued_cpu_work(CPUState *cpu)
}
qemu_mutex_unlock(&cpu->work_mutex);
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);
}
diff --git a/cpus.c b/cpus.c
index 82dcbf8..79dda49 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1149,31 +1149,29 @@ static bool qemu_tcg_should_sleep(CPUState *cpu)
static void qemu_tcg_wait_io_event(CPUState *cpu)
{
- qemu_mutex_lock_iothread();
while (qemu_tcg_should_sleep(cpu)) {
+ qemu_mutex_lock_iothread();
stop_tcg_kick_timer();
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
+ qemu_mutex_unlock_iothread();
}
start_tcg_kick_timer();
qemu_wait_io_event_common(cpu);
-
- qemu_mutex_unlock_iothread();
}
static void qemu_kvm_wait_io_event(CPUState *cpu)
{
- qemu_mutex_lock_iothread();
while (cpu_thread_is_idle(cpu)) {
+ qemu_mutex_lock_iothread();
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
+ qemu_mutex_unlock_iothread();
}
qemu_wait_io_event_common(cpu);
-
- qemu_mutex_unlock_iothread();
}
static void qemu_hvf_wait_io_event(CPUState *cpu)
- [Qemu-devel] [RFC PATCH v3 07/30] replay: fix processing async events, (continued)
- [Qemu-devel] [RFC PATCH v3 07/30] replay: fix processing async events, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 08/30] replay: fixed replay_enable_events, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 09/30] replay: fix save/load vm for non-empty queue, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 10/30] replay: added replay log format description, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 11/30] replay: make safe vmstop at record/replay, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 12/30] replay: save prior value of the host clock, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 13/30] icount: fixed saving/restoring of icount warp timers, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 14/30] target/arm/arm-powertctl: drop BQL assertions, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 15/30] cpus: push BQL lock to qemu_*_wait_io_event, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 16/30] cpus: only take BQL for sleeping threads,
Pavel Dovgalyuk <=
- [Qemu-devel] [RFC PATCH v3 17/30] replay/replay.c: bump REPLAY_VERSION again, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 18/30] replay/replay-internal.c: track holding of replay_lock, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 19/30] replay: make locking visible outside replay code, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 20/30] replay: push replay_mutex_lock up the call tree, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 21/30] replay: don't destroy mutex at exit, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 22/30] replay: check return values of fwrite, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 23/30] replay: avoid recursive call of checkpoints, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 24/30] scripts/qemu-gdb: add simple tcg lock status helper, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 25/30] util/qemu-thread-*: add qemu_lock, locked and unlock trace events, Pavel Dovgalyuk, 2018/01/11
- [Qemu-devel] [RFC PATCH v3 26/30] scripts/analyse-locks-simpletrace.py: script to analyse lock times, Pavel Dovgalyuk, 2018/01/11