summaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorAlex Bennée <alex.bennee@linaro.org>2016-09-30 22:31:01 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2016-10-04 10:00:26 +0200
commitdd1f63493adbbb06fa16ed15f8fc16584f55ee81 (patch)
tree79780c3a96716ede1fbd974bcc8e74916eb380f7 /linux-user
parenta890643958f03aaa344290700093b280cb606c28 (diff)
downloadqemu-dd1f63493adbbb06fa16ed15f8fc16584f55ee81.tar.gz
linux-user/syscall: extend lock around cpu-list
There is a potential race if several threads exit at once. To serialise the exits extend the lock above the initial checking of the CPU list. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20160930213106.20186-11-alex.bennee@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/syscall.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0815f30965..fa559be47f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7476,13 +7476,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
}
+ cpu_list_lock();
+
if (CPU_NEXT(first_cpu)) {
TaskState *ts;
- cpu_list_lock();
/* Remove the CPU from the list. */
QTAILQ_REMOVE(&cpus, cpu, node);
+
cpu_list_unlock();
+
ts = cpu->opaque;
if (ts->child_tidptr) {
put_user_u32(0, ts->child_tidptr);
@@ -7495,6 +7498,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
rcu_unregister_thread();
pthread_exit(NULL);
}
+
+ cpu_list_unlock();
#ifdef TARGET_GPROF
_mcleanup();
#endif