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>
This commit is contained in:
Alex Bennée 2016-09-30 22:31:01 +01:00 committed by Paolo Bonzini
parent a890643958
commit dd1f63493a
1 changed files with 6 additions and 1 deletions

View File

@ -7476,13 +7476,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break; break;
} }
cpu_list_lock();
if (CPU_NEXT(first_cpu)) { if (CPU_NEXT(first_cpu)) {
TaskState *ts; TaskState *ts;
cpu_list_lock();
/* Remove the CPU from the list. */ /* Remove the CPU from the list. */
QTAILQ_REMOVE(&cpus, cpu, node); QTAILQ_REMOVE(&cpus, cpu, node);
cpu_list_unlock(); cpu_list_unlock();
ts = cpu->opaque; ts = cpu->opaque;
if (ts->child_tidptr) { if (ts->child_tidptr) {
put_user_u32(0, 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(); rcu_unregister_thread();
pthread_exit(NULL); pthread_exit(NULL);
} }
cpu_list_unlock();
#ifdef TARGET_GPROF #ifdef TARGET_GPROF
_mcleanup(); _mcleanup();
#endif #endif