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:
parent
a890643958
commit
dd1f63493a
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue