Commit graph

29 commits

Author SHA1 Message Date
Marco Casaroli
70c2ef5911 !sched/arch/libc: Give fork() and vfork() their real, separate semantics.
NuttX implemented fork() and vfork() as the same function.  Both were libc
wrappers around a single up_fork() syscall; vfork() differed only by a
trailing waitpid().  Underneath, the child joined the parent's address
environment -- the same addrenv_join() that pthread_create() uses -- and got
a private copy of the stack.  So the child shared .data, .bss and the heap
with its parent and ran concurrently with it.

That is not fork().  It is vfork()-with-a-private-stack under fork()'s name,
and the history says so: today's fork() is NuttX's old vfork(), renamed in
c33d1c9c97 (2023) without any change of behaviour.  The failure was silent --
a program written against POSIX fork() compiled, ran, and had its child's
writes land in the parent's variables.

Separate them into two primitives, chosen by which function the caller
called rather than by what the hardware happens to be:

  fork()   child gets its own copy of the parent's memory at the same
           virtual addresses; runs concurrently.  Only where an address
           environment can be duplicated -- elsewhere it is not declared at
           all, so calling it is a build error naming the function.
  vfork()  child shares the parent's memory; parent suspended until the
           child _exit()s or exec()s.  Implementable everywhere.

Below libc there is still one syscall.  up_fork() gains a bool saying which
primitive the caller used, since the per-architecture register snapshot is
the same for both, and passes it to nxtask_setup_fork(), which is the single
place the memory semantics are decided.  The argument arrives in the first
argument register and is never touched:  each architecture's snapshot takes
some other call-clobbered register for its scratch, so the flag is simply
still there when the C worker is called.

The vfork() parent suspension moves out of libc into nxtask_start_fork(),
released from nxsched_release_tcb() by nxtask_resume_vfork().  Two things
follow: the parent is resumed at exec(), since exec_swap() has already handed
the child's pid to the loaded program by the time the vfork stub exits, and
vfork() no longer depends on CONFIG_SCHED_WAITPID.

Releasing there requires one fix in nxtask_exit().  It raises rtcb->lockcount
directly rather than through sched_lock() while it tears the TCB down, so the
nxsem_post() that wakes the vfork() parent leaves it queued where a blocked
task collects while pre-emption is off -- g_pendingtasks, or g_readytorun on
SMP -- and the matching raw lockcount-- does not publish it the way
sched_unlock() would, leaving the parent stranded with nothing to move it on.
The fix mirrors sched_unlock() for each case:  nxsched_merge_pending(), or
nxsched_deliver_task() under CONFIG_SMP.  Both are no-ops while pre-emption is
still disabled, and up_exit() re-reads this_task() afterwards, so a change of
the ready-to-run head is honoured.  Without it vfork() deadlocks wherever no
other task happens to call sched_unlock() afterwards -- rv-virt:nsh64 and
rv-virt:pnsh64, where NSH is blocked in waitpid() holding the lock, and
qemu-armv8a:citest_smp, which hangs the moment the vfork() test runs.

fork() is built on a new addrenv_fork(), backed by an up_addrenv_fork() hook
that duplicates an address environment into freshly allocated pages mapped at
the same virtual addresses -- unlike up_addrenv_clone(), which copies only
the representation and leaves both pointing at the same page tables.  The
child then adopts the parent's stack geometry rather than being given a
relocated copy: a pointer to a stack local taken before fork() must name the
same object in the child that it named in the parent, and the parent's stack
is already in the duplicate, with its contents, at the parent's address.

No architecture implements up_addrenv_fork() yet, so this commit leaves
fork() unavailable everywhere.  That is the intended state.  It withdraws
fork() from ARCH_ARM, flat ARCH_ARM64, ARCH_RISCV, ARCH_SIM and ARCH_X86_64,
where until now it named the sharing primitive; per-architecture patches
restore it, with POSIX semantics, as up_addrenv_fork() lands.  In the
meantime the sharing primitive is still there under the name that describes
it: vfork() for a child that runs a program, pthread_create() for a second
flow of control that shares memory, posix_spawn() for both at once.

Kconfig: ARCH_HAVE_VFORK inherits ARCH_HAVE_FORK's select lines, conditions
included, so no configuration gains machinery; ARCH_HAVE_FORK is redefined to
mean "can provide POSIX fork() semantics" and now depends on ARCH_ADDRENV.

