clone (nr 56)
Linux Signature
long clone(unsigned long flags, void *child_stack, int *ptid, int *ctid, unsigned long tls);
Description
Creates a new process. ostoo supports the specific flag combination used by musl’s posix_spawn: CLONE_VM | CLONE_VFORK | SIGCHLD (0x4111). The child shares the parent’s address space and the parent blocks until the child calls execve or _exit.
Current Implementation
Only the flag combination CLONE_VM | CLONE_VFORK | SIGCHLD is accepted. Other flag combinations return -ENOSYS.
- Validate arguments:
child_stackmust be non-zero. Unsupported flags return-ENOSYS. - Read parent state: Copies
pml4_phys,cwd,fd_table(Arc clones),brk_*,mmap_*from the parent process. - Capture user registers: Reads
user_rip,user_rflags, anduser_r9fromPerCpuData(saved by the SYSCALL entry stub). These are needed so the child can “return from syscall” at the same instruction as the parent. - Create child process: New PID, same
pml4_physas parent (CLONE_VM), inherited fd table and cwd. Setsvfork_parent_threadto the parent’s scheduler thread index. - Spawn clone thread: Creates a scheduler thread via
spawn_clone_threadthat entersclone_trampoline. The trampoline sets up kernel state and drops to ring 3 atuser_ripwithRAX=0(child return value) andR9=user_r9(musl’s__clonefn pointer). - Block parent: Calls
block_current_thread()(CLONE_VFORK semantics). The parent is unblocked when the child callsexecveor_exit. - Return: After unblocking, returns the child’s PID to the parent.
Source: osl/src/clone.rs — sys_clone, libkernel/src/task/scheduler.rs — spawn_clone_thread, clone_trampoline
Usage from C (musl)
Not called directly — musl’s posix_spawn uses it internally:
#include <spawn.h>
#include <sys/wait.h>
pid_t child;
int err = posix_spawn(&child, "/hello", NULL, NULL, argv, envp);
if (err == 0) {
int status;
waitpid(child, &status, 0);
}
Errors
| Errno | Condition |
|---|---|
-ENOSYS (-38) | Unsupported flag combination |
-EINVAL (-22) | child_stack is NULL |
Design Notes
- musl’s
__cloneassembly stores the child function pointer in R9 beforesyscall. The entry stub saves R9 toPerCpuData.user_r9(offset 32), andclone_trampolinerestores it viajump_to_userspace(rax=0, r9=user_r9). - The child shares the parent’s PML4 (CLONE_VM). After
execve, the child gets a fresh PML4. The old shared PML4 continues to be used by the parent.