[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v4 12/12] tcg: Make tb_flush() thread safe
From: |
Sergey Fedorov |
Subject: |
[Qemu-devel] [PATCH v4 12/12] tcg: Make tb_flush() thread safe |
Date: |
Fri, 15 Jul 2016 21:57:26 +0300 |
From: Sergey Fedorov <address@hidden>
Use async_safe_run_on_cpu() to make tb_flush() thread safe.
It can happen that multiple threads schedule a safe work to flush the
translation buffer. To keep statistics and debugging output sane, always
check if the translation buffer has already been flushed.
Signed-off-by: Sergey Fedorov <address@hidden>
Signed-off-by: Sergey Fedorov <address@hidden>
---
Changes in v4:
- check if flush has already been done by raced CPU work
Changes in v3:
- 'tb_flushed' removed
Changes in v2:
- stale comment about unsafe tb_flush() removed
---
cpu-exec.c | 14 +-------------
include/qom/cpu.h | 2 --
translate-all.c | 17 +++++++++++------
3 files changed, 12 insertions(+), 21 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index b840e1d2dd41..0b7614ffcc9b 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -203,20 +203,16 @@ static void cpu_exec_nocache(CPUState *cpu, int
max_cycles,
TranslationBlock *orig_tb, bool ignore_icount)
{
TranslationBlock *tb;
- bool old_tb_flushed;
/* Should never happen.
We only end up here when an existing TB is too long. */
if (max_cycles > CF_COUNT_MASK)
max_cycles = CF_COUNT_MASK;
- old_tb_flushed = cpu->tb_flushed;
- cpu->tb_flushed = false;
tb = tb_gen_code(cpu, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
max_cycles | CF_NOCACHE
| (ignore_icount ? CF_IGNORE_ICOUNT : 0));
- tb->orig_tb = cpu->tb_flushed ? NULL : orig_tb;
- cpu->tb_flushed |= old_tb_flushed;
+ tb->orig_tb = orig_tb;
/* execute the generated code */
trace_exec_tb_nocache(tb, tb->pc);
cpu_tb_exec(cpu, tb);
@@ -338,13 +334,6 @@ static inline TranslationBlock *tb_find_fast(CPUState *cpu,
tb->flags != flags)) {
tb = tb_find_slow(cpu, pc, cs_base, flags);
}
- if (cpu->tb_flushed) {
- /* Ensure that no TB jump will be modified as the
- * translation buffer has been flushed.
- */
- *last_tb = NULL;
- cpu->tb_flushed = false;
- }
#ifndef CONFIG_USER_ONLY
/* We don't take care of direct jumps when address mapping changes in
* system emulation. So it's not safe to make a direct jump to a TB
@@ -619,7 +608,6 @@ int cpu_exec(CPUState *cpu)
}
last_tb = NULL; /* forget the last executed TB after exception */
- cpu->tb_flushed = false; /* reset before first TB lookup */
for(;;) {
cpu_handle_interrupt(cpu, &last_tb);
tb = tb_find_fast(cpu, &last_tb, tb_exit);
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index ab67bf2ba19f..9af4420d2bb5 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -258,7 +258,6 @@ struct qemu_work_item {
* @crash_occurred: Indicates the OS reported a crash (panic) for this CPU
* @tcg_exit_req: Set to force TCG to stop executing linked TBs for this
* CPU and return to its top level loop.
- * @tb_flushed: Indicates the translation buffer has been flushed.
* @singlestep_enabled: Flags for single-stepping.
* @icount_extra: Instructions until next timer event.
* @icount_decr: Number of cycles left, with interrupt flag in high bit.
@@ -310,7 +309,6 @@ struct CPUState {
bool unplug;
bool crash_occurred;
bool exit_request;
- bool tb_flushed;
uint32_t interrupt_request;
int singlestep_enabled;
int64_t icount_extra;
diff --git a/translate-all.c b/translate-all.c
index 0d47c1c0cf82..030273ee7b13 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -831,9 +831,11 @@ static void page_flush_tb(void)
}
/* flush all the translation blocks */
-/* XXX: tb_flush is currently not thread safe */
-void tb_flush(CPUState *cpu)
+static void do_tb_flush(CPUState *cpu, void *data)
{
+ if (tcg_ctx.tb_ctx.nb_tbs == 0) {
+ return;
+ }
#if defined(DEBUG_FLUSH)
printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
(unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer),
@@ -849,7 +851,6 @@ void tb_flush(CPUState *cpu)
CPU_FOREACH(cpu) {
memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache));
- cpu->tb_flushed = true;
}
qht_reset_size(&tcg_ctx.tb_ctx.htable, CODE_GEN_HTABLE_SIZE);
@@ -861,6 +862,11 @@ void tb_flush(CPUState *cpu)
tcg_ctx.tb_ctx.tb_flush_count++;
}
+void tb_flush(CPUState *cpu)
+{
+ async_safe_run_on_cpu(cpu, do_tb_flush, NULL);
+}
+
#ifdef DEBUG_TB_CHECK
static void
@@ -1163,9 +1169,8 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
buffer_overflow:
/* flush must be done */
tb_flush(cpu);
- /* cannot fail at this point */
- tb = tb_alloc(pc);
- assert(tb != NULL);
+ mmap_unlock();
+ cpu_loop_exit(cpu);
}
gen_code_buf = tcg_ctx.code_gen_ptr;
--
2.9.1
- [Qemu-devel] [PATCH v4 00/12] cpu-exec: Safe work in quiescent state, Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 01/12] atomic: introduce atomic_dec_fetch., Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 11/12] cpu-exec-common: Introduce async_safe_run_on_cpu(), Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 10/12] bsd-user: Support CPU work queue, Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 05/12] cpus: Rename flush_queued_work(), Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 06/12] linux-user: Use QemuMutex and QemuCond, Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 02/12] cpus: pass CPUState to run_on_cpu helpers, Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 08/12] linux-user: Add qemu_cpu_is_self() and qemu_cpu_kick(), Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 03/12] cpus: Move common code out of {async_, }run_on_cpu(), Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 12/12] tcg: Make tb_flush() thread safe,
Sergey Fedorov <=
- [Qemu-devel] [PATCH v4 04/12] cpus: Wrap mutex used to protect CPU work, Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 07/12] linux-user: Rework exclusive operation mechanism, Sergey Fedorov, 2016/07/15
- [Qemu-devel] [PATCH v4 09/12] linux-user: Support CPU work queue, Sergey Fedorov, 2016/07/15