There is one deliberate departure from "verbatim".  ARCH_ARM selected the
fork family unconditionally, BUILD_KERNEL included, and that has never
worked:  on a kernel build the architecture's fork entry point sees the
kernel's return address and stack pointer rather than the caller's, so the
child resumes at a kernel address.  On qemu-armv7a:knsh master faults in
ostest's fork case with "Child did not run" and then a data abort; without
the condition this change faults the same way through vfork().  ARCH_ARM64
and ARCH_X86_64 already carried "if !BUILD_KERNEL" for exactly this reason --
ARM was the outlier.  Conditioning it turns a runtime fault into an honest
absence, which is the whole point of the change; arch/arm takes the condition
off again in the patch that adds its saved-syscall-frame path.  Only the
MMU-capable ARM ports are affected, since Cortex-M cannot build BUILD_KERNEL
at all.

Also fixes two latent syntax errors found on the way: a missing comma in
riscv_fork.c and mips_fork.c, both in *_FRAMEPOINTER && !SAVE_GP branches
that are never compiled today.

BREAKING CHANGE: fork() is withdrawn from every architecture.  It is no
longer declared in unistd.h, so code that calls it fails to build with an error
naming the function, and the sharing behaviour it used to have is gone rather
than renamed.  CONFIG_ARCH_HAVE_FORK no longer means "fork() exists"; it means
"this configuration can provide POSIX fork() semantics", and no architecture
selects it yet.

Quick fix, chosen by why the call was made:

  to run a program                vfork() + exec*(), or better posix_spawn()
  a second flow of control that   pthread_create()
  shares the caller's memory
  a genuinely independent copy    keep fork(), and wait for the per-arch patch
  of the process                  that implements up_addrenv_fork() and selects
                                  CONFIG_ARCH_HAVE_FORK

Out-of-tree code that tests CONFIG_ARCH_HAVE_FORK to decide whether a
fork-then-exec path is available wants CONFIG_ARCH_HAVE_VFORK instead, which is
selected in exactly the places CONFIG_ARCH_HAVE_FORK used to be.  The full
migration guide is Documentation/guides/fork_vfork_migration.rst.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-08-10 08:57:30 -03:00
Lwazi Dube
784035a3e9 arch/mips/jz4780: Add support for L2 cache operations
The common mips_cache.S only handles generic L1 cache operations and
does not support L2 (secondary) cache operations required for the
JZ4780 target.

This commit introduces mti_cache.S to support both L1 and L2 cache
operations.

The mti_cache.S implementation is BSD licensed from Imagination
Technologies.

Signed-off-by: Lwazi Dube <lwazeh@gmail.com>
2026-07-21 16:40:08 +08:00
Lwazi Dube
e593ba35a4 arch/mips: Add basic support for MIPS Creator CI20 board
This commit introduces a rudimentary architecture and board port for the
MIPS Creator CI20, featuring the dual core Ingenic JZ4780 SoC (MIPS32).

Included in this initial implementation:
- Basic architectural initialization and startup code for the JZ4780 Core 0.
- Minimal configuration required to execute from RAM.
- Early UART/serial console support for basic debugging and NSH output.
- Minimal board-specific configuration for the CI20 target.
- Console output is routed via UART0 on the expansion header.

This establishes basic support for running NuttX on the MIPS CI20.
Further peripherals, optimization, and extended documentation are left for
future iterations or community contributions.

Build and Runtime Deployment Info:
----------------------------------

The baseline can be configured, compiled using the MIPS MTI toolchain,
and loaded via U-Boot using the following commands (replace
<tftp_dir> with your local TFTP root directory).

./tools/configure.sh -l ci20/nsh
  make CROSSDEV=mips-mti-elf-
  mkimage -A mips -O linux -T kernel -C none -a 0x80000180 -e 0x800004ac \
    -n "nx" -d nuttx.bin <tftp_dir>/nuttx.umg

Note: U-Boot must be properly configured for networking (e.g., valid ipaddr,
serverip, and ethaddr environment variables) to fetch the image over TFTP.

Run this from U-Boot prompt:
  tftp nuttx.umg && bootm $fileaddr

Signed-off-by: Lwazi Dube <lwazeh@gmail.com>
2026-07-15 08:02:55 -03:00
guoshichao
c33d1c9c97 sched/task/fork: add fork implementation
1. as we can use fork to implement vfork, so we rename the vfork to
fork, and use the fork method as the base to implement vfork method
2. create the vfork function as a libc function based on fork
function

Signed-off-by: guoshichao <guoshichao@xiaomi.com>
2023-07-12 02:27:37 +08:00
Petro Karashchenko
51a2db6ffc Kconfig: improve uniformity
Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
2021-12-14 07:32:48 -06:00
jordi
f3af6edf93 Kconfig: add quotes in source to clean warnings from setconfig
To avoid the setconfig warning "style: quotes recommended around xxx in
source xxx"
2021-07-23 02:32:19 -07:00
liuhaitao
d5c6bfe6cf arch: Add custom arch chip build support
Just like custom board build support, add custom arch chip build
support.

