Hello, Greg Thank you for your comments, it is true that ARM had fork(), however this was not the real fork():
arch/arm/src/common/gnu/fork.S and arm_fork.c are the entry point. They take a snapshot of the registers of the caller, allocate the child, copy the used part of the stack, and start the child. However, in the generic layer, libs/libc/unistd/lib_fork.c: fork() calls up_fork(). vfork() calls the same up_fork(), and then calls waitpid(). sched/task/task_fork.c: nxtask_setup_fork() calls addrenv_join(parent, child). That is the same call that pthread_create() uses. The child joins the address environment of the parent. up_create_stack() then gives the child its own stack. This is not fork(), and also not vfork(). It is vfork()-with-a-private-stack. Not POSIX. The failure is silent, programs that calls POSIX fork() compiled and ran, and the writes of the child went into the variables of the parent. #19562 changed only the generic layer. up_fork() now takes a bool that says which primitive the caller used, and nxtask_setup_fork() uses it to choose between addrenv_join() and a new addrenv_fork(). arm_fork.c does the same work as before and receives the flag. I agree that the documentation was inconsistent, and I would like to fix it. Documentation/guides/fork_vfork_migration.rst is new in that patch and describes the two primitives. If you tell me which page you read, I will correct it. Two follow-up patches are open, one for each architecture that restores POSIX fork(): #19772 for Xtensa, tested on real hardware, and #19773 for ARM64, a draft because I have only tested it under QEMU. ARM 32-bit is next. Please tell me if I have misread anything. Best Regards, Marco Casaroli On Mon, Aug 10, 2026 at 4:25 PM Gregory Nutt <[email protected]> wrote: > There are ARM-specific implementations of fork. But I don't know a lot > about these: > > arch/arm/src/common/Make.defs:CMN_ASRCS += fork.S > arch/arm/src/common/gnu/fork.S > arch/arm/src/common/iar/fork.S > arch/arm/src/common/arm_fork.c > Arch/arm/src/common/arm_fork.h > > I think some of documentation is incorrect. There is architecture > independent description here: > > Include/nuttx/sched.h > libs/libc/unistd/lib_fork.c: > Sched/task/task_fork.c > > ________________________________ > From: Marco C. <[email protected]> > Sent: Monday, August 10, 2026 5:01 AM > To: [email protected] <[email protected]> > Subject: Re: Please test vfork(). PR #19562 divides fork() and vfork(). > > Hello Nathan, > > Architectures with no MMU cannot implement fork(). So they will only have > vfork(). > > The PR descriptions guides through what to do if you use fork() today: > > to run a program -> use vfork() + exec*() or better yet posix_spawn() > second flow that share the caller memory -> pthread_create() > real independent copy of the process (needs MMU) -> wait for the follow up > PRs > > Let me know if you have any questions. > > Marco Casaroli > > > On Mon, Aug 10, 2026 at 1:58 PM Nathan Hartman <[email protected]> > wrote: > > > What should architectures that don't have a MMU do? > > > > On Mon, Aug 10, 2026 at 7:42 AM Marco C. <[email protected]> > wrote: > > > > > Hello, > > > > > > https://github.com/apache/nuttx/pull/19562 > > > > > > Currently, in NuttX, fork() and vfork() do the same thing. The child > > shares > > > .data, .bss and the heap with the parent. The child also runs at the > same > > > time as the parent. This is the behaviour of vfork(), not of fork(). > > > > > > A program that uses POSIX fork() compiles and runs. But the child > writes > > > into the variables of the parent. There is no error message. > > > > > > This pull request gives each function its own behaviour. It is a > breaking > > > change. It removes fork() from all architectures. unistd.h no longer > > > declares fork(), so a call to fork() now fails to build. Each > > architecture > > > can add fork() again later, with the correct behaviour (which requires > > > MMU). This is step 1 of the plan in issue #19540. > > > > > > vfork() keeps its behaviour. These architectures now have vfork(): ARM > > > 32-bit, ARM64, RISC-V and x86_64 in all build modes; SIM, but not on > > > Windows; MIPS32. The kernel builds of ARM 32-bit, ARM64 and x86_64 are > > new. > > > > > > Please test vfork() on your board. CI builds this branch, but CI does > not > > > run vfork() on hardware. This patch changes the address environments, > the > > > stack setup and the register context of each architecture. I tested 24 > > > configurations with QEMU and two on real hardware. > > > > > > Do these steps: > > > > > > 1. Get this branch and apache/nuttx-apps#3685. > > > 2. Build your configuration. > > > 3. Run ostest. > > > > > > The vfork() test is the first test. It writes this line: > > > > > > vfork_test: Child 5 ran and exited before the parent resumed > > > > > > Send the target, the build mode and this line. A report of a failure is > > as > > > useful as a report of a pass. Comments on the semantics are also > welcome. > > > > > > Thank you, > > > Marco Casaroli > > > > > >
