bsd-user: Implement interlock for atomic operations

Implement the internlock in fork_start() and fork_end() to properly cope
with atomic operations and to safely keep state for parent and child
processes.

Signed-off-by: Stacey Son <sson@FreeBSD.org>
Signed-off-by: Warner Losh <imp@bsdimp.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Warner Losh 2021-08-07 14:22:34 -06:00 committed by Warner Losh
parent f0f7f9dca9
commit 63cca1067a
1 changed files with 24 additions and 0 deletions

View File

@ -69,15 +69,39 @@ unsigned long target_dflssiz = TARGET_DFLSSIZ; /* initial data size limit */
unsigned long target_maxssiz = TARGET_MAXSSIZ; /* max stack size */
unsigned long target_sgrowsiz = TARGET_SGROWSIZ; /* amount to grow stack */
/* Helper routines for implementing atomic operations. */
void fork_start(void)
{
start_exclusive();
cpu_list_lock();
mmap_fork_start();
}
void fork_end(int child)
{
if (child) {
CPUState *cpu, *next_cpu;
/*
* Child processes created by fork() only have a single thread. Discard
* information about the parent threads.
*/
CPU_FOREACH_SAFE(cpu, next_cpu) {
if (cpu != thread_cpu) {
QTAILQ_REMOVE_RCU(&cpus, cpu, node);
}
}
mmap_fork_end(child);
/*
* qemu_init_cpu_list() takes care of reinitializing the exclusive
* state, so we don't need to end_exclusive() here.
*/
qemu_init_cpu_list();
gdbserver_fork(thread_cpu);
} else {
mmap_fork_end(child);
cpu_list_unlock();
end_exclusive();
}
}