Change-Id: I71c87e6b2195501a1b1d728b71d7cbe344951057
Signed-off-by: liuhaitao <liuhaitao@xiaomi.com>
2020-10-20 14:48:16 +08:00
Ouss4
90043390ff arch/mips/: Fix architectures' references in Kconfigs and Toolchain.defs. 2020-02-10 12:40:41 -06:00
Ouss4
0dc1dc605d arch/mips: When a CPU implements an External Interrupt Controller,
use the IPL bits to control masking interrupts.
2020-02-10 12:40:41 -06:00
Gregory Nutt
fb926e7283 Fix references to the no-longer-existent misc/ directory in comments, README files, and documentation 2015-06-28 08:08:57 -06:00
Gregory Nutt
ee84648f96 PIC32MZ: Add an option to use the MIPS32 or the microMIPS ISA 2015-02-28 08:22:37 -06:00
Gregory Nutt
cfd139e8af PIC32MZ: Make sure that the microMIPS ISA is selected on all common MIPS32 assembly files when the PIC21MZ is selected 2015-02-23 12:09:34 -06:00
Gregory Nutt
9c9fc13b6c MIPS: Add some build support for the M14K and also for the PIC32MZ Starter Kit. Still a long way to go 2015-02-22 13:45:59 -06:00
Gregory Nutt
024a5cb278 PIC32MZ: Add just enough PIC32MZ logic that we can run 'make menuconfig' 2015-02-22 10:53:24 -06:00
Gregory Nutt
60d2547cd7 Move selection for CONFIG_SERIAL_TERMIOS out of MCU Kconfigs to common drivers/serial/Kconfig. Add CONFIG_ARCH_HAVE_SERIAL_TERMIOS to indicate if an MCU supports TERMIOS 2014-10-27 11:31:16 -06:00
Gregory Nutt
f53f269a84 Kconfigs: Interrupt prioritization should not be automatically selected 2013-12-20 08:42:54 -06:00
patacongo
c254d0bb3e Add an NSH configuration for the NuTiny-SDK-NUC120. Still does not work
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5678 42af7a65-404d-4744-a932-0658087f49c3
2013-02-26 21:53:12 +00:00
patacongo
ee2be652aa Implement vfork() for the MIPS32 architecture
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5520 42af7a65-404d-4744-a932-0658087f49c3
2013-01-15 15:40:18 +00:00
patacongo
74a42b5f39 Configre configs/ubw32/ostest to use kconfig-frontends
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5518 42af7a65-404d-4744-a932-0658087f49c3
2013-01-14 22:06:19 +00:00
patacongo
9b1ea99dec All ZNEO configurations converted to use the mconf/Kconfig tool
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5401 42af7a65-404d-4744-a932-0658087f49c3
2012-11-29 18:44:02 +00:00
patacongo
4f469e6316 Reconfigured Shenzhou to use JTAG. Misc Kconfig changes
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5118 42af7a65-404d-4744-a932-0658087f49c3
2012-09-09 15:43:18 +00:00
patacongo
06edc9b16b Kconfig: Standardize board LED and button configurations
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5112 42af7a65-404d-4744-a932-0658087f49c3
2012-09-08 03:31:46 +00:00
patacongo
0f4f0d72af LPC17xx Kconfig looks good
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5099 42af7a65-404d-4744-a932-0658087f49c3
2012-09-05 21:36:03 +00:00
patacongo
95ec4c3991 Auto-configuration updates from Richard Cochran
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5032 42af7a65-404d-4744-a932-0658087f49c3
2012-08-17 14:07:48 +00:00
patacongo
868fc6e118 More Kconfig stuff
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4636 42af7a65-404d-4744-a932-0658087f49c3
2012-04-19 22:51:42 +00:00
patacongo
5804060da5 More Kconfig stuff
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4628 42af7a65-404d-4744-a932-0658087f49c3
2012-04-17 22:54:31 +00:00
patacongo
f566645ab9 More Kconfig files
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4624 42af7a65-404d-4744-a932-0658087f49c3
2012-04-17 13:48:39 +00:00
patacongo
3635befa76 Add kconfig documentation
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4567 42af7a65-404d-4744-a932-0658087f49c3
2012-04-06 16:45:52 +00:00
patacongo
d79a3b09f4 Adding skeleton Kconfig files (part 1 of 2)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4564 42af7a65-404d-4744-a932-0658087f49c3
2012-04-06 15:49:35 +00:00