aboutsummaryrefslogtreecommitdiff
path: root/cpus-common.c
diff options
context:
space:
mode:
authorIlya Leoshkevich <iii@linux.ibm.com>2023-02-14 15:08:27 +0100
committerRichard Henderson <richard.henderson@linaro.org>2023-02-21 08:44:13 -1000
commitdf8a688032280ecd07ace7c6fbc70f5650cca9af (patch)
tree1bd5deeda135d8a288d0c822e6619425831b120f /cpus-common.c
parent7de0816f699553514016f52a76e26d1c2ae14034 (diff)
downloadqemu-df8a688032280ecd07ace7c6fbc70f5650cca9af.zip
qemu-df8a688032280ecd07ace7c6fbc70f5650cca9af.tar.gz
qemu-df8a688032280ecd07ace7c6fbc70f5650cca9af.tar.bz2
cpus: Make {start,end}_exclusive() recursive
Currently dying to one of the core_dump_signal()s deadlocks, because dump_core_and_abort() calls start_exclusive() two times: first via stop_all_tasks(), and then via preexit_cleanup() -> qemu_plugin_user_exit(). There are a number of ways to solve this: resume after dumping core; check cpu_in_exclusive_context() in qemu_plugin_user_exit(); or make {start,end}_exclusive() recursive. Pick the last option, since it's the most straightforward one. Fixes: da91c1920242 ("linux-user: Clean up when exiting due to a signal") Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Message-Id: <20230214140829.45392-3-iii@linux.ibm.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'cpus-common.c')
-rw-r--r--cpus-common.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/cpus-common.c b/cpus-common.c
index 793364d..39f355d 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -192,6 +192,11 @@ void start_exclusive(void)
CPUState *other_cpu;
int running_cpus;
+ if (current_cpu->exclusive_context_count) {
+ current_cpu->exclusive_context_count++;
+ return;
+ }
+
qemu_mutex_lock(&qemu_cpu_list_lock);
exclusive_idle();
@@ -219,13 +224,16 @@ void start_exclusive(void)
*/
qemu_mutex_unlock(&qemu_cpu_list_lock);
- current_cpu->in_exclusive_context = true;
+ current_cpu->exclusive_context_count = 1;
}
/* Finish an exclusive operation. */
void end_exclusive(void)
{
- current_cpu->in_exclusive_context = false;
+ current_cpu->exclusive_context_count--;
+ if (current_cpu->exclusive_context_count) {
+ return;
+ }
qemu_mutex_lock(&qemu_cpu_list_lock);
qatomic_set(&pending_cpus, 0);