diff options
-rw-r--r-- | accel/tcg/cpu-exec.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 4318441e4c..61297f8f4a 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -233,6 +233,8 @@ void cpu_exec_step_atomic(CPUState *cpu) uint32_t flags; uint32_t cflags = 1; uint32_t cf_mask = cflags & CF_HASH_MASK; + /* volatile because we modify it between setjmp and longjmp */ + volatile bool in_exclusive_region = false; if (sigsetjmp(cpu->jmp_env, 0) == 0) { tb = tb_lookup__cpu_state(cpu, &pc, &cs_base, &flags, cf_mask); @@ -251,14 +253,12 @@ void cpu_exec_step_atomic(CPUState *cpu) /* Since we got here, we know that parallel_cpus must be true. */ parallel_cpus = false; + in_exclusive_region = true; cc->cpu_exec_enter(cpu); /* execute the generated code */ trace_exec_tb(tb, pc); cpu_tb_exec(cpu, tb); cc->cpu_exec_exit(cpu); - parallel_cpus = true; - - end_exclusive(); } else { /* We may have exited due to another problem here, so we need * to reset any tb_locks we may have taken but didn't release. @@ -270,6 +270,15 @@ void cpu_exec_step_atomic(CPUState *cpu) #endif tb_lock_reset(); } + + if (in_exclusive_region) { + /* We might longjump out of either the codegen or the + * execution, so must make sure we only end the exclusive + * region if we started it. + */ + parallel_cpus = true; + end_exclusive(); + } } struct tb_desc { |