From e5143e30fb87fbf179029387f83f98a5a9b27f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 23 Feb 2017 18:29:12 +0000 Subject: tcg: remove global exit_request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are now only two uses of the global exit_request left. The first ensures we exit the run_loop when we first start to process pending work and in the kick handler. This is just as easily done by setting the first_cpu->exit_request flag. The second use is in the round robin kick routine. The global exit_request ensured every vCPU would set its local exit_request and cause a full exit of the loop. Now the iothread isn't being held while running we can just rely on the kick handler to push us out as intended. We lightly re-factor the main vCPU thread to ensure cpu->exit_requests cause us to exit the main loop and process any IO requests that might come along. As an cpu->exit_request may legitimately get squashed while processing the EXCP_INTERRUPT exception we also check cpu->queued_work_first to ensure queued work is expedited as soon as possible. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson --- cpus.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'cpus.c') diff --git a/cpus.c b/cpus.c index 0ae8f69be5..e165d18785 100644 --- a/cpus.c +++ b/cpus.c @@ -793,7 +793,6 @@ static inline int64_t qemu_tcg_next_kick(void) static void qemu_cpu_kick_rr_cpu(void) { CPUState *cpu; - atomic_mb_set(&exit_request, 1); do { cpu = atomic_mb_read(&tcg_current_rr_cpu); if (cpu) { @@ -1316,11 +1315,11 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) start_tcg_kick_timer(); - /* process any pending work */ - atomic_mb_set(&exit_request, 1); - cpu = first_cpu; + /* process any pending work */ + cpu->exit_request = 1; + while (1) { /* Account partial waits to QEMU_CLOCK_VIRTUAL. */ qemu_account_warp_timer(); @@ -1329,7 +1328,8 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) cpu = first_cpu; } - for (; cpu != NULL && !exit_request; cpu = CPU_NEXT(cpu)) { + while (cpu && !cpu->queued_work_first && !cpu->exit_request) { + atomic_mb_set(&tcg_current_rr_cpu, cpu); qemu_clock_enable(QEMU_CLOCK_VIRTUAL, @@ -1349,12 +1349,15 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) break; } - } /* for cpu.. */ + cpu = CPU_NEXT(cpu); + } /* while (cpu && !cpu->exit_request).. */ + /* Does not need atomic_mb_set because a spurious wakeup is okay. */ atomic_set(&tcg_current_rr_cpu, NULL); - /* Pairs with smp_wmb in qemu_cpu_kick. */ - atomic_mb_set(&exit_request, 0); + if (cpu && cpu->exit_request) { + atomic_mb_set(&cpu->exit_request, 0); + } handle_icount_deadline(); -- cgit v1.2.1